@deepcitation/deepcitation-js 1.1.49 → 1.1.51

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.
Files changed (70) hide show
  1. package/README.md +73 -157
  2. package/lib/chunk-2HINOG74.js +3 -0
  3. package/lib/chunk-2HINOG74.js.map +1 -0
  4. package/lib/chunk-4UWAUWYL.cjs +3 -0
  5. package/lib/chunk-4UWAUWYL.cjs.map +1 -0
  6. package/lib/chunk-5XGN7UAV.js +2 -0
  7. package/lib/chunk-5XGN7UAV.js.map +1 -0
  8. package/lib/chunk-7TORYXU4.cjs +3 -0
  9. package/lib/chunk-7TORYXU4.cjs.map +1 -0
  10. package/lib/chunk-BDSA6VGC.js +125 -0
  11. package/lib/chunk-BDSA6VGC.js.map +1 -0
  12. package/lib/chunk-BEYJEW3Y.js +2 -0
  13. package/lib/chunk-BEYJEW3Y.js.map +1 -0
  14. package/lib/chunk-BWQLFMTV.js +2 -0
  15. package/lib/chunk-BWQLFMTV.js.map +1 -0
  16. package/lib/{chunk-F2MMVEVC.cjs → chunk-BYLIBOAU.cjs} +2 -1
  17. package/lib/chunk-BYLIBOAU.cjs.map +1 -0
  18. package/lib/chunk-DS6SOU4L.cjs +2 -0
  19. package/lib/chunk-DS6SOU4L.cjs.map +1 -0
  20. package/lib/{chunk-UUR2SQKU.cjs → chunk-HL3AXCDL.cjs} +2 -1
  21. package/lib/chunk-HL3AXCDL.cjs.map +1 -0
  22. package/lib/chunk-N7FTXSGM.js +3 -0
  23. package/lib/chunk-N7FTXSGM.js.map +1 -0
  24. package/lib/chunk-WS4CQVDI.cjs +125 -0
  25. package/lib/chunk-WS4CQVDI.cjs.map +1 -0
  26. package/lib/client/index.cjs +2 -1
  27. package/lib/client/index.cjs.map +1 -0
  28. package/lib/client/index.d.cts +58 -13
  29. package/lib/client/index.d.ts +58 -13
  30. package/lib/client/index.js +2 -1
  31. package/lib/client/index.js.map +1 -0
  32. package/lib/{index-fvVBZYVK.d.ts → index-BHjI8Bh1.d.cts} +61 -22
  33. package/lib/{index-fvVBZYVK.d.cts → index-BHjI8Bh1.d.ts} +61 -22
  34. package/lib/index.cjs +2 -1
  35. package/lib/index.cjs.map +1 -0
  36. package/lib/index.d.cts +137 -16
  37. package/lib/index.d.ts +137 -16
  38. package/lib/index.js +2 -1
  39. package/lib/index.js.map +1 -0
  40. package/lib/prompts/index.cjs +2 -1
  41. package/lib/prompts/index.cjs.map +1 -0
  42. package/lib/prompts/index.d.cts +177 -55
  43. package/lib/prompts/index.d.ts +177 -55
  44. package/lib/prompts/index.js +2 -1
  45. package/lib/prompts/index.js.map +1 -0
  46. package/lib/react/index.cjs +8 -5
  47. package/lib/react/index.cjs.map +1 -0
  48. package/lib/react/index.d.cts +348 -21
  49. package/lib/react/index.d.ts +348 -21
  50. package/lib/react/index.js +8 -5
  51. package/lib/react/index.js.map +1 -0
  52. package/lib/styles.css +1 -1
  53. package/lib/types/index.cjs +2 -1
  54. package/lib/types/index.cjs.map +1 -0
  55. package/lib/types/index.d.cts +1 -1
  56. package/lib/types/index.d.ts +1 -1
  57. package/lib/types/index.js +2 -1
  58. package/lib/types/index.js.map +1 -0
  59. package/lib/{utils-q6anRKO_.d.cts → utils-CCi9_JTv.d.cts} +5 -5
  60. package/lib/{utils-DuacFTtu.d.ts → utils-CoSP-i76.d.ts} +5 -5
  61. package/package.json +165 -152
  62. package/src/tailwind.css +5 -5
  63. package/lib/chunk-2PRW5PVT.cjs +0 -2
  64. package/lib/chunk-3XSZLKJW.js +0 -2
  65. package/lib/chunk-D2TKEF6D.cjs +0 -2
  66. package/lib/chunk-DHVODVIA.cjs +0 -71
  67. package/lib/chunk-HRCAI3NV.js +0 -1
  68. package/lib/chunk-ND6LFDGK.js +0 -71
  69. package/lib/chunk-O2XFH626.js +0 -1
  70. package/lib/chunk-PKXMJNRX.js +0 -2
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/icons.tsx","../../src/react/UrlCitationComponent.tsx","../../src/react/Popover.tsx","../../src/utils/diff.ts","../../src/react/useSmartDiff.ts","../../src/react/CitationOverlayContext.tsx","../../src/react/SplitDiffDisplay.tsx","../../src/react/VerificationLog.tsx","../../src/react/CitationComponent.tsx","../../src/react/SourcesListComponent.tsx","../../src/react/CitationDrawer.tsx","../../src/react/PrefetchedPopoverImage.tsx","../../src/react/VerificationTabs.tsx"],"names":["DeepCitationIcon","className","jsxs","jsx","MissIcon","CheckIcon","WarningIcon","SpinnerIcon","LinkIcon","ExternalLinkIcon","CloseIcon","LockIcon","extractDomain","url","truncateString","str","maxLength","getUrlPath","urlObj","path","STATUS_ICONS","isBlockedStatus","status","isErrorStatus","isAccessibleStatus","isRedirectedStatus","isVerifiedStatus","PendingDot","VerifiedCheck","StatusIconWrapper","children","classNames","DefaultFavicon","faviconUrl","isBroken","domain","src","e","UrlCitationComponent","forwardRef","urlMeta","providedCitation","variant","showFullUrlOnHover","showFavicon","showTitle","maxDisplayLength","renderBlockedIndicator","onUrlClick","eventHandlers","preventTooltips","ref","providedDomain","title","fetchStatus","errorMessage","citation","useMemo","citationKey","generateCitationKey","citationInstanceId","generateCitationInstanceId","displayText","pathPart","statusInfo","isBlocked","isError","isVerified","isPartial","isPending","handleClick","useCallback","handleMouseEnter","handleMouseLeave","renderStatusIndicator","Fragment","MemoizedUrlCitationComponent","memo","useUrlMeta","additionalMeta","urlDisplayUtils","cn","classes","Popover","PopoverTrigger","PopoverContent","Et","align","sideOffset","props","computeDiff","oldTokens","newTokens","equals","b","oldLen","newLen","commonPrefixLen","commonSuffixLen","oldMiddle","newMiddle","middleDiff","myersDiff","result","mergeConsecutiveChanges","maxD","v","trace","outer","d","k","x","y","backtrack","changes","prevK","prevX","prevY","change","last","splitLines","text","lines","lineStart","i","EXTENDED_WORD_CHARS","TOKENIZE_REGEX","tokenizeWords","longestCommonPrefix","a","longestCommonSuffix","dedupeWhitespaceInChangeObjects","deletion","insertion","wsPrefix","delWithoutPrefix","insWithoutPrefix","wsSuffix","cleanedDel","cleanedIns","prev","leadingWs","trailingWs","overlap","next","prevTrailingWs","nextLeadingWs","diffLines","oldStr","newStr","oldLines","newLines","diffWordsWithSpace","oldWords","newWords","diff","useSmartDiff","expected","actual","cleanExpected","cleanActual","lineDiffs","processedDiffs","hasDiff","totalChange","part","nextPart","wordDiffs","similarity","CitationOverlayContext","createContext","CitationOverlayProvider","overlayCount","setOverlayCount","useState","registerOverlay","c","unregisterOverlay","value","useCitationOverlay","context","useContext","useHasCitationOverlayProvider","getContextualStatusMessage","expectedPage","actualPage","calculateSimilarity","maxLen","matrix","j","highlightSubstring","substring","highlightClass","index","before","match","after","MatchQualityBar","percentage","fillColor","CollapsibleText","anchorText","anchorTextClass","isExpanded","setIsExpanded","shouldCollapse","content","SplitView","maxCollapsedLength","anchorTextExpected","anchorTextFound","showMatchQuality","SplitDiffDisplay","label","sanitize","mode","providedSimilarity","sanitizedExpected","clean","sanitizedActual","effectiveMode","MAX_QUOTE_BOX_LENGTH","MAX_ANCHOR_TEXT_PREVIEW_LENGTH","MAX_TIMELINE_HEIGHT","MAX_PHRASE_DISPLAY_LENGTH","ICON_COLOR_CLASSES","METHOD_DISPLAY_NAMES","getStatusColorScheme","getStatusHeaderText","getMethodDisplayName","method","PageBadge","foundPage","hasExpected","hasFound","pageToShow","StatusHeader","compact","fullPhrase","colorScheme","headerText","IconComponent","displayAnchorText","displayPhrase","QuoteBox","phrase","VerificationLogSummary","searchAttempts","onToggle","totalCount","successCount","SearchAttemptRow","attempt","locationText","methodName","indexWidth","variations","RejectedMatchesSection","rejectedMatches","AuditSearchDisplay","seen","matches","fallbackPhrases","p","VerificationLogAttempt","isSuccess","showLocationDetail","VerificationLogTimeline","showAuditDisplay","lineKey","key","VerificationLog","expectedLine","foundLine","controlledIsExpanded","onExpandChange","internalIsExpanded","setInternalIsExpanded","expanded","successfulAttempt","derivedFoundPage","derivedFoundLine","AttemptingToVerify","Activity","React","POPOVER_WIDTH","POPOVER_MAX_WIDTH","CitationErrorBoundary","error","errorInfo","getDefaultContent","stripBrackets","getDisplayText","fallbackDisplay","raw","getStatusLabel","getTrustLevel","matchedVariation","isLowTrustMatch","getStatusFromVerification","verification","isMiss","hasLowTrustMatch","isPartialMatch","ImageOverlay","alt","onClose","useEffect","handleKeyDown","createPortal","VerifiedIndicator","PartialIndicator","PendingIndicator","MissIndicator","getKeySpanBoundingBox","boxes","minX","minY","maxX","maxY","box","AnchorTextFocusedImage","onImageClick","maxWidth","maxHeight","containerRef","useRef","imageRef","hasInitializedScrollRef","anchorTextBox","handleImageLoad","container","image","imageDimensions","originalWidth","originalHeight","scaleX","scaleY","anchorTextCenterX","anchorTextCenterY","scrollX","scrollY","getHumanizingMessage","MAX_ANCHOR_LENGTH","safeAnchorText","DefaultPopoverContent","isLoading","isPhrasesExpanded","onPhrasesExpandChange","isVisible","hasImage","searchStatus","hasAnchorTextPosition","showVerificationLog","isCleanSuccess","humanizingMessage","searchingPhrase","statusLabel","hasSnippet","pageNumber","CitationComponent","contentProp","behaviorConfig","isMobile","renderIndicator","renderContent","popoverPosition","renderPopoverContent","additionalCount","showIndicator","isAnyOverlayOpen","resolvedContent","isHovering","setIsHovering","expandedImageSrc","setExpandedImageSrc","setIsPhrasesExpanded","wasPopoverOpenBeforeTap","SPINNER_TIMEOUT_MS","spinnerTimedOut","setSpinnerTimedOut","spinnerTimeoutRef","hasDefinitiveResult","shouldShowSpinner","getBehaviorContext","applyBehaviorActions","actions","HOVER_CLOSE_DELAY_MS","hoverCloseTimeoutRef","isOverPopoverRef","cancelHoverCloseTimeout","handlePopoverMouseEnter","handlePopoverMouseLeave","handleTouchStart","handleTouchEnd","statusClasses","renderCitationContent","chipStatusClasses","supStatusClasses","minimalStatusClasses","faviconSrc","isVerifiedState","isPartialState","isMissState","isPendingState","linterStyles","linterClasses","shouldShowPopover","imageOverlay","triggerProps","popoverContentElement","MemoizedCitationComponent","getFaviconUrl","customFaviconUrl","detectSourceType","getPlatformName","platformMap","name","ChevronRightIcon","SourcesListItem","id","sourceType","citationNumbers","verificationStatus","onClick","showVerificationIndicator","showCitationBadges","renderFavicon","platformName","favicon","detectedType","renderVerificationBadge","config","num","SourcesTrigger","sources","maxIcons","isOpen","displaySources","hasMore","source","SourcesListComponent","onOpenChange","header","emptyMessage","listClassName","onSourceClick","showVerificationIndicators","groupByDomain","renderItem","renderEmpty","renderLoading","mounted","setMounted","groupedSources","groups","handleClose","handleBackdropClick","renderHeader","showCloseButton","showCount","customRender","renderListContent","domainSources","maxHeightStyle","portalContent","MemoizedSourcesListItem","MemoizedSourcesTrigger","MemoizedSourcesListComponent","sourceCitationsToListItems","citations","sourceMap","existing","useSourcesList","initialSources","setSources","setIsOpen","addSource","s","removeSource","clearSources","groupCitationsBySource","item","groupKey","items","firstCitation","getStatusInfo","CitationDrawerItemComponent","isLast","onReadMore","sourceName","articleTitle","snippet","handleReadMore","CitationDrawer","citationGroups","showMoreSection","maxVisibleItems","onCitationClick","position","renderCitationItem","showMore","setShowMore","allCitations","group","visibleCitations","moreCitations","drawerContent","useCitationDrawer","setCitations","openDrawer","closeDrawer","toggleDrawer","addCitation","removeCitation","clearCitations","setCitationsList","PrefetchedPopoverImage","imageStyle","MemoizedPrefetchedPopoverImage","usePrefetchImage","resolve","reject","img","prefetchImages","srcs","promises","TabButton","isActive","ModeToggle","onModeChange","VerificationTabs","renderCopyButton","emptyText","verifiedKeySpan","defaultMode","diffResult","isHighVariance","activeTab","setActiveTab","diffMode","setDiffMode","statusMessage","renderFoundContent","block"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * DeepCitation icon SVG (no dependencies)\n * Default size is 1em (inherits font size). Use className to override.\n */\nexport const DeepCitationIcon = ({ className }: { className?: string }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"square\"\n shapeRendering=\"crispEdges\"\n className={className}\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M7 3 L3 3 L3 21 L7 21\" />\n <path d=\"M17 3 L21 3 L21 21 L17 21\" />\n </svg>\n);\n\n/**\n * Miss/fail indicator - horizontal line (dash)\n * Semantically indicates \"not found\" without implying \"close/delete\"\n * Size is controlled by parent container - use size-4 or similar on wrapper\n */\nexport const MissIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <line x1=\"6\" y1=\"12\" x2=\"18\" y2=\"12\" />\n </svg>\n);\n\n/**\n * Check icon SVG (no dependencies)\n * Size is controlled by parent container - use size-4 or similar on wrapper\n */\nexport const CheckIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n);\n\n/**\n * Warning icon SVG (no dependencies)\n * Size is controlled by parent container - use size-4 or similar on wrapper\n */\nexport const WarningIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <path d=\"M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,88a12,12,0,1,1,12-12A12,12,0,0,1,128,192Z\" />\n </svg>\n);\n\n/**\n * Spinner component for loading/pending state\n * Size is controlled by parent container - use size-4 or similar on wrapper\n * Animation (animate-spin) should be applied to the wrapper\n */\nexport const SpinnerIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n width=\"100%\"\n height=\"100%\"\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n style={{ opacity: 0.25 }}\n />\n <path\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n style={{ opacity: 0.75 }}\n />\n </svg>\n);\n\n/**\n * Link/chain icon for inline URL citations (Gemini-style)\n * Size is controlled by parent container - use size-3 or similar on wrapper\n */\nexport const LinkIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n);\n\n/**\n * External link icon for opening URLs\n * Size is controlled by parent container\n */\nexport const ExternalLinkIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n);\n\n/**\n * Close/X icon\n * Size is controlled by parent container\n */\nexport const CloseIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\n/**\n * Lock icon for restricted/paywall content\n * Size is controlled by parent container\n */\nexport const LockIcon = ({ className }: { className?: string }) => (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n width=\"100%\"\n height=\"100%\"\n >\n <path d=\"M12 2a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2h-1V7a5 5 0 0 0-5-5zm3 8H9V7a3 3 0 0 1 6 0v3z\" />\n </svg>\n);\n","import React, { forwardRef, memo, useCallback, useMemo } from \"react\";\nimport type { Citation } from \"../types/citation.js\";\nimport type { UrlCitationMeta, UrlCitationProps, UrlFetchStatus } from \"./types.js\";\nimport { classNames, generateCitationInstanceId, generateCitationKey } from \"./utils.js\";\nimport { CheckIcon, CloseIcon, LockIcon } from \"./icons.js\";\n\n/**\n * Extracts domain from URL for compact display.\n */\nexport function extractDomain(url: string): string {\n try {\n const urlObj = new URL(url);\n return urlObj.hostname.replace(/^www\\./, \"\");\n } catch {\n // Fallback for invalid URLs\n return url.replace(/^https?:\\/\\/(www\\.)?/, \"\").split(\"/\")[0];\n }\n}\n\n/**\n * Truncates a string to max length with ellipsis.\n */\nfunction truncateString(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - 1) + \"…\";\n}\n\n/**\n * Get path from URL for display.\n */\nfunction getUrlPath(url: string): string {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname + urlObj.search;\n return path === \"/\" ? \"\" : path;\n } catch {\n return \"\";\n }\n}\n\n/**\n * Status indicator icons for URL fetch states.\n */\nconst STATUS_ICONS: Record<UrlFetchStatus, { icon: string; label: string; className: string }> = {\n verified: { icon: \"✓\", label: \"Verified\", className: \"text-green-600 dark:text-green-500\" },\n partial: { icon: \"~\", label: \"Partial match\", className: \"text-amber-600 dark:text-amber-500\" },\n pending: { icon: \"…\", label: \"Verifying\", className: \"text-gray-400 dark:text-gray-500\" },\n accessible: { icon: \"○\", label: \"Accessible\", className: \"text-blue-500 dark:text-blue-400\" },\n redirected: { icon: \"↪\", label: \"Redirected\", className: \"text-amber-600 dark:text-amber-500\" },\n redirected_valid: { icon: \"↪✓\", label: \"Redirected (valid)\", className: \"text-green-600 dark:text-green-500\" },\n blocked_antibot: { icon: \"⊘\", label: \"Blocked by anti-bot\", className: \"text-amber-600 dark:text-amber-500\" },\n blocked_login: { icon: \"⊙\", label: \"Login required\", className: \"text-amber-600 dark:text-amber-500\" },\n blocked_paywall: { icon: \"$\", label: \"Paywall\", className: \"text-amber-600 dark:text-amber-500\" },\n blocked_geo: { icon: \"⊕\", label: \"Geo-restricted\", className: \"text-amber-600 dark:text-amber-500\" },\n blocked_rate_limit: { icon: \"◔\", label: \"Rate limited\", className: \"text-amber-600 dark:text-amber-500\" },\n error_timeout: { icon: \"◷\", label: \"Timed out\", className: \"text-red-500 dark:text-red-400\" },\n error_not_found: { icon: \"404\", label: \"Not found\", className: \"text-red-500 dark:text-red-400\" },\n error_server: { icon: \"⚠\", label: \"Server error\", className: \"text-red-500 dark:text-red-400\" },\n error_network: { icon: \"↯\", label: \"Network error\", className: \"text-red-500 dark:text-red-400\" },\n unknown: { icon: \"?\", label: \"Unknown status\", className: \"text-gray-400 dark:text-gray-500\" },\n};\n\n/**\n * Checks if status is a blocked status.\n */\nexport function isBlockedStatus(status: UrlFetchStatus): boolean {\n return status.startsWith(\"blocked_\");\n}\n\n/**\n * Checks if status is an error status.\n */\nexport function isErrorStatus(status: UrlFetchStatus): boolean {\n return status.startsWith(\"error_\");\n}\n\n/**\n * Checks if status indicates the URL is accessible (may not have verified content yet).\n */\nexport function isAccessibleStatus(status: UrlFetchStatus): boolean {\n return status === \"verified\" || status === \"partial\" || status === \"accessible\" || status === \"redirected_valid\";\n}\n\n/**\n * Checks if status indicates a redirect occurred.\n */\nexport function isRedirectedStatus(status: UrlFetchStatus): boolean {\n return status === \"redirected\" || status === \"redirected_valid\";\n}\n\n/**\n * Checks if URL was successfully verified.\n */\nexport function isVerifiedStatus(status: UrlFetchStatus): boolean {\n return status === \"verified\" || status === \"partial\" || status === \"redirected_valid\";\n}\n\n/**\n * Pulsing dot indicator for pending state.\n */\nconst PendingDot = () => (\n <span\n className=\"w-1.5 h-1.5 rounded-full bg-gray-400 dark:bg-gray-500 animate-pulse\"\n aria-hidden=\"true\"\n />\n);\n\n/**\n * Green verified checkmark indicator.\n */\nconst VerifiedCheck = () => (\n <CheckIcon className=\"w-full h-full text-green-600 dark:text-green-500\" />\n);\n\n/**\n * Status icon wrapper for consistent sizing and alignment.\n */\nconst StatusIconWrapper = ({ children, className }: { children: React.ReactNode; className?: string }) => (\n <span\n className={classNames(\n \"w-3 h-3 flex-shrink-0 flex items-center justify-center\",\n className\n )}\n >\n {children}\n </span>\n);\n\n/**\n * Default favicon component.\n */\nconst DefaultFavicon = ({ url, faviconUrl, isBroken }: { url: string; faviconUrl?: string; isBroken?: boolean }) => {\n const domain = extractDomain(url);\n const src = faviconUrl || `https://www.google.com/s2/favicons?domain=${domain}&sz=16`;\n\n if (isBroken) {\n return (\n <span className=\"w-3.5 h-3.5 flex items-center justify-center text-xs text-gray-400 dark:text-gray-500 flex-shrink-0\">\n 🌐\n </span>\n );\n }\n\n return (\n <img\n src={src}\n alt=\"\"\n className=\"w-3.5 h-3.5 rounded-sm flex-shrink-0\"\n width={14}\n height={14}\n loading=\"lazy\"\n onError={e => {\n // Hide broken favicon images\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n );\n};\n\n/**\n * URL Citation Component\n *\n * Displays a URL citation with compact domain display,\n * verification status, and blocked/error indicators.\n *\n * @example\n * ```tsx\n * <UrlCitationComponent\n * urlMeta={{\n * url: \"https://example.com/article\",\n * fetchStatus: \"verified\",\n * }}\n * />\n * // Renders: [example.com ✓]\n *\n * <UrlCitationComponent\n * urlMeta={{\n * url: \"https://protected-site.com/page\",\n * fetchStatus: \"blocked_login\",\n * }}\n * />\n * // Renders: [protected-site.com 🔒]\n * ```\n */\nexport const UrlCitationComponent = forwardRef<HTMLSpanElement, UrlCitationProps>(\n (\n {\n urlMeta,\n citation: providedCitation,\n children,\n className,\n variant = \"badge\", // Default to badge for URLs\n showFullUrlOnHover = true,\n showFavicon = true,\n showTitle = false,\n maxDisplayLength = 30,\n renderBlockedIndicator,\n onUrlClick,\n eventHandlers,\n preventTooltips = false,\n },\n ref,\n ) => {\n const { url, domain: providedDomain, title, fetchStatus, faviconUrl, errorMessage } = urlMeta;\n\n // Derive citation from URL meta if not provided\n const citation: Citation = useMemo(\n () =>\n providedCitation || {\n value: url,\n fullPhrase: title || url,\n },\n [providedCitation, url, title],\n );\n\n const citationKey = useMemo(() => generateCitationKey(citation), [citation]);\n const citationInstanceId = useMemo(() => generateCitationInstanceId(citationKey), [citationKey]);\n\n // Compute display text\n const domain = useMemo(() => providedDomain || extractDomain(url), [providedDomain, url]);\n const path = useMemo(() => getUrlPath(url), [url]);\n\n const displayText = useMemo(() => {\n if (showTitle && title) {\n return truncateString(title, maxDisplayLength);\n }\n // Show domain + truncated path\n const pathPart = path ? truncateString(path, maxDisplayLength - domain.length - 1) : \"\";\n return pathPart ? `${domain}${pathPart}` : domain;\n }, [showTitle, title, domain, path, maxDisplayLength]);\n\n const statusInfo = STATUS_ICONS[fetchStatus];\n const isBlocked = isBlockedStatus(fetchStatus);\n const isError = isErrorStatus(fetchStatus);\n const isVerified = fetchStatus === \"verified\";\n const isPartial = fetchStatus === \"partial\";\n const isPending = fetchStatus === \"pending\";\n const isBroken = isError;\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLSpanElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (onUrlClick) {\n onUrlClick(url, e);\n } else {\n // Default: open URL in new tab\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n }\n eventHandlers?.onClick?.(citation, citationKey, e);\n },\n [onUrlClick, url, eventHandlers, citation, citationKey],\n );\n\n const handleMouseEnter = useCallback(() => {\n eventHandlers?.onMouseEnter?.(citation, citationKey);\n }, [eventHandlers, citation, citationKey]);\n\n const handleMouseLeave = useCallback(() => {\n eventHandlers?.onMouseLeave?.(citation, citationKey);\n }, [eventHandlers, citation, citationKey]);\n\n const renderStatusIndicator = () => {\n // Verified: Green checkmark\n if (isVerified) {\n return (\n <StatusIconWrapper>\n <VerifiedCheck />\n </StatusIconWrapper>\n );\n }\n\n // Partial: Amber check\n if (isPartial) {\n return (\n <StatusIconWrapper className=\"text-amber-600 dark:text-amber-500\">\n <CheckIcon className=\"w-full h-full\" />\n </StatusIconWrapper>\n );\n }\n\n // Blocked: Lock icon\n if (isBlocked) {\n if (renderBlockedIndicator) {\n return renderBlockedIndicator(fetchStatus, errorMessage);\n }\n return (\n <StatusIconWrapper className=\"text-amber-600 dark:text-amber-500\" aria-label={statusInfo.label}>\n <LockIcon className=\"w-full h-full\" />\n </StatusIconWrapper>\n );\n }\n\n // Error: X icon\n if (isError) {\n if (renderBlockedIndicator) {\n return renderBlockedIndicator(fetchStatus, errorMessage);\n }\n return (\n <StatusIconWrapper className=\"text-red-500 dark:text-red-400\" aria-label={statusInfo.label}>\n <CloseIcon className=\"w-full h-full\" />\n </StatusIconWrapper>\n );\n }\n\n // Pending: Pulsing dot\n if (isPending) {\n return (\n <StatusIconWrapper>\n <PendingDot />\n </StatusIconWrapper>\n );\n }\n\n return null;\n };\n\n // Badge variant (default) - matches the HTML design\n if (variant === \"badge\") {\n return (\n <>\n {children}\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={url}\n data-citation-id={citationKey}\n data-citation-instance={citationInstanceId}\n data-url={url}\n data-fetch-status={fetchStatus}\n data-variant=\"badge\"\n className={classNames(\n // Base styles matching the HTML design\n \"inline-flex items-center gap-2 px-2 py-1\",\n \"bg-white dark:bg-gray-900\",\n \"border border-gray-200 dark:border-gray-700\",\n \"rounded-md\",\n \"text-gray-800 dark:text-gray-200\",\n \"no-underline cursor-pointer\",\n \"transition-all duration-150 ease-in-out\",\n \"hover:border-gray-400 dark:hover:border-gray-500\",\n \"hover:bg-gray-50 dark:hover:bg-gray-800\",\n // Broken state: muted styling\n isBroken && \"opacity-60\",\n className\n )}\n title={showFullUrlOnHover ? (errorMessage || url) : undefined}\n onMouseEnter={preventTooltips ? undefined : handleMouseEnter}\n onMouseLeave={preventTooltips ? undefined : handleMouseLeave}\n onClick={e => {\n e.preventDefault();\n handleClick(e as unknown as React.MouseEvent<HTMLSpanElement>);\n }}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`Link to ${domain}: ${statusInfo.label}`}\n >\n {showFavicon && <DefaultFavicon url={url} faviconUrl={faviconUrl} isBroken={isBroken} />}\n <span\n className={classNames(\n \"font-mono text-[11px] font-medium whitespace-nowrap overflow-hidden text-ellipsis max-w-[140px]\",\n \"text-gray-800 dark:text-gray-200\",\n isBroken && \"line-through\"\n )}\n >\n {displayText}\n </span>\n {renderStatusIndicator()}\n </a>\n </>\n );\n }\n\n // Chip variant - pill style with neutral colors\n if (variant === \"chip\") {\n return (\n <>\n {children}\n <span\n ref={ref}\n data-citation-id={citationKey}\n data-citation-instance={citationInstanceId}\n data-url={url}\n data-fetch-status={fetchStatus}\n data-variant=\"chip\"\n className={classNames(\n \"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-sm cursor-pointer transition-colors no-underline mr-0.5\",\n \"bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300\",\n \"hover:bg-gray-200 dark:hover:bg-gray-700\",\n isBroken && \"opacity-60\",\n className\n )}\n title={showFullUrlOnHover ? url : undefined}\n onMouseEnter={preventTooltips ? undefined : handleMouseEnter}\n onMouseLeave={preventTooltips ? undefined : handleMouseLeave}\n onMouseDown={handleClick}\n onClick={e => e.stopPropagation()}\n role=\"link\"\n aria-label={`Link to ${domain}: ${statusInfo.label}`}\n >\n {showFavicon && <DefaultFavicon url={url} faviconUrl={faviconUrl} />}\n <span className=\"max-w-[200px] overflow-hidden text-ellipsis whitespace-nowrap text-gray-700 dark:text-gray-300\">{displayText}</span>\n {renderStatusIndicator()}\n </span>\n </>\n );\n }\n\n // Inline variant - neutral underline style with spacing\n if (variant === \"inline\") {\n return (\n <>\n {children}\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={url}\n data-citation-id={citationKey}\n data-citation-instance={citationInstanceId}\n data-fetch-status={fetchStatus}\n data-variant=\"inline\"\n className={classNames(\n \"inline-flex items-center gap-1 cursor-pointer transition-colors no-underline border-b border-dotted mr-0.5\",\n \"text-gray-700 dark:text-gray-300 border-gray-400 dark:border-gray-500\",\n \"hover:border-gray-600 dark:hover:border-gray-300\",\n isBroken && \"opacity-60 line-through\",\n className\n )}\n title={showFullUrlOnHover ? url : undefined}\n onMouseEnter={preventTooltips ? undefined : handleMouseEnter}\n onMouseLeave={preventTooltips ? undefined : handleMouseLeave}\n onClick={e => {\n e.preventDefault();\n handleClick(e as unknown as React.MouseEvent<HTMLSpanElement>);\n }}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`Link to ${domain}: ${statusInfo.label}`}\n >\n {showFavicon && <DefaultFavicon url={url} faviconUrl={faviconUrl} />}\n <span>{displayText}</span>\n {renderStatusIndicator()}\n </a>\n </>\n );\n }\n\n // Bracket variant - neutral text color with brackets, spacing for inline context\n return (\n <>\n {children}\n <span\n ref={ref}\n data-citation-id={citationKey}\n data-citation-instance={citationInstanceId}\n data-url={url}\n data-fetch-status={fetchStatus}\n data-variant=\"bracket\"\n className={classNames(\n \"inline-flex items-baseline gap-0.5 whitespace-nowrap cursor-pointer transition-colors mr-0.5\",\n \"font-mono text-xs leading-tight\",\n \"text-gray-500 dark:text-gray-400\",\n isBroken && \"opacity-60\",\n className\n )}\n title={showFullUrlOnHover ? url : undefined}\n onMouseEnter={preventTooltips ? undefined : handleMouseEnter}\n onMouseLeave={preventTooltips ? undefined : handleMouseLeave}\n onMouseDown={handleClick}\n onClick={e => e.stopPropagation()}\n role=\"link\"\n aria-label={`Link to ${domain}: ${statusInfo.label}`}\n >\n [\n {showFavicon && <DefaultFavicon url={url} faviconUrl={faviconUrl} />}\n <span className={classNames(\n \"max-w-[200px] overflow-hidden text-ellipsis whitespace-nowrap\",\n isBroken && \"line-through\"\n )}>{displayText}</span>\n {renderStatusIndicator()}\n ]\n </span>\n </>\n );\n },\n);\n\nUrlCitationComponent.displayName = \"UrlCitationComponent\";\n\n/**\n * Memoized version for performance.\n */\nexport const MemoizedUrlCitationComponent = memo(UrlCitationComponent);\n\n/**\n * Hook to parse URL and create UrlCitationMeta.\n */\nexport function useUrlMeta(\n url: string,\n fetchStatus: UrlFetchStatus = \"unknown\",\n additionalMeta?: Partial<UrlCitationMeta>,\n): UrlCitationMeta {\n return useMemo(\n () => ({\n url,\n domain: extractDomain(url),\n fetchStatus,\n ...additionalMeta,\n }),\n [url, fetchStatus, additionalMeta],\n );\n}\n\n/**\n * Compact URL display utilities.\n */\nexport const urlDisplayUtils = {\n extractDomain,\n truncateString,\n getUrlPath,\n isBlockedStatus,\n isErrorStatus,\n isVerifiedStatus,\n};\n\n/**\n * Status configuration for custom styling.\n */\nexport { STATUS_ICONS };\n","/**\n * Popover component built on Radix UI primitives.\n * This is a shadcn-style component - copy/paste friendly.\n *\n * @see https://ui.shadcn.com/docs/components/popover\n * @see https://www.radix-ui.com/primitives/docs/components/popover\n */\nimport * as React from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\n\nfunction cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverPortal = PopoverPrimitive.Portal;\n\nconst PopoverContent = React.forwardRef<\n React.ComponentRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 8, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n // Base styling: fit-content dimensions, viewport-aware max for both width and height\n // Ensures popover never exceeds screen bounds, leaving room for positioning\n \"z-[9998] rounded-lg border bg-white shadow-xl outline-none\",\n \"w-fit max-w-[min(400px,calc(100vw-2rem))] max-h-[calc(100vh-4rem)]\",\n \"overflow-auto\",\n \"border-gray-200 dark:border-gray-700 dark:bg-gray-900\",\n // Animations\n \"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n \"data-[side=bottom]:slide-in-from-top-2\",\n \"data-[side=left]:slide-in-from-right-2\",\n \"data-[side=right]:slide-in-from-left-2\",\n \"data-[side=top]:slide-in-from-bottom-2\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverPortal };\n","/**\n * Custom diff implementation to replace the 'diff' npm package.\n * This avoids dependency issues in Firebase Functions environments.\n *\n * Implements a Myers diff algorithm with optimizations inspired by jsdiff.\n * @see https://github.com/kpdecker/jsdiff\n *\n * ---\n *\n * BSD 3-Clause License\n *\n * Copyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation\n * and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nexport interface Change {\n value: string;\n added?: boolean;\n removed?: boolean;\n count?: number;\n}\n\n/**\n * Myers diff algorithm with diagonal pruning optimization.\n * This reduces complexity from O(n+d²) to O(n+d) for common cases like appending text.\n *\n * @see https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/\n */\nfunction computeDiff(\n oldTokens: string[],\n newTokens: string[],\n equals: (a: string, b: string) => boolean = (a, b) => a === b,\n): Change[] {\n const oldLen = oldTokens.length;\n const newLen = newTokens.length;\n\n // Handle edge cases\n if (oldLen === 0 && newLen === 0) {\n return [];\n }\n\n // Quick path for completely new content\n if (oldLen === 0) {\n return [{ value: newTokens.join(\"\"), added: true, count: newTokens.length }];\n }\n\n // Quick path for completely removed content\n if (newLen === 0) {\n return [\n { value: oldTokens.join(\"\"), removed: true, count: oldTokens.length },\n ];\n }\n\n // Find common prefix\n let commonPrefixLen = 0;\n while (\n commonPrefixLen < oldLen &&\n commonPrefixLen < newLen &&\n equals(oldTokens[commonPrefixLen], newTokens[commonPrefixLen])\n ) {\n commonPrefixLen++;\n }\n\n // Find common suffix (but don't overlap with prefix)\n let commonSuffixLen = 0;\n while (\n commonSuffixLen < oldLen - commonPrefixLen &&\n commonSuffixLen < newLen - commonPrefixLen &&\n equals(\n oldTokens[oldLen - 1 - commonSuffixLen],\n newTokens[newLen - 1 - commonSuffixLen],\n )\n ) {\n commonSuffixLen++;\n }\n\n // Extract the differing middle portions\n const oldMiddle = oldTokens.slice(commonPrefixLen, oldLen - commonSuffixLen);\n const newMiddle = newTokens.slice(commonPrefixLen, newLen - commonSuffixLen);\n\n // If middles are empty, we only have common prefix/suffix\n if (oldMiddle.length === 0 && newMiddle.length === 0) {\n return [{ value: oldTokens.join(\"\"), count: oldTokens.length }];\n }\n\n // Compute diff on the middle portion using Myers algorithm\n const middleDiff = myersDiff(oldMiddle, newMiddle, equals);\n\n // Build result with prefix, middle diff, and suffix\n const result: Change[] = [];\n\n if (commonPrefixLen > 0) {\n result.push({\n value: oldTokens.slice(0, commonPrefixLen).join(\"\"),\n count: commonPrefixLen,\n });\n }\n\n result.push(...middleDiff);\n\n if (commonSuffixLen > 0) {\n result.push({\n value: oldTokens.slice(oldLen - commonSuffixLen).join(\"\"),\n count: commonSuffixLen,\n });\n }\n\n return mergeConsecutiveChanges(result);\n}\n\n/**\n * Myers diff algorithm implementation.\n * Uses the \"middle snake\" approach for better memory efficiency.\n */\nfunction myersDiff(\n oldTokens: string[],\n newTokens: string[],\n equals: (a: string, b: string) => boolean,\n): Change[] {\n const oldLen = oldTokens.length;\n const newLen = newTokens.length;\n const maxD = oldLen + newLen;\n\n // V array indexed by k = x - y (diagonal)\n // We use an object to handle negative indices\n const v: Record<number, number> = { 1: 0 };\n\n // Store the path for backtracking\n const trace: Array<Record<number, number>> = [];\n\n // Iterate through edit distances\n outer: for (let d = 0; d <= maxD; d++) {\n trace.push({ ...v });\n\n // Iterate through diagonals\n for (let k = -d; k <= d; k += 2) {\n // Decide whether to go down or right\n let x: number;\n if (k === -d || (k !== d && v[k - 1] < v[k + 1])) {\n x = v[k + 1]; // Move down (insert)\n } else {\n x = v[k - 1] + 1; // Move right (delete)\n }\n\n let y = x - k;\n\n // Follow diagonal (matches)\n while (x < oldLen && y < newLen && equals(oldTokens[x], newTokens[y])) {\n x++;\n y++;\n }\n\n v[k] = x;\n\n // Check if we've reached the end\n if (x >= oldLen && y >= newLen) {\n break outer;\n }\n }\n }\n\n // Backtrack to build the diff\n return backtrack(trace, oldTokens, newTokens);\n}\n\nfunction backtrack(\n trace: Array<Record<number, number>>,\n oldTokens: string[],\n newTokens: string[],\n): Change[] {\n const changes: Change[] = [];\n let x = oldTokens.length;\n let y = newTokens.length;\n\n for (let d = trace.length - 1; d >= 0; d--) {\n const v = trace[d];\n const k = x - y;\n\n let prevK: number;\n if (k === -d || (k !== d && v[k - 1] < v[k + 1])) {\n prevK = k + 1;\n } else {\n prevK = k - 1;\n }\n\n const prevX = v[prevK] ?? 0;\n const prevY = prevX - prevK;\n\n // Add diagonal matches (unchanged) - push in reverse order, will reverse at end\n while (x > prevX && y > prevY) {\n x--;\n y--;\n changes.push({ value: oldTokens[x], count: 1 });\n }\n\n if (d > 0) {\n if (x === prevX) {\n // Insertion (went down)\n y--;\n changes.push({ value: newTokens[y], added: true, count: 1 });\n } else {\n // Deletion (went right)\n x--;\n changes.push({ value: oldTokens[x], removed: true, count: 1 });\n }\n }\n }\n\n // Reverse to get correct order (we built backwards for O(n) efficiency)\n return changes.reverse();\n}\n\n/**\n * Merge consecutive changes of the same type.\n */\nfunction mergeConsecutiveChanges(changes: Change[]): Change[] {\n if (changes.length === 0) return [];\n\n const result: Change[] = [];\n\n for (const change of changes) {\n const last = result[result.length - 1];\n\n if (\n last &&\n last.added === change.added &&\n last.removed === change.removed\n ) {\n last.value += change.value;\n last.count = (last.count || 1) + (change.count || 1);\n } else {\n result.push({ ...change });\n }\n }\n\n return result;\n}\n\nfunction splitLines(text: string): string[] {\n if (!text) return [];\n\n const lines: string[] = [];\n let lineStart = 0;\n\n for (let i = 0; i < text.length; i++) {\n if (text[i] === \"\\n\") {\n // Include the newline character in the line\n lines.push(text.substring(lineStart, i + 1));\n lineStart = i + 1;\n }\n }\n\n // Don't forget the last line if it doesn't end with newline\n if (lineStart < text.length) {\n lines.push(text.substring(lineStart));\n }\n\n return lines;\n}\n\n/**\n * Extended word character class - matches jsdiff's extendedWordChars.\n * Includes: a-zA-Z0-9_, soft hyphen, Latin Extended-A/B, IPA Extensions,\n * Spacing Modifier Letters, and Latin Extended Additional.\n *\n * @see https://github.com/kpdecker/jsdiff/blob/master/src/diff/word.ts\n */\nconst EXTENDED_WORD_CHARS =\n \"a-zA-Z0-9_\\\\u00AD\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02C6\\\\u02C8-\\\\u02D7\\\\u02DE-\\\\u02FF\\\\u1E00-\\\\u1EFF\";\n\n/**\n * Tokenization regex matching jsdiff's approach.\n * Matches: word character runs, whitespace runs, or single non-word chars.\n */\nconst TOKENIZE_REGEX = new RegExp(\n `[${EXTENDED_WORD_CHARS}]+|\\\\s+|[^${EXTENDED_WORD_CHARS}]`,\n \"gu\",\n);\n\n/**\n * Split text into tokens using jsdiff's tokenization approach.\n * Each token is one of:\n * - A word (extended word characters)\n * - A whitespace run\n * - A single punctuation/symbol character\n */\nfunction tokenizeWords(text: string): string[] {\n if (!text) return [];\n return text.match(TOKENIZE_REGEX) || [];\n}\n\n/**\n * Find the longest common prefix between two strings.\n */\nfunction longestCommonPrefix(a: string, b: string): string {\n let i = 0;\n while (i < a.length && i < b.length && a[i] === b[i]) {\n i++;\n }\n return a.slice(0, i);\n}\n\n/**\n * Find the longest common suffix between two strings.\n */\nfunction longestCommonSuffix(a: string, b: string): string {\n let i = 0;\n while (\n i < a.length &&\n i < b.length &&\n a[a.length - 1 - i] === b[b.length - 1 - i]\n ) {\n i++;\n }\n return a.slice(a.length - i);\n}\n\n/**\n * Check if a string is only whitespace.\n */\nfunction isWhitespace(str: string): boolean {\n return /^\\s*$/.test(str);\n}\n\n/**\n * Deduplicate whitespace in change objects.\n * This is a simplified version of jsdiff's dedupeWhitespaceInChangeObjects.\n *\n * Handles three main scenarios:\n * 1. Deletion followed by insertion - extract common leading/trailing whitespace\n * 2. Lone insertion after unchanged - strip duplicate leading whitespace\n * 3. Lone deletion between unchanged - distribute whitespace properly\n */\nfunction dedupeWhitespaceInChangeObjects(changes: Change[]): Change[] {\n const result: Change[] = [];\n\n for (let i = 0; i < changes.length; i++) {\n const change = changes[i];\n\n // Scenario 1: Deletion followed by insertion\n if (change.removed && changes[i + 1]?.added) {\n const deletion = change;\n const insertion = changes[i + 1];\n\n // Find common prefix (must be whitespace)\n const commonPrefix = longestCommonPrefix(deletion.value, insertion.value);\n const wsPrefix = commonPrefix.match(/^\\s*/)?.[0] || \"\";\n\n // Find common suffix (must be whitespace)\n const delWithoutPrefix = deletion.value.slice(wsPrefix.length);\n const insWithoutPrefix = insertion.value.slice(wsPrefix.length);\n const commonSuffix = longestCommonSuffix(delWithoutPrefix, insWithoutPrefix);\n const wsSuffix = commonSuffix.match(/\\s*$/)?.[0] || \"\";\n\n // Build the cleaned changes\n if (wsPrefix) {\n result.push({ value: wsPrefix, count: 1 });\n }\n\n const cleanedDel = deletion.value.slice(\n wsPrefix.length,\n deletion.value.length - wsSuffix.length,\n );\n const cleanedIns = insertion.value.slice(\n wsPrefix.length,\n insertion.value.length - wsSuffix.length,\n );\n\n if (cleanedDel) {\n result.push({ value: cleanedDel, removed: true, count: 1 });\n }\n if (cleanedIns) {\n result.push({ value: cleanedIns, added: true, count: 1 });\n }\n\n if (wsSuffix) {\n result.push({ value: wsSuffix, count: 1 });\n }\n\n i++; // Skip the insertion since we processed it\n continue;\n }\n\n // Scenario 2: Lone insertion after unchanged text\n if (change.added && i > 0 && !changes[i - 1].added && !changes[i - 1].removed) {\n const prev = result[result.length - 1];\n if (prev && !prev.added && !prev.removed) {\n // Check for duplicate leading whitespace\n const leadingWs = change.value.match(/^\\s*/)?.[0] || \"\";\n const trailingWs = prev.value.match(/\\s*$/)?.[0] || \"\";\n\n if (leadingWs && trailingWs) {\n const overlap = longestCommonSuffix(trailingWs, leadingWs);\n if (overlap) {\n // Remove overlap from the insertion\n result.push({\n value: change.value.slice(overlap.length),\n added: true,\n count: 1,\n });\n continue;\n }\n }\n }\n }\n\n // Scenario 3: Lone deletion between unchanged text\n if (\n change.removed &&\n !changes[i + 1]?.added &&\n i > 0 &&\n !changes[i - 1]?.added &&\n !changes[i - 1]?.removed\n ) {\n const prev = result[result.length - 1];\n const next = changes[i + 1];\n\n if (prev && next && !next.added && !next.removed) {\n const leadingWs = change.value.match(/^\\s*/)?.[0] || \"\";\n const trailingWs = change.value.match(/\\s*$/)?.[0] || \"\";\n const prevTrailingWs = prev.value.match(/\\s*$/)?.[0] || \"\";\n const nextLeadingWs = next.value.match(/^\\s*/)?.[0] || \"\";\n\n // If deletion starts/ends with whitespace that overlaps with neighbors\n if (leadingWs && prevTrailingWs) {\n const overlap = longestCommonSuffix(prevTrailingWs, leadingWs);\n if (overlap.length === leadingWs.length) {\n // Leading whitespace is already in prev, strip it\n result.push({\n value: change.value.slice(leadingWs.length),\n removed: true,\n count: 1,\n });\n continue;\n }\n }\n\n if (trailingWs && nextLeadingWs) {\n const overlap = longestCommonPrefix(trailingWs, nextLeadingWs);\n if (overlap.length === trailingWs.length) {\n // Trailing whitespace will be in next, strip it\n result.push({\n value: change.value.slice(0, -trailingWs.length) || change.value,\n removed: true,\n count: 1,\n });\n continue;\n }\n }\n }\n }\n\n // Default: just add the change as-is\n result.push({ ...change });\n }\n\n return mergeConsecutiveChanges(result);\n}\n\n/**\n * Compare two strings line by line.\n * Similar to Diff.diffLines from the 'diff' package.\n */\nexport function diffLines(oldStr: string, newStr: string): Change[] {\n const oldLines = splitLines(oldStr);\n const newLines = splitLines(newStr);\n\n return computeDiff(oldLines, newLines);\n}\n\n/**\n * Compare two strings word by word, preserving whitespace.\n * Similar to Diff.diffWordsWithSpace from the 'diff' package.\n *\n * Features matching jsdiff:\n * - Extended Unicode word character support\n * - Proper tokenization (words, whitespace runs, single punctuation)\n * - Whitespace deduplication in consecutive changes\n */\nexport function diffWordsWithSpace(oldStr: string, newStr: string): Change[] {\n const oldWords = tokenizeWords(oldStr);\n const newWords = tokenizeWords(newStr);\n\n const diff = computeDiff(oldWords, newWords);\n return dedupeWhitespaceInChangeObjects(diff);\n}\n","import { diffLines, diffWordsWithSpace } from \"../utils/diff.js\";\nimport { useMemo } from \"react\";\n\nexport type DiffBlockType = \"modified\" | \"added\" | \"removed\" | \"unchanged\";\n\nexport interface DiffPart {\n value: string;\n added?: boolean;\n removed?: boolean;\n}\n\nexport interface DiffBlock {\n type: DiffBlockType;\n parts: DiffPart[];\n}\n\nexport const useSmartDiff = (expected: string = \"\", actual: string = \"\") => {\n return useMemo(() => {\n // 1. Sanitize standard noise (CRLF, trailing spaces)\n const cleanExpected = (expected || \"\").trim().replace(/\\r\\n/g, \"\\n\");\n const cleanActual = (actual || \"\").trim().replace(/\\r\\n/g, \"\\n\");\n\n // 2. First Pass: Diff by LINES.\n // This isolates the \"extra line\" issue. The extra line becomes one \"added\" chunk,\n // and it prevents the tokenizer from getting confused on the rest of the text.\n const lineDiffs = diffLines(cleanExpected, cleanActual);\n\n // 3. Second Pass: Process the line results to find \"Modifications\"\n const processedDiffs: DiffBlock[] = [];\n let hasDiff = false;\n let totalChange = 0;\n\n for (let i = 0; i < lineDiffs.length; i++) {\n const part = lineDiffs[i];\n const nextPart = lineDiffs[i + 1];\n\n // CHECK FOR MODIFICATION:\n // If we see a \"Removed\" block immediately followed by an \"Added\" block,\n // it means this specific line changed. We should DIFF WORDS inside this line.\n if (part.removed && nextPart && nextPart.added) {\n // Run word diff ONLY on this pair of lines\n const wordDiffs = diffWordsWithSpace(part.value, nextPart.value);\n\n processedDiffs.push({\n type: \"modified\",\n parts: wordDiffs,\n });\n\n hasDiff = true;\n // Calculate raw change amount for variance score\n totalChange += Math.abs(part.value.length - nextPart.value.length);\n\n i++; // Skip the next part since we merged it into this block\n }\n // CHECK FOR PURE ADDITION/DELETION (The \"Extra Line\" Scenario)\n else if (part.added || part.removed) {\n processedDiffs.push({\n type: part.added ? \"added\" : \"removed\",\n parts: [{ value: part.value, added: part.added, removed: part.removed }],\n });\n hasDiff = true;\n totalChange += part.value.length;\n }\n // UNCHANGED BLOCKS\n else {\n processedDiffs.push({\n type: \"unchanged\",\n parts: [{ value: part.value }],\n });\n }\n }\n\n // 4. Calculate a similarity score to decide UI defaults\n // 1.0 = Perfect match, 0.0 = Totally different\n const maxLength = Math.max(cleanExpected.length, cleanActual.length);\n const similarity = maxLength === 0 ? 1 : 1 - totalChange / maxLength;\n\n return {\n diffResult: processedDiffs,\n hasDiff,\n similarity,\n // If similarity is too low (< 60%), the Diff view is likely \"Fruit Salad\" (messy).\n // We can use this boolean to default the UI to the \"Source\" tab.\n isHighVariance: similarity < 0.6,\n };\n }, [expected, actual]);\n};\n","/**\n * CitationOverlayContext\n *\n * Manages global state for citation image overlays. When any citation has an\n * expanded image overlay, other citations should not show hover popovers.\n *\n * This context provides a robust, React-idiomatic solution that:\n * - Works with SSR (no global module state)\n * - Is reactive (components re-render when state changes)\n * - Handles multiple overlays correctly\n * - Works across different bundle chunks\n *\n * Usage:\n * 1. Wrap your app (or citation container) with <CitationOverlayProvider>\n * 2. Components use useCitationOverlay() to check/update overlay state\n *\n * If no provider is present, the hook returns a no-op implementation that\n * always allows hover (graceful degradation).\n */\nimport React, {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from \"react\";\n\ninterface CitationOverlayContextValue {\n /** Whether any citation image overlay is currently open */\n isAnyOverlayOpen: boolean;\n /** Register an overlay as open (call on mount) */\n registerOverlay: () => void;\n /** Unregister an overlay (call on unmount) */\n unregisterOverlay: () => void;\n}\n\nconst CitationOverlayContext = createContext<CitationOverlayContextValue | null>(\n null\n);\n\n/**\n * Provider component that manages overlay state for all child citations.\n *\n * Wrap your app or citation container with this provider to enable\n * proper hover blocking when image overlays are expanded.\n *\n * @example\n * ```tsx\n * <CitationOverlayProvider>\n * <YourContent>\n * <CitationComponent ... />\n * <CitationComponent ... />\n * </YourContent>\n * </CitationOverlayProvider>\n * ```\n */\nexport function CitationOverlayProvider({\n children,\n}: {\n children: React.ReactNode;\n}) {\n const [overlayCount, setOverlayCount] = useState(0);\n\n const registerOverlay = useCallback(() => {\n setOverlayCount((c) => c + 1);\n }, []);\n\n const unregisterOverlay = useCallback(() => {\n setOverlayCount((c) => Math.max(0, c - 1));\n }, []);\n\n const value = useMemo(\n () => ({\n isAnyOverlayOpen: overlayCount > 0,\n registerOverlay,\n unregisterOverlay,\n }),\n [overlayCount, registerOverlay, unregisterOverlay]\n );\n\n return (\n <CitationOverlayContext.Provider value={value}>\n {children}\n </CitationOverlayContext.Provider>\n );\n}\n\n/**\n * Hook to access citation overlay state.\n *\n * Returns context value if inside a CitationOverlayProvider,\n * otherwise returns a fallback that allows all hover (graceful degradation).\n *\n * @example\n * ```tsx\n * const { isAnyOverlayOpen, registerOverlay, unregisterOverlay } = useCitationOverlay();\n *\n * // In ImageOverlay component:\n * useEffect(() => {\n * registerOverlay();\n * return () => unregisterOverlay();\n * }, []);\n *\n * // In hover handler:\n * if (isAnyOverlayOpen) return; // Skip hover\n * ```\n */\nexport function useCitationOverlay(): CitationOverlayContextValue {\n const context = useContext(CitationOverlayContext);\n\n // Fallback for when no provider is present - allows hover, no-op register\n // This provides graceful degradation for users who don't wrap with provider\n if (!context) {\n return {\n isAnyOverlayOpen: false,\n registerOverlay: () => {},\n unregisterOverlay: () => {},\n };\n }\n\n return context;\n}\n\n/**\n * Check if the CitationOverlayProvider is present in the tree.\n * Useful for debugging or conditional behavior.\n */\nexport function useHasCitationOverlayProvider(): boolean {\n const context = useContext(CitationOverlayContext);\n return context !== null;\n}\n","import React, { memo, useState, useMemo } from \"react\";\nimport { cn } from \"./utils.js\";\nimport { CheckIcon } from \"./icons.js\";\nimport type { SearchStatus } from \"../types/search.js\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport type DiffDisplayMode = \"auto\" | \"inline\" | \"split\";\n\nexport interface SplitDiffDisplayProps {\n /** The expected/claimed text from the AI */\n expected: string;\n /** The actual text found in the source */\n actual: string;\n /** Optional label for the diff section */\n label?: string;\n /** Additional class name */\n className?: string;\n /** Sanitize function for text preprocessing */\n sanitize?: (text: string) => string;\n /** Display mode: auto (smart), inline (word diff), or split (two-row) */\n mode?: DiffDisplayMode;\n /** Show a match quality indicator bar */\n showMatchQuality?: boolean;\n /** Maximum characters before collapsing with \"Show more\" */\n maxCollapsedLength?: number;\n /** Expected anchorText to highlight within expected text */\n anchorTextExpected?: string;\n /** Found anchorText to highlight within actual text */\n anchorTextFound?: string;\n /** Verification status for contextual messages */\n status?: SearchStatus | null;\n /** Similarity score (0-1), calculated if not provided */\n similarity?: number;\n}\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\n/**\n * Get a human-readable status message for the verification status\n */\nexport function getContextualStatusMessage(\n status: SearchStatus | null | undefined,\n expectedPage?: number | null,\n actualPage?: number | null\n): string {\n if (!status) return \"\";\n\n switch (status) {\n case \"found\":\n return \"Exact match found\";\n case \"found_anchor_text_only\":\n return \"Key phrase found, full context differs\";\n case \"found_phrase_missed_anchor_text\":\n return \"Full phrase found, anchor text highlight missed\";\n case \"partial_text_found\":\n return \"Partial text match found\";\n case \"found_on_other_page\":\n if (expectedPage != null && actualPage != null) {\n return `Found on page ${actualPage} (expected page ${expectedPage})`;\n }\n return \"Found on different page\";\n case \"found_on_other_line\":\n return \"Found on different line\";\n case \"first_word_found\":\n return \"Only first word matched\";\n case \"not_found\":\n return \"Not found in source\";\n case \"pending\":\n case \"loading\":\n return \"Searching...\";\n default:\n return \"\";\n }\n}\n\n/**\n * Calculate similarity between two strings (0-1)\n */\nfunction calculateSimilarity(a: string, b: string): number {\n if (!a && !b) return 1;\n if (!a || !b) return 0;\n\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n\n // Simple Levenshtein-based similarity\n const matrix: number[][] = [];\n for (let i = 0; i <= a.length; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= b.length; j++) {\n matrix[0][j] = j;\n }\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n if (a[i - 1] === b[j - 1]) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j] + 1\n );\n }\n }\n }\n\n const distance = matrix[a.length][b.length];\n return 1 - distance / maxLen;\n}\n\n/**\n * Highlight a substring within text\n */\nfunction highlightSubstring(\n text: string,\n substring: string | undefined,\n highlightClass: string\n): React.ReactNode {\n if (!substring || !text.includes(substring)) {\n return text;\n }\n\n const index = text.indexOf(substring);\n const before = text.slice(0, index);\n const match = text.slice(index, index + substring.length);\n const after = text.slice(index + substring.length);\n\n return (\n <>\n {before}\n <span className={highlightClass}>{match}</span>\n {after}\n </>\n );\n}\n\n// =============================================================================\n// MATCH QUALITY BAR COMPONENT\n// =============================================================================\n\ninterface MatchQualityBarProps {\n similarity: number;\n className?: string;\n}\n\nconst MatchQualityBar: React.FC<MatchQualityBarProps> = memo(({ similarity, className }) => {\n const percentage = Math.round(similarity * 100);\n const fillColor =\n percentage >= 80\n ? \"bg-green-500 dark:bg-green-400\"\n : percentage >= 40\n ? \"bg-amber-500 dark:bg-amber-400\"\n : \"bg-red-500 dark:bg-red-400\";\n\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n <div className=\"flex-1 h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden\">\n <div\n className={cn(\"h-full rounded-full transition-all duration-300\", fillColor)}\n style={{ width: `${percentage}%` }}\n />\n </div>\n <span className=\"text-[10px] font-medium text-gray-500 dark:text-gray-400 tabular-nums\">\n {percentage}%\n </span>\n </div>\n );\n});\n\nMatchQualityBar.displayName = \"MatchQualityBar\";\n\n// =============================================================================\n// COLLAPSIBLE TEXT COMPONENT\n// =============================================================================\n\ninterface CollapsibleTextProps {\n text: string;\n maxLength: number;\n className?: string;\n anchorText?: string;\n anchorTextClass?: string;\n}\n\nconst CollapsibleText: React.FC<CollapsibleTextProps> = memo(({\n text,\n maxLength,\n className,\n anchorText,\n anchorTextClass = \"border-b-2 border-blue-400 dark:border-blue-500\",\n}) => {\n const [isExpanded, setIsExpanded] = useState(false);\n const shouldCollapse = text.length > maxLength;\n\n const displayText = shouldCollapse && !isExpanded\n ? text.slice(0, maxLength) + \"…\"\n : text;\n\n const content = anchorText\n ? highlightSubstring(displayText, anchorText, anchorTextClass)\n : displayText;\n\n return (\n <div className={className}>\n <span className=\"whitespace-pre-wrap break-words\">{content}</span>\n {shouldCollapse && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setIsExpanded(!isExpanded);\n }}\n className=\"ml-1 text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 text-[10px] font-medium\"\n >\n {isExpanded ? \"Show less\" : \"Show full text\"}\n </button>\n )}\n </div>\n );\n});\n\nCollapsibleText.displayName = \"CollapsibleText\";\n\n// =============================================================================\n// SPLIT VIEW COMPONENT\n// =============================================================================\n\ninterface SplitViewProps {\n expected: string;\n actual: string;\n maxCollapsedLength: number;\n anchorTextExpected?: string;\n anchorTextFound?: string;\n showMatchQuality?: boolean;\n similarity: number;\n}\n\nconst SplitView: React.FC<SplitViewProps> = memo(({\n expected,\n actual,\n maxCollapsedLength,\n anchorTextExpected,\n anchorTextFound,\n showMatchQuality,\n similarity,\n}) => {\n return (\n <div className=\"space-y-2\">\n {showMatchQuality && (\n <MatchQualityBar similarity={similarity} className=\"mb-3\" />\n )}\n\n {/* Expected row */}\n <div className=\"rounded-md overflow-hidden\">\n <div className=\"flex items-start gap-2 p-2.5 bg-red-50 dark:bg-red-900/20\">\n <span className=\"shrink-0 text-[10px] font-medium text-red-600 dark:text-red-400 uppercase tracking-wide pt-0.5\">\n Expected:\n </span>\n <CollapsibleText\n text={expected}\n maxLength={maxCollapsedLength}\n className=\"flex-1 font-mono text-[11px] text-red-700 dark:text-red-300\"\n anchorText={anchorTextExpected}\n anchorTextClass=\"bg-red-200 dark:bg-red-800/50 px-0.5 rounded\"\n />\n </div>\n </div>\n\n {/* Found row */}\n <div className=\"rounded-md overflow-hidden\">\n <div className=\"flex items-start gap-2 p-2.5 bg-green-50 dark:bg-green-900/20\">\n <span className=\"shrink-0 text-[10px] font-medium text-green-600 dark:text-green-400 uppercase tracking-wide pt-0.5 inline-flex items-center gap-1\">\n Found:\n <span className=\"size-2.5 text-green-500 dark:text-green-400\">\n <CheckIcon />\n </span>\n </span>\n {actual ? (\n <CollapsibleText\n text={actual}\n maxLength={maxCollapsedLength}\n className=\"flex-1 font-mono text-[11px] text-green-700 dark:text-green-300\"\n anchorText={anchorTextFound}\n anchorTextClass=\"bg-green-200 dark:bg-green-800/50 px-0.5 rounded\"\n />\n ) : (\n <span className=\"flex-1 font-mono text-[11px] text-gray-500 dark:text-gray-400 italic\">\n No text found\n </span>\n )}\n </div>\n </div>\n </div>\n );\n});\n\nSplitView.displayName = \"SplitView\";\n\n// =============================================================================\n// MAIN COMPONENT\n// =============================================================================\n\n/**\n * SplitDiffDisplay - Enhanced diff display with split view mode\n *\n * Features:\n * - Auto mode: intelligently chooses inline or split based on similarity\n * - Split view: clear two-row Expected/Found layout for high-variance diffs\n * - KeySpan highlighting: underlines matching portions\n * - Match quality bar: visual similarity indicator\n * - Collapsible text: truncates long text with expand option\n */\nexport const SplitDiffDisplay: React.FC<SplitDiffDisplayProps> = memo(({\n expected,\n actual,\n label,\n className,\n sanitize,\n mode = \"auto\",\n showMatchQuality = false,\n maxCollapsedLength = 200,\n anchorTextExpected,\n anchorTextFound,\n status,\n similarity: providedSimilarity,\n}) => {\n // Sanitize inputs\n const sanitizedExpected = useMemo(() => {\n const clean = (expected || \"\").trim().replace(/\\r\\n/g, \"\\n\");\n return sanitize ? sanitize(clean) : clean;\n }, [expected, sanitize]);\n\n const sanitizedActual = useMemo(() => {\n const clean = (actual || \"\").trim().replace(/\\r\\n/g, \"\\n\");\n return sanitize ? sanitize(clean) : clean;\n }, [actual, sanitize]);\n\n // Calculate similarity\n const similarity = useMemo(() => {\n if (providedSimilarity !== undefined) return providedSimilarity;\n return calculateSimilarity(sanitizedExpected, sanitizedActual);\n }, [sanitizedExpected, sanitizedActual, providedSimilarity]);\n\n // Determine effective display mode\n const effectiveMode = useMemo(() => {\n if (mode !== \"auto\") return mode;\n\n // Smart mode selection based on PRD thresholds\n if (similarity >= 0.8) return \"inline\";\n if (similarity < 0.6) return \"split\";\n\n // For status-based decisions\n if (status === \"found_anchor_text_only\" || status === \"partial_text_found\") {\n return \"split\";\n }\n\n // Default to split for moderate variance (0.6-0.8) when showing diff\n return \"split\";\n }, [mode, similarity, status]);\n\n // Check if exact match\n const isExactMatch = sanitizedExpected === sanitizedActual && sanitizedExpected.length > 0;\n\n if (isExactMatch) {\n return (\n <div data-testid=\"split-diff-display\" data-exact-match=\"true\" className={cn(\"space-y-2\", className)}>\n {label && (\n <div className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n {label}\n </div>\n )}\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 rounded-full text-sm font-medium\">\n <span className=\"size-2.5\">\n <CheckIcon />\n </span>\n <span>Exact match</span>\n </div>\n <div className=\"p-3 bg-gray-50 dark:bg-gray-800 rounded-md text-sm text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words\">\n {sanitizedActual}\n </div>\n </div>\n );\n }\n\n return (\n <div data-testid=\"split-diff-display\" data-mode={effectiveMode} className={cn(\"space-y-2\", className)}>\n {label && (\n <div className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n {label}\n </div>\n )}\n\n <SplitView\n expected={sanitizedExpected}\n actual={sanitizedActual}\n maxCollapsedLength={maxCollapsedLength}\n anchorTextExpected={anchorTextExpected}\n anchorTextFound={anchorTextFound}\n showMatchQuality={showMatchQuality}\n similarity={similarity}\n />\n </div>\n );\n});\n\nSplitDiffDisplay.displayName = \"SplitDiffDisplay\";\n\nexport { MatchQualityBar, CollapsibleText };\nexport default SplitDiffDisplay;\n","import React, { useState, useMemo } from \"react\";\nimport type { SearchAttempt, SearchStatus, SearchMethod } from \"../types/search.js\";\nimport { CheckIcon, MissIcon, SpinnerIcon } from \"./icons.js\";\nimport { cn } from \"./utils.js\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Maximum length for matched text display before truncation */\nconst MAX_MATCHED_TEXT_LENGTH = 40;\n\n/** Maximum length for quote box phrase display */\nconst MAX_QUOTE_BOX_LENGTH = 150;\n\n/** Maximum length for anchor text preview in headers */\nconst MAX_ANCHOR_TEXT_PREVIEW_LENGTH = 50;\n\n/** Maximum height for the scrollable timeline */\nconst MAX_TIMELINE_HEIGHT = \"200px\";\n\n/** Maximum length for phrase display in search attempt rows */\nconst MAX_PHRASE_DISPLAY_LENGTH = 60;\n\n/** Icon color classes by status - defined outside component to avoid recreation on every render */\nconst ICON_COLOR_CLASSES = {\n green: \"text-green-600 dark:text-green-400\",\n amber: \"text-amber-600 dark:text-amber-400\",\n red: \"text-red-500 dark:text-red-400\",\n gray: \"text-gray-400 dark:text-gray-500\",\n} as const;\n\n/** User-friendly method names for display (Issue #10: simplified from technical jargon) */\nconst METHOD_DISPLAY_NAMES: Record<SearchMethod, string> = {\n exact_line_match: \"Exact location\",\n line_with_buffer: \"Nearby lines\",\n current_page: \"Expected page\",\n anchor_text_fallback: \"Key phrase\",\n adjacent_pages: \"Nearby pages\",\n expanded_window: \"Wider area\",\n regex_search: \"Entire document\",\n first_word_fallback: \"First word\",\n};\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\nexport interface VerificationLogProps {\n /** Array of search attempts from verification */\n searchAttempts: SearchAttempt[];\n /** Overall verification status */\n status?: SearchStatus | null;\n /** Expected page number from citation */\n expectedPage?: number;\n /** Expected line number from citation */\n expectedLine?: number;\n /** Page where match was found */\n foundPage?: number;\n /** Line where match was found */\n foundLine?: number;\n /** Whether the log is expanded (controlled) */\n isExpanded?: boolean;\n /** Callback when expansion state changes */\n onExpandChange?: (expanded: boolean) => void;\n /** Full phrase from citation (for audit display) */\n fullPhrase?: string;\n /** Anchor text from citation (for audit display) */\n anchorText?: string;\n}\n\nexport interface StatusHeaderProps {\n /** Verification status */\n status?: SearchStatus | null;\n /** Page where match was found */\n foundPage?: number;\n /** Expected page from citation */\n expectedPage?: number;\n /** Whether this is a compact header (for success states) */\n compact?: boolean;\n /** Anchor text to display in the header (for combined layout) */\n anchorText?: string;\n /** Full phrase for quote box (when using combined layout) */\n fullPhrase?: string;\n}\n\nexport interface QuoteBoxProps {\n /** The phrase to display */\n phrase: string;\n /** Maximum length before truncation */\n maxLength?: number;\n}\n\n// =============================================================================\n// UTILITY FUNCTIONS\n// =============================================================================\n\n/**\n * Get the color scheme based on status.\n */\nfunction getStatusColorScheme(status?: SearchStatus | null): \"green\" | \"amber\" | \"red\" | \"gray\" {\n if (!status) return \"gray\";\n\n switch (status) {\n case \"found\":\n case \"found_anchor_text_only\":\n case \"found_phrase_missed_anchor_text\":\n return \"green\";\n case \"found_on_other_page\":\n case \"found_on_other_line\":\n case \"partial_text_found\":\n case \"first_word_found\":\n return \"amber\";\n case \"not_found\":\n return \"red\";\n case \"pending\":\n case \"loading\":\n default:\n return \"gray\";\n }\n}\n\n/**\n * Get the header text based on status.\n * Issue #3: Made more concise - anchor text will be integrated separately.\n */\nfunction getStatusHeaderText(status?: SearchStatus | null): string {\n if (!status) return \"Verifying...\";\n\n switch (status) {\n case \"found\":\n case \"found_anchor_text_only\":\n case \"found_phrase_missed_anchor_text\":\n return \"Verified\";\n case \"found_on_other_page\":\n return \"Found on different page\";\n case \"found_on_other_line\":\n return \"Found on different line\";\n case \"partial_text_found\":\n case \"first_word_found\":\n return \"Partial match\";\n case \"not_found\":\n return \"Not found\";\n case \"pending\":\n case \"loading\":\n return \"Verifying...\";\n default:\n return \"Unknown\";\n }\n}\n\n/**\n * Get human-readable method name.\n */\nfunction getMethodDisplayName(method: SearchMethod): string {\n return METHOD_DISPLAY_NAMES[method] || method;\n}\n\n/**\n * Format a scope badge string from search attempt.\n */\nfunction formatScopeBadge(attempt: SearchAttempt): string {\n const page = attempt.pageSearched;\n const line = attempt.lineSearched;\n const scope = attempt.searchScope;\n\n if (scope === \"document\") return \"Entire Doc\";\n\n if (page != null) {\n if (line != null) {\n const lineStr = Array.isArray(line) ? line.join(\"-\") : line.toString();\n return `Pg ${page} : Line ${lineStr}`;\n }\n return `Pg ${page} : All Lines`;\n }\n\n return \"Unknown\";\n}\n\n/**\n * Get result text for a search attempt.\n */\nfunction getAttemptResultText(attempt: SearchAttempt): string {\n if (attempt.success) {\n if (attempt.matchedText) {\n const truncated = attempt.matchedText.length > MAX_MATCHED_TEXT_LENGTH\n ? attempt.matchedText.slice(0, MAX_MATCHED_TEXT_LENGTH) + \"...\"\n : attempt.matchedText;\n return `Found: \"${truncated}\"`;\n }\n return \"Match found\";\n }\n\n // Failed attempt\n if (attempt.note) return attempt.note;\n\n return \"Text does not match\";\n}\n\n/**\n * Get deemphasized detail text for GitHub CI/CD style display.\n * Shows location info in a clean, subtle format.\n */\nfunction getAttemptDetailText(attempt: SearchAttempt): string {\n const page = attempt.pageSearched;\n const line = attempt.lineSearched;\n const scope = attempt.searchScope;\n\n // For successful matches, show where it was found\n if (attempt.success) {\n if (attempt.foundLocation) {\n const { page: foundPage, line: foundLine } = attempt.foundLocation;\n if (foundLine != null) {\n return `Found on Pg ${foundPage}, Line ${foundLine}`;\n }\n return `Found on Pg ${foundPage}`;\n }\n if (page != null) {\n if (line != null) {\n const lineStr = Array.isArray(line) ? `${line[0]}-${line[line.length - 1]}` : line.toString();\n return `Pg ${page}, Line ${lineStr}`;\n }\n return `Pg ${page}`;\n }\n }\n\n // For failed searches, show where we searched\n if (scope === \"document\") return \"Full document search\";\n\n if (page != null) {\n if (line != null) {\n const lineStr = Array.isArray(line) ? `Lines ${line[0]}-${line[line.length - 1]}` : `Line ${line}`;\n return `Pg ${page}, ${lineStr}`;\n }\n return `Pg ${page}, all lines`;\n }\n\n return \"\";\n}\n\n// =============================================================================\n// PAGE BADGE COMPONENT\n// =============================================================================\n\ninterface PageBadgeProps {\n /** Expected page from citation */\n expectedPage?: number;\n /** Page where match was found */\n foundPage?: number;\n}\n\n/**\n * Displays page location information.\n * Shows arrow format (Pg 5 → 7) when location differs from expected.\n */\nfunction PageBadge({ expectedPage, foundPage }: PageBadgeProps) {\n const hasExpected = expectedPage != null && expectedPage > 0;\n const hasFound = foundPage != null && foundPage > 0;\n const locationDiffers = hasExpected && hasFound && expectedPage !== foundPage;\n\n // Show arrow format when location differs (Issue #8: Pg 5 → 7)\n if (locationDiffers) {\n return (\n <span className=\"text-xs font-mono text-gray-500 dark:text-gray-400 flex items-center gap-1\">\n <span className=\"text-gray-400 dark:text-gray-500\">Pg {expectedPage}</span>\n <span className=\"text-gray-400 dark:text-gray-500\">→</span>\n <span className=\"text-gray-700 dark:text-gray-300\">{foundPage}</span>\n </span>\n );\n }\n\n // Show found page or expected page\n const pageToShow = hasFound ? foundPage : expectedPage;\n if (pageToShow != null && pageToShow > 0) {\n return (\n <span className=\"text-xs font-mono text-gray-500 dark:text-gray-400\">\n Pg {pageToShow}\n </span>\n );\n }\n\n return null;\n}\n\n// =============================================================================\n// STATUS HEADER COMPONENT\n// =============================================================================\n\n/**\n * Header bar showing verification status with icon and text.\n *\n * shadcn HoverCard style:\n * - Clean white/dark background (no colored header backgrounds)\n * - Colored icon only indicates status\n * - Subtle ring border for elevation\n * - Page badge uses arrow format for location differences (Pg 5 → 7)\n */\nexport function StatusHeader({ status, foundPage, expectedPage, compact = false, anchorText, fullPhrase }: StatusHeaderProps) {\n const colorScheme = getStatusColorScheme(status);\n const headerText = getStatusHeaderText(status);\n\n // Select appropriate icon based on status\n // - Green (verified): CheckIcon\n // - Amber (partial): CheckIcon (de-emphasized, not aggressive warning)\n // - Red (not found): MissIcon (dash)\n // - Gray (pending): SpinnerIcon (not aggressive warning)\n const IconComponent = colorScheme === \"green\" ? CheckIcon\n : colorScheme === \"amber\" ? CheckIcon\n : colorScheme === \"red\" ? MissIcon\n : SpinnerIcon;\n\n // Combined layout: status + anchor text + quote in one header section\n const hasCombinedContent = anchorText || fullPhrase;\n\n if (hasCombinedContent) {\n const displayAnchorText = anchorText || fullPhrase?.slice(0, MAX_ANCHOR_TEXT_PREVIEW_LENGTH) || \"\";\n const displayPhrase = fullPhrase || anchorText || \"\";\n\n return (\n <div className=\"border-b border-gray-200 dark:border-gray-700\">\n {/* Status row - clean neutral background */}\n <div className={cn(\n \"flex items-center justify-between gap-2 text-sm\",\n compact ? \"px-3 py-2\" : \"px-4 py-2.5\"\n )}>\n <div className=\"flex items-center gap-2\">\n <span className={cn(\"size-4 max-w-4 max-h-4 flex-shrink-0\", ICON_COLOR_CLASSES[colorScheme])}>\n <IconComponent />\n </span>\n <span className=\"font-medium text-gray-800 dark:text-gray-100\">{headerText}</span>\n </div>\n <PageBadge expectedPage={expectedPage} foundPage={foundPage} />\n </div>\n\n {/* Anchor text and quote */}\n <div className=\"px-4 pb-3 pt-1\">\n <div className=\"text-[15px] font-semibold text-gray-800 dark:text-gray-100 mb-2\">\n \"{displayAnchorText}\"\n </div>\n {displayPhrase && displayPhrase !== displayAnchorText && (\n <QuoteBox phrase={displayPhrase} />\n )}\n </div>\n </div>\n );\n }\n\n // Simple header (no anchor text/quote)\n return (\n <div\n className={cn(\n \"flex items-center justify-between gap-2 border-b border-gray-200 dark:border-gray-700 text-sm\",\n compact ? \"px-3 py-2\" : \"px-4 py-2.5\"\n )}\n >\n <div className=\"flex items-center gap-2\">\n <span className={cn(\"size-4 max-w-4 max-h-4 flex-shrink-0\", ICON_COLOR_CLASSES[colorScheme])}>\n <IconComponent />\n </span>\n <span className=\"font-medium text-gray-800 dark:text-gray-100\">{headerText}</span>\n </div>\n <PageBadge expectedPage={expectedPage} foundPage={foundPage} />\n </div>\n );\n}\n\n// =============================================================================\n// QUOTE BOX COMPONENT\n// =============================================================================\n\n/**\n * Styled quote box for displaying the phrase being verified.\n * Issue #7: Removed serif/italic for modern UI consistency.\n * Uses left border accent (which aligns with shadcn patterns).\n */\nexport function QuoteBox({ phrase, maxLength = MAX_QUOTE_BOX_LENGTH }: QuoteBoxProps) {\n const displayPhrase = phrase.length > maxLength\n ? phrase.slice(0, maxLength) + \"...\"\n : phrase;\n\n return (\n <blockquote className=\"text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-gray-800/50 p-3 border-l-[3px] border-gray-300 dark:border-gray-600 leading-relaxed text-sm\">\n \"{displayPhrase}\"\n </blockquote>\n );\n}\n\n// =============================================================================\n// VERIFICATION LOG SUMMARY\n// =============================================================================\n\ninterface VerificationLogSummaryProps {\n status?: SearchStatus | null;\n searchAttempts: SearchAttempt[];\n expectedPage?: number;\n expectedLine?: number;\n foundPage?: number;\n foundLine?: number;\n isExpanded: boolean;\n onToggle: () => void;\n}\n\n/**\n * Clickable summary header - GitHub-style with just chevron + count.\n * Issue #6 & #11: Simplified to avoid redundant info (header already shows status).\n */\nfunction VerificationLogSummary({\n searchAttempts,\n isExpanded,\n onToggle,\n}: VerificationLogSummaryProps) {\n const totalCount = searchAttempts.length;\n const successCount = searchAttempts.filter(a => a.success).length;\n\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={isExpanded}\n aria-controls=\"verification-log-timeline\"\n className=\"w-full px-4 py-2.5 flex items-center justify-between text-xs hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors\"\n >\n <div className=\"flex items-center gap-1.5 text-gray-600 dark:text-gray-400\">\n <svg\n className={cn(\n \"size-3 transition-transform duration-200\",\n isExpanded && \"rotate-90\"\n )}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n aria-hidden=\"true\"\n >\n <path d=\"M9 6l6 6-6 6\" />\n </svg>\n <span>Details</span>\n <span className=\"text-gray-400 dark:text-gray-500\">\n ({successCount} / {totalCount} {totalCount === 1 ? \"search\" : \"searches\"})\n </span>\n </div>\n </button>\n );\n}\n\n// =============================================================================\n// AUDIT-FOCUSED SEARCH DISPLAY\n// =============================================================================\n\ninterface AuditSearchDisplayProps {\n searchAttempts: SearchAttempt[];\n /** Citation's full phrase (for display) */\n fullPhrase?: string;\n /** Citation's anchor text (for display) */\n anchorText?: string;\n}\n\ninterface SearchAttemptRowProps {\n attempt: SearchAttempt;\n index: number;\n totalCount: number;\n}\n\n/**\n * Single row showing one search attempt with its phrase, method, and location.\n * Displays as: \"1. \"phrase...\" Method · Pg X\"\n * Also shows search variations if present.\n */\nfunction SearchAttemptRow({ attempt, index, totalCount }: SearchAttemptRowProps) {\n // Format the phrase for display (truncate if too long), with null safety\n const phrase = attempt.searchPhrase ?? \"\";\n const displayPhrase = phrase.length === 0\n ? \"(empty)\"\n : phrase.length > MAX_PHRASE_DISPLAY_LENGTH\n ? phrase.slice(0, MAX_PHRASE_DISPLAY_LENGTH) + \"...\"\n : phrase;\n\n // Format location\n const locationText = attempt.searchScope === \"document\"\n ? \"Entire doc\"\n : attempt.pageSearched != null\n ? `Pg ${attempt.pageSearched}`\n : \"\";\n\n // Get method display name\n const methodName = METHOD_DISPLAY_NAMES[attempt.method] || attempt.method;\n\n // Calculate the width needed for the index number (for alignment)\n const indexWidth = String(totalCount).length;\n\n // Get search variations (if any)\n const variations = attempt.searchVariations ?? [];\n\n return (\n <div className=\"flex items-start gap-2 py-0.5\">\n {/* Index number */}\n <span\n className=\"text-[10px] text-gray-400 dark:text-gray-500 font-mono flex-shrink-0 tabular-nums\"\n style={{ minWidth: `${indexWidth + 1}ch` }}\n >\n {index}.\n </span>\n\n {/* Status icon */}\n <span\n className={cn(\n \"size-3 max-w-3 max-h-3 mt-0.5 flex-shrink-0\",\n attempt.success ? \"text-green-600 dark:text-green-400\" : \"text-gray-400 dark:text-gray-500\"\n )}\n role=\"img\"\n aria-label={attempt.success ? \"Found\" : \"Not found\"}\n >\n {attempt.success ? <CheckIcon /> : <MissIcon />}\n </span>\n\n {/* Phrase and details */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-xs text-gray-700 dark:text-gray-200 font-mono break-all\">\n \"{displayPhrase}\"\n </span>\n <span className=\"text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0 whitespace-nowrap\">\n {methodName}{locationText && ` · ${locationText}`}\n </span>\n </div>\n {/* Show search variations if present */}\n {variations.length > 0 && (\n <div className=\"text-[10px] text-gray-400 dark:text-gray-500 mt-0.5\">\n Also tried: {variations.slice(0, 3).map(v => `\"${v}\"`).join(\", \")}\n {variations.length > 3 && ` +${variations.length - 3} more`}\n </div>\n )}\n </div>\n </div>\n );\n}\n\ninterface RejectedMatchesSectionProps {\n rejectedMatches: Array<{ text: string; count?: number }>;\n}\n\n/**\n * Section showing text that was found but rejected.\n * Helps auditors understand why partial matches weren't accepted.\n */\nfunction RejectedMatchesSection({ rejectedMatches }: RejectedMatchesSectionProps) {\n if (rejectedMatches.length === 0) return null;\n\n return (\n <div>\n <div className=\"text-[11px] text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1.5\">\n Found but rejected\n </div>\n <div className=\"space-y-1\">\n {rejectedMatches.map((match) => (\n <div key={match.text} className=\"text-xs text-gray-600 dark:text-gray-300 font-mono\">\n \"{match.text}\"{match.count != null && ` (${match.count} occurrences)`}\n </div>\n ))}\n </div>\n <p className=\"text-[11px] text-gray-500 dark:text-gray-400 mt-1.5 italic\">\n Context did not match citation\n </p>\n </div>\n );\n}\n\n/**\n * Audit-focused search display.\n * Shows each search attempt in order with its phrase, method, and location.\n * This makes it clear what was searched at each step of the progression.\n */\nfunction AuditSearchDisplay({ searchAttempts, fullPhrase, anchorText }: AuditSearchDisplayProps) {\n // Collect rejected matches (found but not accepted)\n const rejectedMatches = useMemo(() => {\n const seen = new Set<string>();\n const matches: Array<{ text: string; count?: number }> = [];\n for (const attempt of searchAttempts) {\n if (!attempt.success && attempt.matchedText && !seen.has(attempt.matchedText)) {\n seen.add(attempt.matchedText);\n matches.push({ text: attempt.matchedText });\n }\n }\n return matches;\n }, [searchAttempts]);\n\n // If no search attempts, fall back to citation data\n if (searchAttempts.length === 0) {\n const fallbackPhrases = [fullPhrase, anchorText].filter((p): p is string => Boolean(p));\n if (fallbackPhrases.length === 0) return null;\n\n // Display fallback as simple list\n return (\n <div className=\"px-4 py-3 space-y-3 text-sm\">\n <div>\n <div className=\"text-[11px] text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1.5\">\n Searched for\n </div>\n <div className=\"space-y-1\">\n {fallbackPhrases.map((phrase, i) => (\n <div key={i} className=\"flex items-start gap-2\">\n <span className=\"size-3 max-w-3 max-h-3 mt-0.5 text-gray-400 dark:text-gray-500 flex-shrink-0\">\n <MissIcon />\n </span>\n <span className=\"text-xs text-gray-700 dark:text-gray-200 font-mono break-all\">\n \"{phrase}\"\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"px-4 py-3 space-y-4 text-sm\">\n {/* Search attempts timeline */}\n <div>\n <div className=\"text-[11px] text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-2\">\n Search attempts\n </div>\n <div className=\"space-y-0.5\">\n {searchAttempts.map((attempt, i) => (\n <SearchAttemptRow\n key={i}\n attempt={attempt}\n index={i + 1}\n totalCount={searchAttempts.length}\n />\n ))}\n </div>\n </div>\n\n {/* Rejected matches section */}\n <RejectedMatchesSection rejectedMatches={rejectedMatches} />\n </div>\n );\n}\n\n// =============================================================================\n// LEGACY VERIFICATION LOG ATTEMPT (kept for success states)\n// =============================================================================\n\ninterface VerificationLogAttemptProps {\n attempt: SearchAttempt;\n expectedPage?: number;\n}\n\n/**\n * Single attempt row - simplified, only shows meaningful info.\n * For success: shows where found (if different from expected).\n */\nfunction VerificationLogAttempt({ attempt, expectedPage }: VerificationLogAttemptProps) {\n const isSuccess = attempt.success;\n const methodName = getMethodDisplayName(attempt.method);\n\n // Only show location detail if found on different page than expected\n const foundPage = attempt.foundLocation?.page;\n const showLocationDetail = isSuccess && foundPage && expectedPage && foundPage !== expectedPage;\n\n // Icon component and color\n const IconComponent = isSuccess ? CheckIcon : MissIcon;\n const iconColorClass = isSuccess\n ? \"text-green-600 dark:text-green-400\"\n : \"text-gray-400 dark:text-gray-500\";\n\n return (\n <div className=\"flex items-center gap-2 py-1.5 px-2 -mx-2 rounded hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors\">\n {/* Leading icon */}\n <span className={cn(\"size-3.5 max-w-3.5 max-h-3.5 flex-shrink-0\", iconColorClass)}>\n <IconComponent />\n </span>\n {/* Method name */}\n <span className=\"flex-1 text-xs text-gray-700 dark:text-gray-300\">\n {methodName}\n </span>\n {/* Location detail - only when found on different page */}\n {showLocationDetail && (\n <span className=\"text-[11px] text-gray-500 dark:text-gray-400 flex-shrink-0\">\n → Pg {foundPage}\n </span>\n )}\n </div>\n );\n}\n\n// =============================================================================\n// VERIFICATION LOG TIMELINE\n// =============================================================================\n\ninterface VerificationLogTimelineProps {\n searchAttempts: SearchAttempt[];\n expectedPage?: number;\n /** For miss states: show audit-focused phrase display instead of method list */\n showAuditDisplay?: boolean;\n fullPhrase?: string;\n anchorText?: string;\n}\n\n/**\n * Scrollable timeline showing search attempts.\n * For miss states: shows audit-focused phrase display (what was searched).\n * For success/partial states: shows simplified method list with location info.\n */\nfunction VerificationLogTimeline({ searchAttempts, expectedPage, showAuditDisplay, fullPhrase, anchorText }: VerificationLogTimelineProps) {\n // For miss states, show audit-focused display\n if (showAuditDisplay) {\n return (\n <div id=\"verification-log-timeline\" style={{ maxHeight: MAX_TIMELINE_HEIGHT }} className=\"overflow-y-auto\">\n <AuditSearchDisplay\n searchAttempts={searchAttempts}\n fullPhrase={fullPhrase}\n anchorText={anchorText}\n />\n </div>\n );\n }\n\n // For success/partial states, show simplified method list\n return (\n <div\n id=\"verification-log-timeline\"\n className=\"px-4 pb-3 overflow-y-auto\"\n style={{ maxHeight: MAX_TIMELINE_HEIGHT }}\n >\n {searchAttempts.map((attempt, index) => {\n const lineKey = Array.isArray(attempt.lineSearched)\n ? attempt.lineSearched.join(\"-\")\n : attempt.lineSearched ?? \"none\";\n const key = `${attempt.method}-${attempt.pageSearched ?? \"doc\"}-${lineKey}-${index}`;\n return (\n <VerificationLogAttempt\n key={key}\n attempt={attempt}\n expectedPage={expectedPage}\n />\n );\n })}\n </div>\n );\n}\n\n// =============================================================================\n// MAIN VERIFICATION LOG COMPONENT\n// =============================================================================\n\n/**\n * Collapsible verification log showing search attempt timeline.\n * Displays a summary header that can be clicked to expand the full log.\n */\nexport function VerificationLog({\n searchAttempts,\n status,\n expectedPage,\n expectedLine,\n foundPage,\n foundLine,\n isExpanded: controlledIsExpanded,\n onExpandChange,\n fullPhrase,\n anchorText,\n}: VerificationLogProps) {\n const [internalIsExpanded, setInternalIsExpanded] = useState(false);\n\n // Use controlled state if provided, otherwise internal\n const isExpanded = controlledIsExpanded ?? internalIsExpanded;\n const setIsExpanded = (expanded: boolean) => {\n if (onExpandChange) {\n onExpandChange(expanded);\n } else {\n setInternalIsExpanded(expanded);\n }\n };\n\n // Memoize the successful attempt lookup\n const successfulAttempt = useMemo(\n () => searchAttempts.find(a => a.success),\n [searchAttempts]\n );\n\n // Don't render if no attempts\n if (!searchAttempts || searchAttempts.length === 0) {\n return null;\n }\n\n // Derive found location from successful attempt if not provided\n const derivedFoundPage = foundPage ?? successfulAttempt?.foundLocation?.page ?? successfulAttempt?.pageSearched;\n const derivedFoundLine = foundLine ?? successfulAttempt?.foundLocation?.line;\n\n return (\n <div className=\"border-t border-gray-200 dark:border-gray-700\">\n <VerificationLogSummary\n status={status}\n searchAttempts={searchAttempts}\n expectedPage={expectedPage}\n expectedLine={expectedLine}\n foundPage={derivedFoundPage}\n foundLine={derivedFoundLine}\n isExpanded={isExpanded}\n onToggle={() => setIsExpanded(!isExpanded)}\n />\n {isExpanded && (\n <VerificationLogTimeline\n searchAttempts={searchAttempts}\n expectedPage={expectedPage}\n showAuditDisplay={status === \"not_found\"}\n fullPhrase={fullPhrase}\n anchorText={anchorText}\n />\n )}\n </div>\n );\n}\n\n// =============================================================================\n// ATTEMPTING TO VERIFY SECTION\n// =============================================================================\n\nexport interface AttemptingToVerifyProps {\n /** The anchor text or key phrase being verified */\n anchorText?: string;\n /** The full phrase being searched */\n fullPhrase?: string;\n}\n\n/**\n * Section showing what citation is being verified.\n * Displays the anchor text and quote box being searched.\n */\nexport function AttemptingToVerify({ anchorText, fullPhrase }: AttemptingToVerifyProps) {\n const displayAnchorText = anchorText || fullPhrase?.slice(0, MAX_ANCHOR_TEXT_PREVIEW_LENGTH) || \"Citation\";\n const displayPhrase = fullPhrase || anchorText || \"\";\n\n return (\n <div className=\"px-4 py-3 space-y-2\">\n <div className=\"text-[10px] text-gray-500 dark:text-gray-400 uppercase font-medium tracking-wide\">\n Searching for:\n </div>\n <div className=\"text-[15px] font-semibold text-gray-800 dark:text-gray-100\">\n \"{displayAnchorText}\"\n </div>\n {displayPhrase && displayPhrase !== displayAnchorText && (\n <QuoteBox phrase={displayPhrase} />\n )}\n </div>\n );\n}\n","import React, {\r\n forwardRef,\r\n memo,\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\n\r\n// React 19.2+ Activity component for prefetching - falls back to Fragment if unavailable\r\nconst Activity =\r\n (React as { Activity?: React.ComponentType<{ mode: \"visible\" | \"hidden\"; children: React.ReactNode }> }).Activity ??\r\n (({ children }: { mode: \"visible\" | \"hidden\"; children: React.ReactNode }) => <>{children}</>);\r\nimport { type CitationStatus } from \"../types/citation.js\";\r\nimport type { Verification } from \"../types/verification.js\";\r\nimport type { MatchedVariation, SearchAttempt, SearchStatus } from \"../types/search.js\";\r\nimport { CheckIcon, CloseIcon, SpinnerIcon, WarningIcon } from \"./icons.js\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"./Popover.js\";\r\nimport type {\r\n BaseCitationProps,\r\n CitationBehaviorActions,\r\n CitationBehaviorConfig,\r\n CitationBehaviorContext,\r\n CitationContent,\r\n CitationEventHandlers,\r\n CitationRenderProps,\r\n CitationVariant,\r\n} from \"./types.js\";\r\nimport {\r\n cn,\r\n generateCitationInstanceId,\r\n generateCitationKey,\r\n} from \"./utils.js\";\r\nimport { useSmartDiff } from \"./useSmartDiff.js\";\r\nimport { useCitationOverlay } from \"./CitationOverlayContext.js\";\r\nimport { SplitDiffDisplay, getContextualStatusMessage } from \"./SplitDiffDisplay.js\";\r\nimport { StatusHeader, VerificationLog } from \"./VerificationLog.js\";\r\n\r\n// Re-export types for convenience\r\nexport type { CitationVariant, CitationContent } from \"./types.js\";\r\n\r\n// Constants\r\n/** Default number of search attempt groups to show before expanding */\r\nconst DEFAULT_VISIBLE_GROUP_COUNT = 2;\r\n\r\n/** Maximum characters to show for truncated phrases in search attempts */\r\nconst MAX_PHRASE_LENGTH = 50;\r\n\r\n/** Popover container width */\r\nconst POPOVER_WIDTH = \"380px\";\r\n\r\n/** Popover container max width (viewport-relative) */\r\nconst POPOVER_MAX_WIDTH = \"90vw\";\r\n\r\n/** Maximum characters to show for matched text display in search results */\r\nconst MAX_MATCHED_TEXT_LENGTH = 40;\r\n\r\n/** Maximum number of search variations to show before collapsing */\r\nconst MAX_VISIBLE_VARIATIONS = 3;\r\n\r\n/** Maximum characters to show for variation strings */\r\nconst MAX_VARIATION_LENGTH = 30;\r\n\r\n// =============================================================================\r\n// ERROR BOUNDARY\r\n// =============================================================================\r\n\r\ninterface ErrorBoundaryProps {\r\n children: React.ReactNode;\r\n fallback?: React.ReactNode;\r\n}\r\n\r\ninterface ErrorBoundaryState {\r\n hasError: boolean;\r\n error?: Error;\r\n}\r\n\r\n/**\r\n * Error boundary for catching and displaying rendering errors in citation components.\r\n * Prevents the entire app from crashing if citation rendering fails.\r\n */\r\nclass CitationErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\r\n constructor(props: ErrorBoundaryProps) {\r\n super(props);\r\n this.state = { hasError: false };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\r\n return { hasError: true, error };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\r\n console.error(\"[DeepCitation] Citation component error:\", error, errorInfo);\r\n }\r\n\r\n render(): React.ReactNode {\r\n if (this.state.hasError) {\r\n if (this.props.fallback) {\r\n return this.props.fallback;\r\n }\r\n // Default fallback: minimal error indicator\r\n return (\r\n <span\r\n className=\"inline-flex items-center text-red-500 dark:text-red-400\"\r\n title={`Citation error: ${this.state.error?.message || \"Unknown error\"}`}\r\n >\r\n <WarningIcon className=\"size-3\" />\r\n </span>\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\n// =============================================================================\r\n// UTILITY FUNCTIONS\r\n// =============================================================================\r\n\r\n/**\r\n * Get the default content type based on variant.\r\n */\r\nfunction getDefaultContent(variant: CitationVariant): CitationContent {\r\n switch (variant) {\r\n case \"chip\":\r\n case \"text\":\r\n case \"brackets\":\r\n case \"linter\":\r\n return \"anchorText\";\r\n case \"source\":\r\n return \"source\";\r\n case \"superscript\":\r\n case \"minimal\":\r\n default:\r\n return \"number\";\r\n }\r\n}\r\n\r\n/**\r\n * Strip leading/trailing brackets from text.\r\n * Handles cases where LLM output includes brackets in anchorText.\r\n */\r\nfunction stripBrackets(text: string): string {\r\n return text.replace(/^\\[+\\s*/, \"\").replace(/\\s*\\]+$/, \"\");\r\n}\r\n\r\n/**\r\n * Get display text based on content type and citation data.\r\n * Returns \"1\" as fallback if no citation number is available.\r\n */\r\nfunction getDisplayText(\r\n citation: BaseCitationProps[\"citation\"],\r\n content: CitationContent,\r\n fallbackDisplay?: string | null\r\n): string {\r\n if (content === \"indicator\") {\r\n return \"\";\r\n }\r\n\r\n if (content === \"anchorText\") {\r\n const raw =\r\n citation.anchorText?.toString() ||\r\n citation.citationNumber?.toString() ||\r\n fallbackDisplay ||\r\n \"1\";\r\n return stripBrackets(raw);\r\n }\r\n\r\n if (content === \"source\") {\r\n // Source content: show siteName or domain (using main's field names)\r\n return citation.siteName || citation.domain || citation.anchorText?.toString() || \"Source\";\r\n }\r\n\r\n // content === \"number\"\r\n return citation.citationNumber?.toString() || \"1\";\r\n}\r\n\r\n// =============================================================================\r\n// TYPES\r\n// =============================================================================\r\n\r\n/**\r\n * Props for the CitationComponent.\r\n *\r\n * ## Behavior\r\n *\r\n * Default interaction pattern:\r\n * - **Hover**: Shows popover with verification image/details\r\n * - **Click**: Opens full-size image overlay (zoom)\r\n * - **Escape / Click outside / Click overlay**: Closes image overlay\r\n *\r\n * Custom behavior:\r\n * - Use `behaviorConfig.onClick` to replace the default click behavior\r\n * - Use `eventHandlers.onClick` to add side effects (disables default)\r\n *\r\n * @example Default usage\r\n * ```tsx\r\n * <CitationComponent\r\n * citation={citation}\r\n * verification={verification}\r\n * />\r\n * ```\r\n *\r\n * @example Custom click behavior\r\n * ```tsx\r\n * <CitationComponent\r\n * citation={citation}\r\n * verification={verification}\r\n * behaviorConfig={{\r\n * onClick: (context) => {\r\n * // Custom action\r\n * console.log('Clicked:', context.citationKey);\r\n * return { setImageExpanded: true };\r\n * }\r\n * }}\r\n * />\r\n * ```\r\n */\r\nexport interface CitationComponentProps extends BaseCitationProps {\r\n /** Verification result from the DeepCitation API */\r\n verification?: Verification | null;\r\n /**\r\n * Explicitly show loading spinner. When true, displays spinner regardless\r\n * of verification status. Use this when verification is in-flight.\r\n */\r\n isLoading?: boolean;\r\n /**\r\n * Visual style variant for the citation.\r\n * - `chip`: Pill/badge style with background color\r\n * - `brackets`: [text✓] with square brackets (default)\r\n * - `text`: Plain text, inherits parent styling\r\n * - `superscript`: Small raised text like footnotes¹\r\n * - `minimal`: Compact text with indicator, truncated\r\n * - `source`: ChatGPT-style source chip with name + count\r\n * - `linter`: Inline text with semantic underlines (solid/dashed/wavy)\r\n */\r\n variant?: CitationVariant;\r\n /**\r\n * What content to display in the citation.\r\n * - `anchorText`: Descriptive text (e.g., \"Revenue Growth\")\r\n * - `number`: Citation number (e.g., \"1\", \"2\", \"3\")\r\n * - `indicator`: Only the status icon, no text\r\n * - `source`: Source name (e.g., \"Wikipedia\")\r\n *\r\n * Defaults based on variant:\r\n * - `chip` → `anchorText`\r\n * - `brackets` → `anchorText`\r\n * - `text` → `anchorText`\r\n * - `linter` → `anchorText`\r\n * - `superscript` → `number`\r\n * - `minimal` → `number`\r\n * - `source` → `source`\r\n */\r\n content?: CitationContent;\r\n /** Event handlers for citation interactions */\r\n eventHandlers?: CitationEventHandlers;\r\n /**\r\n * Configuration for customizing default click/hover behaviors.\r\n * Providing onClick REPLACES the default click behavior.\r\n */\r\n behaviorConfig?: CitationBehaviorConfig;\r\n /** Enable mobile touch handlers */\r\n isMobile?: boolean;\r\n /** Custom render function for the status indicator */\r\n renderIndicator?: (status: CitationStatus) => React.ReactNode;\r\n /** Custom render function for entire citation content */\r\n renderContent?: (props: CitationRenderProps) => React.ReactNode;\r\n /** Position of popover. Use \"hidden\" to disable. */\r\n popoverPosition?: \"top\" | \"bottom\" | \"hidden\";\r\n /** Custom render function for popover content */\r\n renderPopoverContent?: (props: {\r\n citation: BaseCitationProps[\"citation\"];\r\n verification: Verification | null;\r\n status: CitationStatus;\r\n }) => React.ReactNode;\r\n /**\r\n * Number of additional citations grouped with this one (for source variant).\r\n * Shows as \"+N\" suffix (e.g., \"Wikipedia +2\")\r\n */\r\n additionalCount?: number;\r\n /**\r\n * Favicon URL to display (for source variant).\r\n * Falls back to citation.faviconUrl if not provided.\r\n */\r\n faviconUrl?: string;\r\n /**\r\n * Whether to show the status indicator (checkmark, warning, spinner).\r\n * Defaults to true. Set to false to hide the indicator.\r\n */\r\n showIndicator?: boolean;\r\n}\r\n\r\nfunction getStatusLabel(status: CitationStatus): string {\r\n if (status.isVerified && !status.isPartialMatch) return \"Verified\";\r\n if (status.isPartialMatch) return \"Partial Match\";\r\n if (status.isMiss) return \"Not Found\";\r\n if (status.isPending) return \"Verifying...\";\r\n return \"\";\r\n}\r\n\r\n// =============================================================================\r\n// TRUST LEVEL HELPERS\r\n// =============================================================================\r\n\r\n/**\r\n * Get the trust level from a MatchedVariation.\r\n * Trust levels determine indicator colors:\r\n * - high: Green checkmark (exact or normalized full phrase)\r\n * - medium: Green checkmark (anchorText matches)\r\n * - low: Amber checkmark (partial matches)\r\n */\r\nfunction getTrustLevel(matchedVariation?: MatchedVariation): \"high\" | \"medium\" | \"low\" {\r\n if (!matchedVariation) return \"medium\";\r\n switch (matchedVariation) {\r\n case \"exact_full_phrase\":\r\n case \"normalized_full_phrase\":\r\n return \"high\";\r\n case \"exact_anchor_text\":\r\n case \"normalized_anchor_text\":\r\n return \"medium\";\r\n case \"partial_full_phrase\":\r\n case \"partial_anchor_text\":\r\n case \"first_word_only\":\r\n return \"low\";\r\n default:\r\n return \"medium\";\r\n }\r\n}\r\n\r\n/**\r\n * Check if a match has low trust (should show amber indicator).\r\n */\r\nfunction isLowTrustMatch(matchedVariation?: MatchedVariation): boolean {\r\n return getTrustLevel(matchedVariation) === \"low\";\r\n}\r\n\r\n/**\r\n * Get the search phrase from a SearchAttempt.\r\n */\r\nfunction getSearchPhrase(attempt: SearchAttempt): string {\r\n return attempt.searchPhrase || \"\";\r\n}\r\n\r\n/**\r\n * Get the note from a SearchAttempt.\r\n */\r\nfunction getSearchNote(attempt: SearchAttempt): string | undefined {\r\n return attempt.note;\r\n}\r\n\r\n// =============================================================================\r\n// GROUPED SEARCH ATTEMPTS DISPLAY\r\n// =============================================================================\r\n\r\n/**\r\n * A grouped search attempt combines multiple attempts that searched the same phrase.\r\n * This provides a cleaner display when the same phrase is searched on multiple pages.\r\n */\r\ninterface GroupedSearchAttempt {\r\n /** The search phrase (normalized for grouping) */\r\n phrase: string;\r\n /** Type of phrase: full_phrase or anchor_text */\r\n phraseType: \"full_phrase\" | \"anchor_text\" | undefined;\r\n /** All pages that were searched */\r\n pagesSearched: number[];\r\n /** All methods used */\r\n methodsUsed: Set<string>;\r\n /** All variations tried (from searchVariations arrays) */\r\n variationsTried: string[];\r\n /** Whether any attempt succeeded */\r\n anySuccess: boolean;\r\n /** The successful attempt if any */\r\n successfulAttempt?: SearchAttempt;\r\n /** All notes from attempts (deduplicated) */\r\n uniqueNotes: string[];\r\n /** Total number of attempts in this group */\r\n attemptCount: number;\r\n}\r\n\r\n/**\r\n * Get a human-readable label for search methods.\r\n */\r\nfunction getMethodLabel(method: string): string {\r\n const labels: Record<string, string> = {\r\n exact_line_match: \"exact line\",\r\n line_with_buffer: \"line buffer\",\r\n current_page: \"expected page\",\r\n anchor_text_fallback: \"anchor text\",\r\n adjacent_pages: \"adjacent pages\",\r\n expanded_window: \"expanded search\",\r\n regex_search: \"regex\",\r\n first_word_fallback: \"first word\",\r\n };\r\n return labels[method] || method;\r\n}\r\n\r\n/**\r\n * Format a list of page numbers into a readable string.\r\n * Combines consecutive pages into ranges for compact display.\r\n *\r\n * @param pages - Array of page numbers to format\r\n * @returns Formatted string like \"pages 1-3, 5-7\" or \"page 2\"\r\n *\r\n * @example\r\n * formatPageList([1, 2, 3, 5, 6, 7]) // \"pages 1-3, 5-7\"\r\n * formatPageList([2]) // \"page 2\"\r\n * formatPageList([]) // \"\"\r\n */\r\nfunction formatPageList(pages: number[]): string {\r\n if (pages.length === 0) return \"\";\r\n const sorted = [...new Set(pages)].sort((a, b) => a - b);\r\n if (sorted.length === 1) return `page ${sorted[0]}`;\r\n\r\n const ranges: string[] = [];\r\n let rangeStart = sorted[0];\r\n let rangeEnd = sorted[0];\r\n\r\n for (let i = 1; i < sorted.length; i++) {\r\n if (sorted[i] === rangeEnd + 1) {\r\n rangeEnd = sorted[i];\r\n } else {\r\n ranges.push(rangeStart === rangeEnd ? `${rangeStart}` : `${rangeStart}-${rangeEnd}`);\r\n rangeStart = sorted[i];\r\n rangeEnd = sorted[i];\r\n }\r\n }\r\n ranges.push(rangeStart === rangeEnd ? `${rangeStart}` : `${rangeStart}-${rangeEnd}`);\r\n\r\n return `pages ${ranges.join(\", \")}`;\r\n}\r\n\r\n/**\r\n * Group search attempts by unique phrase for a cleaner display.\r\n * Attempts with the same phrase are combined into a single group showing\r\n * all pages searched, methods used, and variations tried.\r\n *\r\n * @param attempts - Array of search attempts from verification\r\n * @returns Array of grouped attempts, sorted with successful matches first\r\n *\r\n * @example\r\n * const grouped = groupSearchAttempts(verification.searchAttempts);\r\n * grouped.forEach(group => {\r\n * console.log(`\"${group.phrase}\" - searched ${group.pagesSearched.length} pages`);\r\n * });\r\n */\r\nfunction groupSearchAttempts(attempts: SearchAttempt[]): GroupedSearchAttempt[] {\r\n const groups = new Map<string, GroupedSearchAttempt>();\r\n\r\n for (const attempt of attempts) {\r\n const phrase = getSearchPhrase(attempt);\r\n // Create a key that includes phrase type to differentiate fullPhrase vs anchorText searches\r\n const key = `${attempt.searchPhraseType || \"unknown\"}:${phrase}`;\r\n\r\n let group = groups.get(key);\r\n if (!group) {\r\n group = {\r\n phrase,\r\n phraseType: attempt.searchPhraseType,\r\n pagesSearched: [],\r\n methodsUsed: new Set(),\r\n variationsTried: [],\r\n anySuccess: false,\r\n uniqueNotes: [],\r\n attemptCount: 0,\r\n };\r\n groups.set(key, group);\r\n }\r\n\r\n group.attemptCount++;\r\n if (attempt.pageSearched != null) {\r\n group.pagesSearched.push(attempt.pageSearched);\r\n }\r\n group.methodsUsed.add(attempt.method);\r\n\r\n // Collect unique variations\r\n if (attempt.searchVariations) {\r\n for (const variation of attempt.searchVariations) {\r\n if (variation !== phrase && !group.variationsTried.includes(variation)) {\r\n group.variationsTried.push(variation);\r\n }\r\n }\r\n }\r\n\r\n // Track success\r\n if (attempt.success) {\r\n group.anySuccess = true;\r\n group.successfulAttempt = attempt;\r\n }\r\n\r\n // Collect unique notes\r\n const note = getSearchNote(attempt);\r\n if (note && !group.uniqueNotes.includes(note)) {\r\n group.uniqueNotes.push(note);\r\n }\r\n }\r\n\r\n // Sort groups: successful first, then by phrase type (full_phrase before anchor_text)\r\n return Array.from(groups.values()).sort((a, b) => {\r\n if (a.anySuccess !== b.anySuccess) return a.anySuccess ? -1 : 1;\r\n if (a.phraseType !== b.phraseType) {\r\n if (a.phraseType === \"full_phrase\") return -1;\r\n if (b.phraseType === \"full_phrase\") return 1;\r\n }\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * Derive citation status from a Verification object.\r\n * The status comes from verification.status.\r\n *\r\n * Status classification:\r\n * - GREEN (isVerified only): Full phrase found at expected location\r\n * - \"found\": Exact match\r\n * - \"found_phrase_missed_anchor_text\": Full phrase found, anchor text highlighting failed\r\n *\r\n * - AMBER (isVerified + isPartialMatch): Something found but not ideal\r\n * - \"found_anchor_text_only\": Only anchor text found, full phrase not matched\r\n * - \"found_on_other_page\": Found but on different page than expected\r\n * - \"found_on_other_line\": Found but on different line than expected\r\n * - \"partial_text_found\": Only part of the text was found\r\n * - \"first_word_found\": Only the first word matched (lowest confidence)\r\n * - Low-trust matches from matchedVariation also show amber\r\n *\r\n * - RED (isMiss): Not found\r\n * - \"not_found\": Text not found in document\r\n *\r\n * Note: isPending is only true when status is explicitly \"pending\" or \"loading\".\r\n * Use the isLoading prop to show spinner when verification is in-flight.\r\n */\r\nfunction getStatusFromVerification(\r\n verification: Verification | null | undefined\r\n): CitationStatus {\r\n const status = verification?.status;\r\n\r\n // No verification or no status = no status flags set\r\n // (use isLoading prop to explicitly show loading state)\r\n if (!verification || !status) {\r\n return {\r\n isVerified: false,\r\n isMiss: false,\r\n isPartialMatch: false,\r\n isPending: false,\r\n };\r\n }\r\n\r\n const isMiss = status === \"not_found\";\r\n const isPending = status === \"pending\" || status === \"loading\";\r\n\r\n // Check if any successful search attempt has low trust\r\n const hasLowTrustMatch =\r\n verification.searchAttempts?.some(\r\n (a) => a.success && isLowTrustMatch(a.matchedVariation)\r\n ) ?? false;\r\n\r\n // Partial matches show amber indicator - something found but not ideal\r\n const isPartialMatch =\r\n status === \"found_anchor_text_only\" || // Only anchor text found, not full phrase\r\n status === \"found_on_other_page\" ||\r\n status === \"found_on_other_line\" ||\r\n status === \"partial_text_found\" ||\r\n status === \"first_word_found\" ||\r\n hasLowTrustMatch; // Low-trust matches also show as partial (amber)\r\n\r\n // Verified = we found something (either exact or partial)\r\n const isVerified =\r\n status === \"found\" ||\r\n status === \"found_phrase_missed_anchor_text\" || // Full phrase found, just missed anchor text highlight\r\n isPartialMatch;\r\n\r\n return { isVerified, isMiss, isPartialMatch, isPending };\r\n}\r\n\r\n// =============================================================================\r\n// IMAGE OVERLAY COMPONENT\r\n// =============================================================================\r\n\r\ninterface ImageOverlayProps {\r\n src: string;\r\n alt: string;\r\n onClose: () => void;\r\n}\r\n\r\n/**\r\n * Full-screen image overlay for zoomed verification images.\r\n * Click anywhere or press Escape to close.\r\n */\r\nfunction ImageOverlay({ src, alt, onClose }: ImageOverlayProps) {\r\n const { registerOverlay, unregisterOverlay } = useCitationOverlay();\r\n\r\n // Register this overlay as open globally (blocks hover on other citations)\r\n useEffect(() => {\r\n registerOverlay();\r\n return () => unregisterOverlay();\r\n }, [registerOverlay, unregisterOverlay]);\r\n\r\n useEffect(() => {\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") onClose();\r\n };\r\n document.addEventListener(\"keydown\", handleKeyDown);\r\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\r\n }, [onClose]);\r\n\r\n return createPortal(\r\n <div\r\n className=\"fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 backdrop-blur-sm animate-in fade-in-0 duration-[50ms]\"\r\n onClick={onClose}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label=\"Full size verification image\"\r\n >\r\n <div className=\"relative max-w-[95vw] max-h-[95vh] cursor-zoom-out animate-in zoom-in-95 duration-[50ms]\">\r\n <img\r\n src={src}\r\n alt={alt}\r\n className=\"max-w-full max-h-[95vh] object-contain rounded-lg shadow-2xl\"\r\n draggable={false}\r\n />\r\n </div>\r\n </div>,\r\n document.body\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// INDICATOR COMPONENTS\r\n// =============================================================================\r\n//\r\n// Status indicators show the verification state visually:\r\n//\r\n// | Status | Indicator | Color | searchState.status values |\r\n// |---------------|--------------------| -------|----------------------------------------------|\r\n// | Pending | Spinner | Gray | \"pending\", \"loading\", null/undefined |\r\n// | Verified | Checkmark (✓) | Green | \"found\", \"found_anchor_text_only\", etc. |\r\n// | Partial Match | Checkmark (✓) | Amber | \"found_on_other_page\", \"partial_text_found\" |\r\n// | Not Found | Warning triangle | Red | \"not_found\" |\r\n//\r\n// Use `renderIndicator` prop to customize. Use `variant=\"indicator\"` to show only the icon.\r\n// =============================================================================\r\n\r\n/** Verified indicator - green checkmark for exact matches (subscript-positioned) */\r\nconst VerifiedIndicator = () => (\r\n <span\r\n className=\"inline-flex relative ml-0.5 top-[0.15em] size-2.5 text-green-600 dark:text-green-500\"\r\n aria-hidden=\"true\"\r\n >\r\n <CheckIcon />\r\n </span>\r\n);\r\n\r\n/** Partial match indicator - amber checkmark for partial/relocated matches (subscript-positioned) */\r\nconst PartialIndicator = () => (\r\n <span\r\n className=\"inline-flex relative ml-0.5 top-[0.15em] size-2.5 text-amber-600 dark:text-amber-500\"\r\n aria-hidden=\"true\"\r\n >\r\n <CheckIcon />\r\n </span>\r\n);\r\n\r\n/** Pending indicator - spinner for loading state (subscript-positioned) */\r\nconst PendingIndicator = () => (\r\n <span\r\n className=\"inline-flex relative ml-1 top-[0.15em] size-2.5 animate-spin text-gray-400 dark:text-gray-500\"\r\n aria-hidden=\"true\"\r\n >\r\n <SpinnerIcon />\r\n </span>\r\n);\r\n\r\n/** Miss indicator - amber warning triangle for not found (subscript-positioned) */\r\nconst MissIndicator = () => (\r\n <span\r\n className=\"inline-flex relative ml-0.5 top-[0.15em] size-2.5 text-amber-500 dark:text-amber-400\"\r\n aria-hidden=\"true\"\r\n >\r\n <WarningIcon />\r\n </span>\r\n);\r\n\r\n// =============================================================================\r\n// KEYSPAN FOCUSED IMAGE COMPONENT\r\n// =============================================================================\r\n\r\n/**\r\n * Calculate the bounding box that encompasses all anchorText boxes.\r\n * Falls back to phraseMatchDeepItem if no anchorText boxes are available.\r\n */\r\nfunction getKeySpanBoundingBox(verification: Verification | null): {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n} | null {\r\n if (!verification) return null;\r\n\r\n // Prefer anchorTextMatchDeepItems for multi-box spans\r\n const boxes = verification.anchorTextMatchDeepItems;\r\n if (boxes && boxes.length > 0) {\r\n // Calculate bounding box encompassing all anchorText boxes\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const box of boxes) {\r\n minX = Math.min(minX, box.x);\r\n minY = Math.min(minY, box.y);\r\n maxX = Math.max(maxX, box.x + box.width);\r\n maxY = Math.max(maxY, box.y + box.height);\r\n }\r\n\r\n return {\r\n x: minX,\r\n y: minY,\r\n width: maxX - minX,\r\n height: maxY - minY,\r\n };\r\n }\r\n\r\n // Fall back to phraseMatchDeepItem\r\n const phrase = verification.phraseMatchDeepItem;\r\n if (phrase) {\r\n return {\r\n x: phrase.x,\r\n y: phrase.y,\r\n width: phrase.width,\r\n height: phrase.height,\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Displays a verification image in a scrollable container that initially\r\n * focuses on the anchorText position. Uses the anchorTextMatchDeepItems or\r\n * phraseMatchDeepItem coordinates to calculate the initial scroll position.\r\n */\r\nfunction AnchorTextFocusedImage({\r\n verification,\r\n onImageClick,\r\n maxWidth = \"min(70vw, 384px)\",\r\n maxHeight = \"min(50vh, 300px)\",\r\n}: {\r\n verification: Verification;\r\n onImageClick?: () => void;\r\n maxWidth?: string;\r\n maxHeight?: string;\r\n}) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const imageRef = useRef<HTMLImageElement>(null);\r\n const hasInitializedScrollRef = useRef(false);\r\n\r\n const anchorTextBox = useMemo(\r\n () => getKeySpanBoundingBox(verification),\r\n [verification]\r\n );\r\n\r\n // Set initial scroll position when image loads, only once\r\n const handleImageLoad = useCallback(() => {\r\n if (\r\n hasInitializedScrollRef.current ||\r\n !containerRef.current ||\r\n !imageRef.current ||\r\n !anchorTextBox\r\n ) {\r\n return;\r\n }\r\n\r\n const container = containerRef.current;\r\n const image = imageRef.current;\r\n const imageDimensions = verification.verificationImageDimensions;\r\n\r\n // We need to know the original image dimensions to calculate scale\r\n // If not provided in verification, use the natural image dimensions\r\n const originalWidth = imageDimensions?.width || image.naturalWidth;\r\n const originalHeight = imageDimensions?.height || image.naturalHeight;\r\n\r\n if (originalWidth === 0 || originalHeight === 0) return;\r\n\r\n // Calculate the scale factor: displayed size / original size\r\n const scaleX = image.clientWidth / originalWidth;\r\n const scaleY = image.clientHeight / originalHeight;\r\n\r\n // Calculate the anchorText center in displayed image coordinates\r\n const anchorTextCenterX = (anchorTextBox.x + anchorTextBox.width / 2) * scaleX;\r\n const anchorTextCenterY = (anchorTextBox.y + anchorTextBox.height / 2) * scaleY;\r\n\r\n // Calculate scroll position to center the anchorText in the viewport\r\n // with some vertical bias towards showing content above the anchorText\r\n const scrollX = Math.max(0, anchorTextCenterX - container.clientWidth / 2);\r\n const scrollY = Math.max(0, anchorTextCenterY - container.clientHeight * 0.4);\r\n\r\n container.scrollLeft = scrollX;\r\n container.scrollTop = scrollY;\r\n hasInitializedScrollRef.current = true;\r\n }, [anchorTextBox, verification.verificationImageDimensions]);\r\n\r\n // Reset scroll initialization when verification changes\r\n useEffect(() => {\r\n hasInitializedScrollRef.current = false;\r\n }, [verification.verificationImageBase64]);\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n className=\"group block cursor-zoom-in relative rounded-md bg-gray-50 dark:bg-gray-800\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onImageClick?.();\r\n }}\r\n aria-label=\"Click to view full size\"\r\n >\r\n <div\r\n ref={containerRef}\r\n className=\"overflow-auto rounded-md\"\r\n style={{\r\n maxWidth,\r\n maxHeight,\r\n }}\r\n >\r\n <img\r\n ref={imageRef}\r\n src={verification.verificationImageBase64 as string}\r\n alt=\"Citation verification\"\r\n className=\"block\"\r\n style={{\r\n // Let the image display at its natural size for scrolling,\r\n // but cap it at reasonable maximums for very large images\r\n maxWidth: \"none\",\r\n maxHeight: \"none\",\r\n width: \"auto\",\r\n height: \"auto\",\r\n }}\r\n loading=\"eager\"\r\n decoding=\"async\"\r\n onLoad={handleImageLoad}\r\n />\r\n </div>\r\n {/* Bottom bar with expand hint on hover */}\r\n <span className=\"absolute left-0 right-0 bottom-0 flex items-center justify-end px-2 pb-1.5 pt-4 bg-gradient-to-t from-black/50 to-transparent rounded-b-md pointer-events-none\">\r\n <span className=\"text-xs text-white font-medium drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] opacity-0 group-hover:opacity-100 transition-opacity\">\r\n Click to expand\r\n </span>\r\n </span>\r\n </button>\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// HUMANIZING MESSAGES (Issue #5)\r\n// =============================================================================\r\n\r\n/**\r\n * Get a conversational message for not-found or partial match states.\r\n * Uses the actual anchor text for context, truncating if needed.\r\n */\r\nfunction getHumanizingMessage(\r\n status: SearchStatus | null | undefined,\r\n anchorText?: string,\r\n expectedPage?: number,\r\n foundPage?: number\r\n): string | null {\r\n if (!status) return null;\r\n\r\n const MAX_ANCHOR_LENGTH = 30;\r\n // Type guard: ensure anchorText is a string before using string methods\r\n const safeAnchorText = typeof anchorText === \"string\" ? anchorText : null;\r\n const displayText = safeAnchorText\r\n ? safeAnchorText.length > MAX_ANCHOR_LENGTH\r\n ? `\"${safeAnchorText.slice(0, MAX_ANCHOR_LENGTH)}…\"`\r\n : `\"${safeAnchorText}\"`\r\n : \"this phrase\";\r\n\r\n switch (status) {\r\n case \"not_found\":\r\n return `We couldn't find ${displayText} in this document.`;\r\n case \"found_on_other_page\":\r\n if (expectedPage && foundPage) {\r\n return `Found ${displayText} on page ${foundPage} instead of page ${expectedPage}.`;\r\n }\r\n return `Found ${displayText} on a different page than expected.`;\r\n case \"found_on_other_line\":\r\n return `Found ${displayText} at a different position than expected.`;\r\n case \"partial_text_found\":\r\n return `Only part of ${displayText} was found.`;\r\n case \"first_word_found\":\r\n return `Only the beginning of ${displayText} was found.`;\r\n case \"found_anchor_text_only\":\r\n return `Found ${displayText}, but not the full surrounding context.`;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\n// =============================================================================\r\n// POPOVER CONTENT COMPONENT\r\n// =============================================================================\r\n\r\ninterface PopoverContentProps {\r\n citation: BaseCitationProps[\"citation\"];\r\n verification: Verification | null;\r\n status: CitationStatus;\r\n onImageClick?: () => void;\r\n isLoading?: boolean;\r\n isPhrasesExpanded?: boolean;\r\n onPhrasesExpandChange?: (expanded: boolean) => void;\r\n /** Whether the popover is currently visible (used for Activity prefetching) */\r\n isVisible?: boolean;\r\n}\r\n\r\n/**\r\n * Get border color class based on search attempt success and trust level.\r\n * - Green: Successful match with high/medium trust\r\n * - Amber: Successful match with low trust\r\n * - Red: Failed search attempt\r\n */\r\nfunction getSearchAttemptBorderClass(attempt: SearchAttempt): string {\r\n if (!attempt.success) {\r\n return \"border-red-400 dark:border-red-500\";\r\n }\r\n if (isLowTrustMatch(attempt.matchedVariation)) {\r\n return \"border-amber-400 dark:border-amber-500\";\r\n }\r\n return \"border-green-400 dark:border-green-500\";\r\n}\r\n\r\n/**\r\n * Component to display searched phrases from search attempts.\r\n * Groups similar attempts together for a cleaner display:\r\n * - Same phrase searched on multiple pages → shows once with page summary\r\n * - Shows methods used and variations tried\r\n * - Highlights successful vs failed attempts\r\n */\r\nfunction SearchedPhrasesInfo({\r\n citation,\r\n verification,\r\n isExpanded: externalIsExpanded,\r\n onExpandChange,\r\n}: {\r\n citation: BaseCitationProps[\"citation\"];\r\n verification: Verification | null;\r\n isExpanded?: boolean;\r\n onExpandChange?: (expanded: boolean) => void;\r\n}) {\r\n // Get search attempts from verification, or create fallback from citation\r\n const searchAttempts = useMemo(() => {\r\n if (verification?.searchAttempts && verification.searchAttempts.length > 0) {\r\n return verification.searchAttempts;\r\n }\r\n\r\n // Fallback: create synthetic attempts from citation data\r\n const fallbackAttempts: SearchAttempt[] = [];\r\n if (citation.fullPhrase) {\r\n fallbackAttempts.push({\r\n method: \"current_page\",\r\n success: false,\r\n searchPhrase: citation.fullPhrase,\r\n searchPhraseType: \"full_phrase\",\r\n });\r\n }\r\n // Also add anchorText as a separate fallback if it differs from fullPhrase\r\n if (citation.anchorText && citation.anchorText !== citation.fullPhrase) {\r\n fallbackAttempts.push({\r\n method: \"anchor_text_fallback\",\r\n success: false,\r\n searchPhrase: citation.anchorText.toString(),\r\n searchPhraseType: \"anchor_text\",\r\n });\r\n }\r\n return fallbackAttempts;\r\n }, [citation, verification]);\r\n\r\n // Group attempts by unique phrase for cleaner display\r\n const groupedAttempts = useMemo(\r\n () => groupSearchAttempts(searchAttempts),\r\n [searchAttempts]\r\n );\r\n\r\n const [internalIsExpanded, setInternalIsExpanded] = useState(false);\r\n\r\n // Use external state if provided, otherwise internal\r\n const isExpanded = externalIsExpanded ?? internalIsExpanded;\r\n const setIsExpanded = useCallback((expanded: boolean) => {\r\n if (onExpandChange) {\r\n onExpandChange(expanded);\r\n } else {\r\n setInternalIsExpanded(expanded);\r\n }\r\n }, [onExpandChange]);\r\n\r\n if (groupedAttempts.length === 0) return null;\r\n\r\n // Calculate pages searched across all attempts\r\n const allPagesSearched = new Set<number>();\r\n for (const group of groupedAttempts) {\r\n for (const page of group.pagesSearched) {\r\n if (page != null) allPagesSearched.add(page);\r\n }\r\n }\r\n const pagesSearchedCount = allPagesSearched.size;\r\n\r\n // Show first DEFAULT_VISIBLE_GROUP_COUNT groups by default (usually fullPhrase + anchorText), expand to show all\r\n const defaultDisplayCount = Math.min(DEFAULT_VISIBLE_GROUP_COUNT, groupedAttempts.length);\r\n const displayCount = isExpanded ? groupedAttempts.length : defaultDisplayCount;\r\n const hiddenGroupCount = groupedAttempts.length - defaultDisplayCount;\r\n\r\n return (\r\n <div className=\"mt-1\">\r\n {/* Summary header showing what was searched */}\r\n <div className=\"text-[10px] text-gray-600 dark:text-gray-400 mb-2\">\r\n Searched {pagesSearchedCount > 1 ? `${pagesSearchedCount} pages` : pagesSearchedCount === 1 ? \"1 page\" : \"document\"}\r\n {hiddenGroupCount > 0 && (\r\n <button\r\n type=\"button\"\r\n onClick={() => setIsExpanded(!isExpanded)}\r\n className=\"ml-2 text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300\"\r\n >\r\n {isExpanded ? \"show less\" : `show all ${groupedAttempts.length} phrases`}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Search phrase list */}\r\n <div className=\"space-y-2\">\r\n {groupedAttempts.slice(0, displayCount).map((group, index) => (\r\n <SearchAttemptRow key={index} group={group} />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * Compact single-row display for a grouped search attempt.\r\n * Shows phrase, metadata badges, and result on one or two lines.\r\n * Uses cleaner, less colorful design with monochrome badges.\r\n */\r\nfunction SearchAttemptRow({ group }: { group: GroupedSearchAttempt }) {\r\n // Truncate phrase for display\r\n const displayPhrase = group.phrase.length > MAX_PHRASE_LENGTH\r\n ? group.phrase.slice(0, MAX_PHRASE_LENGTH) + \"…\"\r\n : group.phrase;\r\n\r\n // Build location info string\r\n const validPages = group.pagesSearched.filter((p): p is number => p != null);\r\n const locationInfo = validPages.length > 0\r\n ? formatPageList(validPages)\r\n : \"entire document\";\r\n\r\n // Status indicator - only icon is colored\r\n const statusIndicator = group.anySuccess ? (\r\n <span className={cn(\r\n \"inline-flex size-3 flex-shrink-0\",\r\n isLowTrustMatch(group.successfulAttempt?.matchedVariation)\r\n ? \"text-amber-600 dark:text-amber-400\"\r\n : \"text-green-600 dark:text-green-400\"\r\n )}>\r\n <CheckIcon />\r\n </span>\r\n ) : (\r\n <span className=\"inline-flex size-3 flex-shrink-0 text-gray-500 dark:text-gray-400\">\r\n <CloseIcon />\r\n </span>\r\n );\r\n\r\n // Phrase type label\r\n const phraseTypeLabel = group.phraseType === \"anchor_text\" ? \"Key phrase\" : \"Full phrase\";\r\n\r\n // For failed attempts, show variations that were also searched\r\n const visibleVariations = group.variationsTried.slice(0, MAX_VISIBLE_VARIATIONS);\r\n const hiddenVariationsCount = group.variationsTried.length - MAX_VISIBLE_VARIATIONS;\r\n\r\n return (\r\n <div className=\"p-2 bg-gray-50 dark:bg-gray-800/40 rounded-md\">\r\n {/* Phrase type and location - monochrome */}\r\n <div className=\"flex items-center justify-between text-[10px] text-gray-500 dark:text-gray-400 mb-1\">\r\n <span className=\"font-medium\">{phraseTypeLabel}</span>\r\n <span>{locationInfo}</span>\r\n </div>\r\n\r\n {/* The searched phrase */}\r\n <div className=\"flex items-start gap-1.5\">\r\n <p className=\"font-mono text-[11px] text-gray-700 dark:text-gray-200 break-words flex-1\">\r\n \"{displayPhrase}\"\r\n </p>\r\n {statusIndicator}\r\n </div>\r\n\r\n {/* Result line for successful matches */}\r\n {group.anySuccess && group.successfulAttempt?.matchedText &&\r\n group.successfulAttempt.matchedText !== group.phrase && (\r\n <p className=\"text-[10px] text-green-600 dark:text-green-400 truncate mt-1\">\r\n Found: \"{group.successfulAttempt.matchedText.slice(0, MAX_MATCHED_TEXT_LENGTH)}{group.successfulAttempt.matchedText.length > MAX_MATCHED_TEXT_LENGTH ? \"…\" : \"\"}\"\r\n </p>\r\n )}\r\n\r\n {/* Detailed info for failed attempts */}\r\n {!group.anySuccess && (\r\n <>\r\n {/* Variations that were also searched */}\r\n {visibleVariations.length > 0 && (\r\n <div className=\"text-[10px] text-gray-500 dark:text-gray-400 mt-1\">\r\n <span className=\"font-medium\">Also tried: </span>\r\n {visibleVariations.map((variation, index) => {\r\n const truncatedVar = variation.length > MAX_VARIATION_LENGTH\r\n ? variation.slice(0, MAX_VARIATION_LENGTH) + \"…\"\r\n : variation;\r\n return (\r\n <span key={index}>\r\n <span className=\"font-mono\">\"{truncatedVar}\"</span>\r\n {index < visibleVariations.length - 1 && \", \"}\r\n </span>\r\n );\r\n })}\r\n {hiddenVariationsCount > 0 && (\r\n <span className=\"text-gray-400 dark:text-gray-500\">\r\n {\" \"}+{hiddenVariationsCount} more\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Notes (if any, for additional context) */}\r\n {group.uniqueNotes.length > 0 && (\r\n <p className=\"text-[10px] text-gray-400 dark:text-gray-500 mt-1\">\r\n {group.uniqueNotes[0]}\r\n </p>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction DefaultPopoverContent({\r\n citation,\r\n verification,\r\n status,\r\n onImageClick,\r\n isLoading = false,\r\n isPhrasesExpanded,\r\n onPhrasesExpandChange,\r\n isVisible = true,\r\n}: PopoverContentProps) {\r\n const hasImage = verification?.verificationImageBase64;\r\n const { isMiss, isPartialMatch, isPending, isVerified } = status;\r\n const searchStatus = verification?.status;\r\n\r\n // Check if we have anchorText position data for focused scrolling\r\n const hasAnchorTextPosition = !!(\r\n verification &&\r\n (verification.anchorTextMatchDeepItems?.length ||\r\n verification.phraseMatchDeepItem)\r\n );\r\n\r\n // Determine if we should show the verification log (for non-success states)\r\n const showVerificationLog = isMiss || isPartialMatch;\r\n\r\n // Determine if this is a \"clean\" success (no log needed)\r\n const isCleanSuccess = isVerified && !isPartialMatch && !isMiss;\r\n\r\n // Get page/line info for the log\r\n const expectedPage = citation.pageNumber;\r\n const expectedLine = citation.lineIds?.[0];\r\n const foundPage = verification?.verifiedPageNumber ?? undefined;\r\n const foundLine = verification?.verifiedLineIds?.[0];\r\n\r\n // Get humanizing message for partial/not-found states\r\n const anchorText = citation.anchorText?.toString();\r\n const fullPhrase = citation.fullPhrase;\r\n const humanizingMessage = useMemo(\r\n () => getHumanizingMessage(searchStatus, anchorText, expectedPage ?? undefined, foundPage),\r\n [searchStatus, anchorText, expectedPage, foundPage]\r\n );\r\n\r\n // Loading/pending state view\r\n if (isLoading || isPending) {\r\n const searchingPhrase = fullPhrase || anchorText;\r\n return (\r\n <div className=\"p-3 flex flex-col gap-2 min-w-[200px] max-w-[400px]\">\r\n <span className=\"text-xs font-medium text-gray-600 dark:text-gray-300\">\r\n <span className=\"inline-block relative top-[0.1em] mr-1.5 size-2 animate-spin\">\r\n <SpinnerIcon />\r\n </span>\r\n Searching...\r\n </span>\r\n {searchingPhrase && (\r\n <p className=\"p-2 bg-gray-50 dark:bg-gray-800/50 rounded font-mono text-[11px] break-words text-gray-700 dark:text-gray-300\">\r\n \"{searchingPhrase.length > 80 ? searchingPhrase.slice(0, 80) + '…' : searchingPhrase}\"\r\n </p>\r\n )}\r\n {citation.pageNumber && citation.pageNumber > 0 && (\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n Looking on page {citation.pageNumber}\r\n </span>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // ==========================================================================\r\n // SUCCESS STATE (Green) - Header + Image + optional expandable search details\r\n // ==========================================================================\r\n if (isCleanSuccess && hasImage && verification) {\r\n return (\r\n <Activity mode={isVisible ? \"visible\" : \"hidden\"}>\r\n <div className=\"overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-md\" style={{ width: POPOVER_WIDTH, maxWidth: POPOVER_MAX_WIDTH }}>\r\n {/* Green status header - show expected page */}\r\n <StatusHeader status={searchStatus} foundPage={foundPage} expectedPage={expectedPage ?? undefined} />\r\n\r\n {/* Verification image */}\r\n <div className=\"p-2\">\r\n {hasAnchorTextPosition ? (\r\n <AnchorTextFocusedImage\r\n verification={verification}\r\n onImageClick={onImageClick}\r\n />\r\n ) : (\r\n <button\r\n type=\"button\"\r\n className=\"group block cursor-zoom-in relative overflow-hidden rounded-md bg-gray-50 dark:bg-gray-800 w-full\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onImageClick?.();\r\n }}\r\n aria-label=\"Click to view full size\"\r\n >\r\n <img\r\n src={verification.verificationImageBase64 as string}\r\n alt=\"Citation verification\"\r\n className=\"block rounded-md w-full\"\r\n style={{\r\n maxHeight: \"min(50vh, 300px)\",\r\n objectFit: \"contain\",\r\n }}\r\n loading=\"eager\"\r\n decoding=\"async\"\r\n />\r\n <span className=\"absolute left-0 right-0 bottom-0 flex items-center justify-end px-2 pb-1.5 pt-4 bg-gradient-to-t from-black/50 to-transparent rounded-b-md\">\r\n <span className=\"text-xs text-white font-medium drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] opacity-0 group-hover:opacity-100 transition-opacity\">\r\n Click to expand\r\n </span>\r\n </span>\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Expandable search details for verified matches */}\r\n {verification.searchAttempts && verification.searchAttempts.length > 0 && (\r\n <VerificationLog\r\n searchAttempts={verification.searchAttempts}\r\n status={searchStatus}\r\n expectedPage={expectedPage ?? undefined}\r\n expectedLine={expectedLine}\r\n foundPage={foundPage}\r\n foundLine={foundLine}\r\n isExpanded={isPhrasesExpanded}\r\n onExpandChange={onPhrasesExpandChange}\r\n fullPhrase={fullPhrase ?? undefined}\r\n anchorText={anchorText}\r\n />\r\n )}\r\n </div>\r\n </Activity>\r\n );\r\n }\r\n\r\n // ==========================================================================\r\n // PARTIAL/DISPLACED STATE (Amber) or NOT FOUND (Red) - Full layout\r\n // ==========================================================================\r\n if (isMiss || isPartialMatch) {\r\n return (\r\n <Activity mode={isVisible ? \"visible\" : \"hidden\"}>\r\n <div className=\"overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-md\" style={{ width: POPOVER_WIDTH, maxWidth: POPOVER_MAX_WIDTH }}>\r\n {/* Content area: Image with simple header, OR combined status header with quote */}\r\n {hasImage && verification ? (\r\n // Show simple header + image (for partial matches that have images)\r\n <>\r\n <StatusHeader status={searchStatus} foundPage={foundPage} expectedPage={expectedPage ?? undefined} />\r\n {/* Humanizing message for partial matches with images */}\r\n {humanizingMessage && (\r\n <div className=\"px-4 py-2 text-sm text-gray-600 dark:text-gray-300 border-b border-gray-100 dark:border-gray-800\">\r\n {humanizingMessage}\r\n </div>\r\n )}\r\n <div className=\"p-2\">\r\n {hasAnchorTextPosition ? (\r\n <AnchorTextFocusedImage\r\n verification={verification}\r\n onImageClick={onImageClick}\r\n />\r\n ) : (\r\n <button\r\n type=\"button\"\r\n className=\"group block cursor-zoom-in relative overflow-hidden rounded-md bg-gray-50 dark:bg-gray-800 w-full\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onImageClick?.();\r\n }}\r\n aria-label=\"Click to view full size\"\r\n >\r\n <img\r\n src={verification.verificationImageBase64 as string}\r\n alt=\"Citation verification\"\r\n className=\"block rounded-md w-full\"\r\n style={{\r\n maxHeight: \"min(50vh, 300px)\",\r\n objectFit: \"contain\",\r\n }}\r\n loading=\"eager\"\r\n decoding=\"async\"\r\n />\r\n <span className=\"absolute left-0 right-0 bottom-0 flex items-center justify-end px-2 pb-1.5 pt-4 bg-gradient-to-t from-black/50 to-transparent rounded-b-md\">\r\n <span className=\"text-xs text-white font-medium drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] opacity-0 group-hover:opacity-100 transition-opacity\">\r\n Click to expand\r\n </span>\r\n </span>\r\n </button>\r\n )}\r\n </div>\r\n </>\r\n ) : (\r\n // Combined header with anchor text and quote (for not_found or partial without image)\r\n // When humanizingMessage exists, skip anchorText in header to avoid redundancy\r\n // (humanizingMessage already contains the anchor text in quotes)\r\n <>\r\n <StatusHeader\r\n status={searchStatus}\r\n foundPage={foundPage}\r\n expectedPage={expectedPage ?? undefined}\r\n anchorText={humanizingMessage ? undefined : anchorText}\r\n fullPhrase={humanizingMessage ? undefined : (fullPhrase ?? undefined)}\r\n />\r\n {/* Humanizing message replaces the anchor text display */}\r\n {humanizingMessage && (\r\n <div className=\"px-4 py-3 text-sm text-gray-600 dark:text-gray-300\">\r\n {humanizingMessage}\r\n </div>\r\n )}\r\n </>\r\n )}\r\n\r\n {/* Verification log (collapsible) */}\r\n {showVerificationLog && verification?.searchAttempts && (\r\n <VerificationLog\r\n searchAttempts={verification.searchAttempts}\r\n status={searchStatus}\r\n expectedPage={expectedPage ?? undefined}\r\n expectedLine={expectedLine}\r\n foundPage={foundPage}\r\n foundLine={foundLine}\r\n isExpanded={isPhrasesExpanded}\r\n onExpandChange={onPhrasesExpandChange}\r\n fullPhrase={fullPhrase ?? undefined}\r\n anchorText={anchorText}\r\n />\r\n )}\r\n </div>\r\n </Activity>\r\n );\r\n }\r\n\r\n // ==========================================================================\r\n // FALLBACK: Text-only view (verified/partial match without image)\r\n // ==========================================================================\r\n const statusLabel = getStatusLabel(status);\r\n const hasSnippet = verification?.verifiedMatchSnippet;\r\n const pageNumber = verification?.verifiedPageNumber;\r\n\r\n if (!hasSnippet && !statusLabel) return null;\r\n\r\n return (\r\n <div className=\"p-3 flex flex-col gap-2 min-w-[180px] max-w-full\">\r\n {statusLabel && (\r\n <span\r\n className={cn(\r\n \"text-xs font-medium\",\r\n status.isVerified &&\r\n !status.isPartialMatch &&\r\n \"text-green-600 dark:text-green-400\",\r\n status.isPartialMatch && \"text-amber-600 dark:text-amber-400\",\r\n status.isMiss && \"text-red-500 dark:text-red-400\",\r\n status.isPending && \"text-gray-500 dark:text-gray-400\"\r\n )}\r\n >\r\n {statusLabel}\r\n </span>\r\n )}\r\n {hasSnippet && (\r\n <span className=\"text-sm text-gray-700 dark:text-gray-200\">\r\n \"{verification.verifiedMatchSnippet}\"\r\n </span>\r\n )}\r\n {pageNumber && pageNumber > 0 && (\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n Page {pageNumber}\r\n </span>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// DIFF DETAILS COMPONENT\r\n// =============================================================================\r\n\r\n/**\r\n * Renders diff highlighting between expected citation text and actual found text.\r\n * Uses split view for high-variance diffs and inline diff for low-variance.\r\n */\r\nfunction DiffDetails({\r\n citation,\r\n verification,\r\n status,\r\n}: {\r\n citation: BaseCitationProps[\"citation\"];\r\n verification: Verification | null;\r\n status: CitationStatus;\r\n}) {\r\n const { isMiss, isPartialMatch } = status;\r\n\r\n const expectedText =\r\n citation.fullPhrase || citation.anchorText?.toString() || \"\";\r\n const actualText = verification?.verifiedMatchSnippet || \"\";\r\n\r\n // Use the diff library for smart word-level diffing\r\n const { hasDiff, similarity } = useSmartDiff(\r\n expectedText,\r\n actualText\r\n );\r\n\r\n if (!isMiss && !isPartialMatch) return null;\r\n\r\n const expectedLineIds = citation.lineIds;\r\n const actualLineIds = verification?.verifiedLineIds;\r\n const lineIdDiffers =\r\n expectedLineIds &&\r\n actualLineIds &&\r\n JSON.stringify(expectedLineIds) !== JSON.stringify(actualLineIds);\r\n\r\n const expectedPage = citation.pageNumber;\r\n const actualPage = verification?.verifiedPageNumber;\r\n const pageDiffers =\r\n expectedPage != null && actualPage != null && expectedPage !== actualPage;\r\n\r\n // Get contextual status message\r\n const searchStatus = verification?.status;\r\n const statusMessage = getContextualStatusMessage(searchStatus, expectedPage, actualPage);\r\n\r\n // For \"not_found\" status, show expected text and \"Not found\" message\r\n if (isMiss) {\r\n return (\r\n <div className=\"mt-2 pt-2 border-t border-gray-200 dark:border-gray-700 text-xs space-y-2\">\r\n {expectedText && (\r\n <SplitDiffDisplay\r\n expected={expectedText}\r\n actual=\"\"\r\n mode=\"split\"\r\n showMatchQuality={false}\r\n maxCollapsedLength={150}\r\n anchorTextExpected={citation.anchorText?.toString()}\r\n status={searchStatus}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // For partial matches, show enhanced diff with split view\r\n return (\r\n <div className=\"mt-2 pt-2 border-t border-gray-200 dark:border-gray-700 text-xs space-y-2\">\r\n {/* Contextual status message */}\r\n {statusMessage && searchStatus !== \"found\" && (\r\n <div className={cn(\r\n \"text-[10px] font-medium px-1.5 py-0.5 rounded inline-flex items-center gap-1\",\r\n \"bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400\"\r\n )}>\r\n <span className=\"size-2\">\r\n <CheckIcon />\r\n </span>\r\n {statusMessage}\r\n </div>\r\n )}\r\n\r\n {expectedText && actualText && hasDiff ? (\r\n <SplitDiffDisplay\r\n expected={expectedText}\r\n actual={actualText}\r\n mode=\"split\"\r\n showMatchQuality={true}\r\n maxCollapsedLength={150}\r\n anchorTextExpected={citation.anchorText?.toString()}\r\n anchorTextFound={verification?.verifiedAnchorText ?? undefined}\r\n status={searchStatus}\r\n similarity={similarity}\r\n />\r\n ) : expectedText && !hasDiff ? (\r\n // Text matches exactly (partial match is due to location difference)\r\n <div>\r\n <div className=\"inline-flex items-center gap-1.5 text-green-600 dark:text-green-500 text-[10px] font-medium mb-1\">\r\n <span className=\"size-2\">\r\n <CheckIcon />\r\n </span>\r\n <span>Text matches</span>\r\n </div>\r\n <p className=\"p-2 bg-gray-100 dark:bg-gray-800 rounded font-mono text-[11px] break-words text-gray-700 dark:text-gray-300\">\r\n {expectedText.length > 150\r\n ? expectedText.slice(0, 150) + \"…\"\r\n : expectedText}\r\n </p>\r\n </div>\r\n ) : null}\r\n\r\n {/* Location differences */}\r\n {(pageDiffers || lineIdDiffers) && (\r\n <div className=\"flex flex-wrap gap-3 pt-1\">\r\n {pageDiffers && (\r\n <div className=\"flex items-center gap-1.5\">\r\n <span className=\"text-gray-500 dark:text-gray-400 font-medium uppercase text-[10px]\">\r\n Page:\r\n </span>\r\n <span className=\"font-mono text-[11px]\">\r\n <span className=\"text-red-600 dark:text-red-400 line-through opacity-70\">\r\n {expectedPage}\r\n </span>\r\n <span className=\"text-gray-400 mx-1\">→</span>\r\n <span className=\"text-green-600 dark:text-green-400\">\r\n {actualPage}\r\n </span>\r\n </span>\r\n </div>\r\n )}\r\n {lineIdDiffers && (\r\n <div className=\"flex items-center gap-1.5\">\r\n <span className=\"text-gray-500 dark:text-gray-400 font-medium uppercase text-[10px]\">\r\n Line:\r\n </span>\r\n <span className=\"font-mono text-[11px]\">\r\n <span className=\"text-red-600 dark:text-red-400 line-through opacity-70\">\r\n {expectedLineIds?.join(\", \")}\r\n </span>\r\n <span className=\"text-gray-400 mx-1\">→</span>\r\n <span className=\"text-green-600 dark:text-green-400\">\r\n {actualLineIds?.join(\", \")}\r\n </span>\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// MAIN COMPONENT\r\n// =============================================================================\r\n\r\n/**\r\n * CitationComponent displays a citation with verification status.\r\n *\r\n * ## Interaction Pattern\r\n *\r\n * - **Hover**: Shows popover with verification image or details\r\n * - **Click**: Opens full-size image overlay (if image available)\r\n * - **Escape / Click overlay**: Closes the image overlay\r\n *\r\n * ## Customization\r\n *\r\n * Use `behaviorConfig.onClick` to completely replace the click behavior,\r\n * or `eventHandlers.onClick` to add side effects (which disables defaults).\r\n */\r\nexport const CitationComponent = forwardRef<\r\n HTMLSpanElement,\r\n CitationComponentProps\r\n>(\r\n (\r\n {\r\n citation,\r\n children,\r\n className,\r\n fallbackDisplay,\r\n verification,\r\n isLoading = false,\r\n variant = \"brackets\",\r\n content: contentProp,\r\n eventHandlers,\r\n behaviorConfig,\r\n isMobile = false,\r\n renderIndicator,\r\n renderContent,\r\n popoverPosition = \"top\",\r\n renderPopoverContent,\r\n additionalCount,\r\n faviconUrl,\r\n showIndicator = true,\r\n },\r\n ref\r\n ) => {\r\n // Get overlay context for blocking hover when any image overlay is open\r\n const { isAnyOverlayOpen } = useCitationOverlay();\r\n\r\n // Resolve content: explicit content prop or default for variant\r\n const resolvedContent: CitationContent = useMemo(() => {\r\n if (contentProp) return contentProp;\r\n return getDefaultContent(variant);\r\n }, [contentProp, variant]);\r\n const [isHovering, setIsHovering] = useState(false);\r\n const [expandedImageSrc, setExpandedImageSrc] = useState<string | null>(\r\n null\r\n );\r\n const [isPhrasesExpanded, setIsPhrasesExpanded] = useState(false);\r\n // Track if popover was already open before current interaction (for mobile tap-to-expand)\r\n const wasPopoverOpenBeforeTap = useRef(false);\r\n\r\n const citationKey = useMemo(\r\n () => generateCitationKey(citation),\r\n [citation]\r\n );\r\n const citationInstanceId = useMemo(\r\n () => generateCitationInstanceId(citationKey),\r\n [citationKey]\r\n );\r\n\r\n // Derive status from verification object\r\n const status = useMemo(\r\n () => getStatusFromVerification(verification),\r\n [verification]\r\n );\r\n const { isMiss, isPartialMatch, isVerified, isPending } = status;\r\n\r\n // Spinner timeout: auto-hide after ~5s if still pending\r\n const SPINNER_TIMEOUT_MS = 5000;\r\n const [spinnerTimedOut, setSpinnerTimedOut] = useState(false);\r\n const spinnerTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\r\n // Determine if we should show spinner:\r\n // - explicit isLoading prop OR isPending status\r\n // - BUT NOT if we have a verification image or definitive status\r\n // - AND NOT if spinner has timed out\r\n const hasDefinitiveResult =\r\n verification?.verificationImageBase64 ||\r\n verification?.status === \"found\" ||\r\n verification?.status === \"found_anchor_text_only\" ||\r\n verification?.status === \"found_phrase_missed_anchor_text\" ||\r\n verification?.status === \"not_found\" ||\r\n verification?.status === \"partial_text_found\" ||\r\n verification?.status === \"found_on_other_page\" ||\r\n verification?.status === \"found_on_other_line\" ||\r\n verification?.status === \"first_word_found\";\r\n\r\n const shouldShowSpinner =\r\n (isLoading || isPending) && !hasDefinitiveResult && !spinnerTimedOut;\r\n\r\n // Reset spinner timeout when loading state changes\r\n useEffect(() => {\r\n // Clear any existing timeout\r\n if (spinnerTimeoutRef.current) {\r\n clearTimeout(spinnerTimeoutRef.current);\r\n spinnerTimeoutRef.current = null;\r\n }\r\n\r\n // If we should show spinner, start timeout\r\n if ((isLoading || isPending) && !hasDefinitiveResult) {\r\n setSpinnerTimedOut(false);\r\n spinnerTimeoutRef.current = setTimeout(() => {\r\n setSpinnerTimedOut(true);\r\n }, SPINNER_TIMEOUT_MS);\r\n } else {\r\n // Reset timed out state when we get a result\r\n setSpinnerTimedOut(false);\r\n }\r\n\r\n return () => {\r\n if (spinnerTimeoutRef.current) {\r\n clearTimeout(spinnerTimeoutRef.current);\r\n }\r\n };\r\n }, [isLoading, isPending, hasDefinitiveResult]);\r\n\r\n const displayText = useMemo(() => {\r\n return getDisplayText(citation, resolvedContent, fallbackDisplay);\r\n }, [citation, resolvedContent, fallbackDisplay]);\r\n\r\n // Behavior context for custom handlers\r\n const getBehaviorContext = useCallback(\r\n (): CitationBehaviorContext => ({\r\n citation,\r\n citationKey,\r\n verification: verification ?? null,\r\n isTooltipExpanded: isHovering,\r\n isImageExpanded: !!expandedImageSrc,\r\n hasImage: !!verification?.verificationImageBase64,\r\n }),\r\n [citation, citationKey, verification, isHovering, expandedImageSrc]\r\n );\r\n\r\n // Apply behavior actions from custom handler\r\n const applyBehaviorActions = useCallback(\r\n (actions: CitationBehaviorActions) => {\r\n if (actions.setImageExpanded !== undefined) {\r\n if (typeof actions.setImageExpanded === \"string\") {\r\n setExpandedImageSrc(actions.setImageExpanded);\r\n } else if (\r\n actions.setImageExpanded === true &&\r\n verification?.verificationImageBase64\r\n ) {\r\n setExpandedImageSrc(verification.verificationImageBase64);\r\n } else if (actions.setImageExpanded === false) {\r\n setExpandedImageSrc(null);\r\n }\r\n }\r\n },\r\n [verification?.verificationImageBase64]\r\n );\r\n\r\n // Click handler\r\n const handleClick = useCallback(\r\n (e: React.MouseEvent<HTMLSpanElement>) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n const context = getBehaviorContext();\r\n\r\n // Custom onClick via behaviorConfig replaces default\r\n if (behaviorConfig?.onClick) {\r\n const result = behaviorConfig.onClick(context, e);\r\n if (result && typeof result === \"object\") {\r\n applyBehaviorActions(result);\r\n }\r\n eventHandlers?.onClick?.(citation, citationKey, e);\r\n return;\r\n }\r\n\r\n // Custom eventHandlers.onClick disables default\r\n if (eventHandlers?.onClick) {\r\n eventHandlers.onClick(citation, citationKey, e);\r\n return;\r\n }\r\n\r\n // On mobile: first tap shows popover, second tap (when popover already open) opens image\r\n // wasPopoverOpenBeforeTap is set in handleTouchStart before the click fires\r\n if (isMobile && !wasPopoverOpenBeforeTap.current) {\r\n // First tap on mobile: just show popover (already triggered by touch events)\r\n // Don't open the image overlay yet\r\n setIsHovering(true);\r\n return;\r\n }\r\n\r\n // Default: click opens image if available, or toggles phrases expansion for miss state\r\n if (verification?.verificationImageBase64) {\r\n setExpandedImageSrc(verification.verificationImageBase64);\r\n } else if (isMiss) {\r\n // For miss state without image, toggle phrases expansion\r\n setIsPhrasesExpanded((prev) => !prev);\r\n }\r\n },\r\n [\r\n behaviorConfig,\r\n eventHandlers,\r\n citation,\r\n citationKey,\r\n verification?.verificationImageBase64,\r\n isMiss,\r\n isMobile,\r\n getBehaviorContext,\r\n applyBehaviorActions,\r\n ]\r\n );\r\n\r\n // Hover handlers with delay for popover accessibility\r\n // Use a timeout to allow user to move mouse from trigger to popover\r\n const HOVER_CLOSE_DELAY_MS = 150;\r\n const hoverCloseTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const isOverPopoverRef = useRef(false);\r\n\r\n const cancelHoverCloseTimeout = useCallback(() => {\r\n if (hoverCloseTimeoutRef.current) {\r\n clearTimeout(hoverCloseTimeoutRef.current);\r\n hoverCloseTimeoutRef.current = null;\r\n }\r\n }, []);\r\n\r\n const handleMouseEnter = useCallback(() => {\r\n // Don't trigger hover popover if any image overlay is expanded\r\n if (isAnyOverlayOpen) return;\r\n\r\n cancelHoverCloseTimeout();\r\n setIsHovering(true);\r\n if (behaviorConfig?.onHover?.onEnter) {\r\n behaviorConfig.onHover.onEnter(getBehaviorContext());\r\n }\r\n eventHandlers?.onMouseEnter?.(citation, citationKey);\r\n }, [\r\n eventHandlers,\r\n behaviorConfig,\r\n citation,\r\n citationKey,\r\n getBehaviorContext,\r\n cancelHoverCloseTimeout,\r\n isAnyOverlayOpen,\r\n ]);\r\n\r\n const handleMouseLeave = useCallback(() => {\r\n // Delay closing to allow mouse to move to popover\r\n cancelHoverCloseTimeout();\r\n hoverCloseTimeoutRef.current = setTimeout(() => {\r\n if (!isOverPopoverRef.current) {\r\n setIsHovering(false);\r\n if (behaviorConfig?.onHover?.onLeave) {\r\n behaviorConfig.onHover.onLeave(getBehaviorContext());\r\n }\r\n eventHandlers?.onMouseLeave?.(citation, citationKey);\r\n }\r\n }, HOVER_CLOSE_DELAY_MS);\r\n }, [\r\n eventHandlers,\r\n behaviorConfig,\r\n citation,\r\n citationKey,\r\n getBehaviorContext,\r\n cancelHoverCloseTimeout,\r\n ]);\r\n\r\n // Popover content hover handlers\r\n const handlePopoverMouseEnter = useCallback(() => {\r\n cancelHoverCloseTimeout();\r\n isOverPopoverRef.current = true;\r\n }, [cancelHoverCloseTimeout]);\r\n\r\n const handlePopoverMouseLeave = useCallback(() => {\r\n isOverPopoverRef.current = false;\r\n // Delay closing to allow mouse to move back to trigger\r\n cancelHoverCloseTimeout();\r\n hoverCloseTimeoutRef.current = setTimeout(() => {\r\n setIsHovering(false);\r\n if (behaviorConfig?.onHover?.onLeave) {\r\n behaviorConfig.onHover.onLeave(getBehaviorContext());\r\n }\r\n eventHandlers?.onMouseLeave?.(citation, citationKey);\r\n }, HOVER_CLOSE_DELAY_MS);\r\n }, [\r\n eventHandlers,\r\n behaviorConfig,\r\n citation,\r\n citationKey,\r\n getBehaviorContext,\r\n cancelHoverCloseTimeout,\r\n ]);\r\n\r\n // Cleanup hover timeout on unmount\r\n useEffect(() => {\r\n return () => {\r\n if (hoverCloseTimeoutRef.current) {\r\n clearTimeout(hoverCloseTimeoutRef.current);\r\n }\r\n };\r\n }, []);\r\n\r\n // Touch start handler for mobile - captures popover state before click fires\r\n const handleTouchStart = useCallback(\r\n (e: React.TouchEvent<HTMLSpanElement>) => {\r\n if (isMobile) {\r\n // Capture whether popover was already open before this tap\r\n // This is used in handleClick to determine first vs second tap behavior\r\n wasPopoverOpenBeforeTap.current = isHovering;\r\n }\r\n },\r\n [isMobile, isHovering]\r\n );\r\n\r\n // Touch handler for mobile\r\n const handleTouchEnd = useCallback(\r\n (e: React.TouchEvent<HTMLSpanElement>) => {\r\n if (isMobile) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n eventHandlers?.onTouchEnd?.(citation, citationKey, e);\r\n }\r\n },\r\n [eventHandlers, citation, citationKey, isMobile]\r\n );\r\n\r\n // Early return for miss with fallback display (only when showing anchorText)\r\n if (\r\n fallbackDisplay !== null &&\r\n fallbackDisplay !== undefined &&\r\n resolvedContent === \"anchorText\" &&\r\n isMiss\r\n ) {\r\n return (\r\n <span className={cn(\"text-gray-400 dark:text-gray-500\", className)}>\r\n {fallbackDisplay}\r\n </span>\r\n );\r\n }\r\n\r\n // Status classes for text styling\r\n // Variants that display inline text (text, minimal, superscript, linter) need\r\n // a default text color that works in both light and dark modes\r\n const needsDefaultTextColor =\r\n variant === \"text\" || variant === \"minimal\" || variant === \"superscript\" || variant === \"linter\";\r\n\r\n const statusClasses = cn(\r\n // Default text color for inline variants (ensures dark mode compatibility)\r\n needsDefaultTextColor && !isMiss && !shouldShowSpinner && \"text-gray-900 dark:text-gray-100\",\r\n // Found status (text color) - verified or partial match, for brackets variant\r\n (isVerified || isPartialMatch) &&\r\n variant === \"brackets\" &&\r\n \"text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 hover:underline\",\r\n isMiss && \"opacity-70 line-through text-gray-700 dark:text-gray-200\",\r\n shouldShowSpinner && \"text-gray-500 dark:text-gray-400\"\r\n );\r\n\r\n // Render indicator based on status priority:\r\n // 1. If showIndicator is false, return null (unless custom renderIndicator provided)\r\n // 2. Custom renderIndicator (if provided)\r\n // 3. shouldShowSpinner → Spinner (respects timeout and definitive results)\r\n // 4. Verified (not partial) → Green checkmark\r\n // 5. Partial match → Amber checkmark\r\n // 6. Miss → Warning triangle\r\n const renderStatusIndicator = () => {\r\n if (renderIndicator) return renderIndicator(status);\r\n if (!showIndicator) return null;\r\n if (shouldShowSpinner) return <PendingIndicator />;\r\n if (isVerified && !isPartialMatch) return <VerifiedIndicator />;\r\n if (isPartialMatch) return <PartialIndicator />;\r\n if (isMiss) return <MissIndicator />;\r\n return null;\r\n };\r\n\r\n // Render citation content\r\n const renderCitationContent = () => {\r\n if (renderContent) {\r\n return renderContent({\r\n citation,\r\n status,\r\n citationKey,\r\n displayText,\r\n isMergedDisplay: resolvedContent === \"anchorText\",\r\n });\r\n }\r\n\r\n // Content type: indicator only\r\n if (resolvedContent === \"indicator\") {\r\n return <span>{renderStatusIndicator()}</span>;\r\n }\r\n\r\n // Variant: chip (pill/badge style)\r\n if (variant === \"chip\") {\r\n const chipStatusClasses = cn(\r\n isVerified &&\r\n !isPartialMatch &&\r\n !shouldShowSpinner &&\r\n \"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400\",\r\n isPartialMatch &&\r\n !shouldShowSpinner &&\r\n \"bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400\",\r\n isMiss &&\r\n !shouldShowSpinner &&\r\n \"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400 line-through\",\r\n shouldShowSpinner &&\r\n \"bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400\",\r\n !isVerified &&\r\n !isMiss &&\r\n !shouldShowSpinner &&\r\n \"bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400\"\r\n );\r\n return (\r\n <span\r\n className={cn(\r\n \"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-sm font-medium\",\r\n chipStatusClasses\r\n )}\r\n >\r\n <span className=\"max-w-60 overflow-hidden text-ellipsis whitespace-nowrap\">\r\n {displayText}\r\n </span>\r\n {renderStatusIndicator()}\r\n </span>\r\n );\r\n }\r\n\r\n // Variant: superscript (footnote style)\r\n if (variant === \"superscript\") {\r\n const supStatusClasses = cn(\r\n // Default text color for dark mode compatibility\r\n // Miss state keeps readable text - line-through is the signal\r\n (!shouldShowSpinner) && \"text-gray-700 dark:text-gray-200\",\r\n // Miss state - keep line-through but text stays readable\r\n isMiss && !shouldShowSpinner && \"line-through opacity-60\",\r\n // Pending state\r\n shouldShowSpinner && \"text-gray-500 dark:text-gray-400\"\r\n );\r\n return (\r\n <sup\r\n className={cn(\r\n \"text-xs font-medium transition-colors hover:underline\",\r\n supStatusClasses\r\n )}\r\n >\r\n [{displayText}\r\n {renderStatusIndicator()}]\r\n </sup>\r\n );\r\n }\r\n\r\n // Variant: text (inherits parent styling)\r\n if (variant === \"text\") {\r\n return (\r\n <span className={statusClasses}>\r\n {displayText}\r\n {renderStatusIndicator()}\r\n </span>\r\n );\r\n }\r\n\r\n // Variant: minimal (compact with truncation)\r\n if (variant === \"minimal\") {\r\n const minimalStatusClasses = cn(\r\n // Default text color for dark mode compatibility\r\n // Miss state keeps readable text - line-through is the signal\r\n (!shouldShowSpinner) && \"text-gray-700 dark:text-gray-200\",\r\n // Miss state - keep line-through but text stays readable\r\n isMiss && !shouldShowSpinner && \"opacity-70 line-through\",\r\n // Pending state\r\n shouldShowSpinner && \"text-gray-500 dark:text-gray-400\"\r\n );\r\n return (\r\n <span\r\n className={cn(\r\n \"max-w-80 overflow-hidden text-ellipsis\",\r\n minimalStatusClasses\r\n )}\r\n >\r\n {displayText}\r\n {renderStatusIndicator()}\r\n </span>\r\n );\r\n }\r\n\r\n // Variant: source (ChatGPT-style source chip)\r\n if (variant === \"source\") {\r\n const faviconSrc = faviconUrl || citation.faviconUrl;\r\n return (\r\n <span\r\n className={cn(\r\n \"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-sm font-medium\",\r\n \"bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300\",\r\n \"hover:bg-gray-200 dark:hover:bg-gray-700\",\r\n \"transition-colors cursor-pointer\"\r\n )}\r\n >\r\n {faviconSrc && (\r\n <img\r\n src={faviconSrc}\r\n alt=\"\"\r\n className=\"w-4 h-4 rounded-sm object-contain\"\r\n loading=\"lazy\"\r\n onError={(e) => {\r\n // Hide broken favicon images\r\n (e.target as HTMLImageElement).style.display = 'none';\r\n }}\r\n />\r\n )}\r\n <span className=\"max-w-40 overflow-hidden text-ellipsis whitespace-nowrap\">\r\n {displayText}\r\n </span>\r\n {additionalCount !== undefined && additionalCount > 0 && (\r\n <span className=\"text-gray-500 dark:text-gray-400\">\r\n +{additionalCount}\r\n </span>\r\n )}\r\n </span>\r\n );\r\n }\r\n\r\n // Variant: linter (semantic underlines like grammar/spell-check tools)\r\n // Uses text-decoration-style to differentiate verification states:\r\n // - Verified: solid underline with subtle green background wash\r\n // - Partial: dashed underline (amber)\r\n // - Not Found: wavy underline (red) - familiar from spell-checkers\r\n // - Pending: dotted underline (gray)\r\n //\r\n // The linter variant respects showIndicator prop (default true).\r\n // When showIndicator is true, the status indicator appears after the text.\r\n // The underline style also conveys status visually for additional context.\r\n if (variant === \"linter\") {\r\n // Compute status states once to avoid repetition\r\n const isVerifiedState = isVerified && !isPartialMatch && !shouldShowSpinner;\r\n const isPartialState = isPartialMatch && !shouldShowSpinner;\r\n const isMissState = isMiss && !shouldShowSpinner;\r\n const isPendingState = shouldShowSpinner;\r\n\r\n // Build inline styles for text-decoration since Tailwind doesn't support all decoration styles\r\n // Using Tailwind color values to match the rest of the component:\r\n // - green-600: #16a34a (verified)\r\n // - amber-600: #d97706 (partial)\r\n // - red-500: #ef4444 (miss)\r\n // - gray-400: #9ca3af (pending)\r\n //\r\n // Font-size is inherited from parent to avoid layout shifts\r\n const linterStyles: React.CSSProperties = {\r\n textDecoration: \"underline\",\r\n textDecorationThickness: \"2px\",\r\n textUnderlineOffset: \"3px\",\r\n borderRadius: \"2px\",\r\n // Inherit font properties to avoid size changes\r\n fontSize: \"inherit\",\r\n fontFamily: \"inherit\",\r\n lineHeight: \"inherit\",\r\n };\r\n\r\n // Apply status-specific decoration styles\r\n if (isMissState) {\r\n linterStyles.textDecorationStyle = \"wavy\";\r\n linterStyles.textDecorationColor = \"var(--dc-linter-error, #ef4444)\"; // red-500\r\n } else if (isPartialState) {\r\n linterStyles.textDecorationStyle = \"dashed\";\r\n linterStyles.textDecorationColor = \"var(--dc-linter-warning, #d97706)\"; // amber-600\r\n } else if (isVerifiedState) {\r\n linterStyles.textDecorationStyle = \"solid\";\r\n linterStyles.textDecorationColor = \"var(--dc-linter-success, #16a34a)\"; // green-600\r\n } else {\r\n // Pending or unknown state\r\n linterStyles.textDecorationStyle = \"dotted\";\r\n linterStyles.textDecorationColor = \"var(--dc-linter-pending, #9ca3af)\"; // gray-400\r\n }\r\n\r\n const linterClasses = cn(\r\n \"cursor-pointer\",\r\n // Text color: let the underline convey status, keep text readable\r\n // Miss state uses same color as verified/partial - wavy red underline is the signal\r\n (isVerifiedState || isPartialState || isMissState) && \"text-gray-700 dark:text-gray-200\",\r\n // Only pending is slightly muted\r\n isPendingState && \"text-gray-500 dark:text-gray-400\",\r\n // Verified: subtle green background wash (using green-600 to match component)\r\n isVerifiedState &&\r\n \"bg-green-600/[0.08] hover:bg-green-600/[0.15] dark:bg-green-500/[0.08] dark:hover:bg-green-500/[0.15]\",\r\n // Partial: subtle amber background on hover (using amber-600 to match component)\r\n isPartialState &&\r\n \"hover:bg-amber-600/10 dark:hover:bg-amber-500/10\",\r\n // Miss: subtle red background on hover (using red-500 to match component)\r\n isMissState &&\r\n \"hover:bg-red-500/10 dark:hover:bg-red-400/10\",\r\n // Pending: subtle gray background\r\n isPendingState &&\r\n \"bg-gray-500/[0.05] hover:bg-gray-500/10 dark:bg-gray-400/[0.05] dark:hover:bg-gray-400/10\"\r\n );\r\n\r\n return (\r\n <span className={linterClasses} style={linterStyles}>\r\n {displayText}\r\n {showIndicator && renderStatusIndicator()}\r\n </span>\r\n );\r\n }\r\n\r\n // Variant: brackets (default)\r\n return (\r\n <span\r\n className={cn(\r\n \"inline-flex items-baseline gap-0.5 whitespace-nowrap\",\r\n \"font-mono text-xs leading-tight\",\r\n \"text-gray-500 dark:text-gray-400\",\r\n \"transition-colors\"\r\n )}\r\n aria-hidden=\"true\"\r\n >\r\n [\r\n <span\r\n className={cn(\r\n \"max-w-80 overflow-hidden text-ellipsis\",\r\n statusClasses\r\n )}\r\n >\r\n {displayText}\r\n {renderStatusIndicator()}\r\n </span>\r\n ]\r\n </span>\r\n );\r\n };\r\n\r\n // Popover visibility\r\n const isPopoverHidden = popoverPosition === \"hidden\";\r\n // Show popover for:\r\n // 1. Verification with image or snippet (verified cases)\r\n // 2. Loading/pending states (informative searching message)\r\n // 3. Miss states (show what was searched)\r\n const shouldShowPopover =\r\n !isPopoverHidden &&\r\n (\r\n // Has verification with image or snippet\r\n (verification && (verification.verificationImageBase64 || verification.verifiedMatchSnippet)) ||\r\n // Loading/pending state\r\n shouldShowSpinner ||\r\n isPending ||\r\n isLoading ||\r\n // Miss state (show what was searched)\r\n isMiss\r\n );\r\n\r\n const hasImage = !!verification?.verificationImageBase64;\r\n\r\n // Image overlay\r\n const imageOverlay = expandedImageSrc ? (\r\n <ImageOverlay\r\n src={expandedImageSrc}\r\n alt=\"Citation verification - full size\"\r\n onClose={() => setExpandedImageSrc(null)}\r\n />\r\n ) : null;\r\n\r\n // Shared trigger element props\r\n // Note: linter variant handles its own hover styles, so we skip the blue hover for it\r\n const triggerProps = {\r\n \"data-citation-id\": citationKey,\r\n \"data-citation-instance\": citationInstanceId,\r\n className: cn(\r\n \"relative inline-flex items-baseline cursor-pointer\",\r\n \"px-0.5 -mx-0.5 rounded-sm\",\r\n \"transition-all duration-[50ms]\",\r\n // Only apply blue hover for non-linter variants (linter has its own status-colored hover)\r\n variant !== \"linter\" && \"hover:bg-blue-500/10 dark:hover:bg-blue-400/10\",\r\n hasImage && \"cursor-zoom-in\",\r\n className\r\n ),\r\n onMouseEnter: handleMouseEnter,\r\n onMouseLeave: handleMouseLeave,\r\n onClick: handleClick,\r\n onTouchStart: isMobile ? handleTouchStart : undefined,\r\n onTouchEndCapture: isMobile ? handleTouchEnd : undefined,\r\n \"aria-label\": displayText ? `[${displayText}]` : undefined,\r\n };\r\n\r\n // Render with Radix Popover\r\n if (shouldShowPopover) {\r\n const popoverContentElement = renderPopoverContent ? (\r\n <CitationErrorBoundary>\r\n {renderPopoverContent({\r\n citation,\r\n verification: verification ?? null,\r\n status,\r\n })}\r\n </CitationErrorBoundary>\r\n ) : (\r\n <CitationErrorBoundary>\r\n <DefaultPopoverContent\r\n citation={citation}\r\n verification={verification ?? null}\r\n status={status}\r\n isLoading={isLoading || shouldShowSpinner}\r\n isPhrasesExpanded={isPhrasesExpanded}\r\n onPhrasesExpandChange={setIsPhrasesExpanded}\r\n isVisible={isHovering}\r\n onImageClick={() => {\r\n if (verification?.verificationImageBase64) {\r\n setExpandedImageSrc(verification.verificationImageBase64);\r\n }\r\n }}\r\n />\r\n </CitationErrorBoundary>\r\n );\r\n\r\n // Pre-render the image content in hidden mode when we have an image\r\n // but the user isn't hovering yet. This uses React 19.2's Activity\r\n // component to prefetch and decode the image before it's needed.\r\n const prefetchElement = hasImage && !isHovering && !renderPopoverContent ? (\r\n <CitationErrorBoundary>\r\n <DefaultPopoverContent\r\n citation={citation}\r\n verification={verification ?? null}\r\n status={status}\r\n isLoading={false}\r\n isVisible={false}\r\n onImageClick={() => {}}\r\n />\r\n </CitationErrorBoundary>\r\n ) : null;\r\n\r\n return (\r\n <>\r\n {children}\r\n {/* Hidden prefetch layer - pre-renders image content using Activity */}\r\n {prefetchElement}\r\n <Popover open={isHovering}>\r\n <PopoverTrigger asChild>\r\n <span ref={ref} {...triggerProps}>\r\n {renderCitationContent()}\r\n </span>\r\n </PopoverTrigger>\r\n <PopoverContent\r\n side={popoverPosition === \"bottom\" ? \"bottom\" : \"top\"}\r\n onPointerDownOutside={(e: Event) => e.preventDefault()}\r\n onInteractOutside={(e: Event) => e.preventDefault()}\r\n onMouseEnter={handlePopoverMouseEnter}\r\n onMouseLeave={handlePopoverMouseLeave}\r\n >\r\n {popoverContentElement}\r\n </PopoverContent>\r\n </Popover>\r\n {imageOverlay}\r\n </>\r\n );\r\n }\r\n\r\n // Render without popover\r\n return (\r\n <>\r\n {children}\r\n <span ref={ref} {...triggerProps}>\r\n {renderCitationContent()}\r\n </span>\r\n {imageOverlay}\r\n </>\r\n );\r\n }\r\n);\r\n\r\nCitationComponent.displayName = \"CitationComponent\";\r\n\r\nexport const MemoizedCitationComponent = memo(CitationComponent);\r\n","import React, { forwardRef, memo, useCallback, useMemo, useState, useEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { SourceType } from \"../types/citation.js\";\nimport type {\n SourcesListProps,\n SourcesListItemProps,\n SourcesTriggerProps,\n SourcesListVariant,\n} from \"./types.js\";\nimport { classNames } from \"./utils.js\";\nimport { extractDomain } from \"./UrlCitationComponent.js\";\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Extracts domain from URL for favicon fetching.\n */\nfunction getFaviconUrl(url: string, customFaviconUrl?: string): string {\n if (customFaviconUrl) return customFaviconUrl;\n const domain = extractDomain(url);\n return `https://www.google.com/s2/favicons?domain=${domain}&sz=32`;\n}\n\n/**\n * Detects source type from URL domain.\n */\nexport function detectSourceType(url: string): SourceType {\n // Validate URL format\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n return \"unknown\";\n }\n\n try {\n const domain = extractDomain(url).toLowerCase();\n\n // Social media\n if (domain.includes(\"twitter.com\") || domain === \"x.com\" || domain.endsWith(\".x.com\")) return \"social\";\n if (domain.includes(\"facebook.com\") || domain.includes(\"instagram.com\")) return \"social\";\n if (domain.includes(\"linkedin.com\")) return \"social\";\n if (domain.includes(\"threads.net\") || domain.includes(\"mastodon\")) return \"social\";\n\n // Video platforms\n if (domain.includes(\"youtube.com\") || domain.includes(\"youtu.be\")) return \"video\";\n if (domain.includes(\"twitch.tv\")) return \"video\";\n if (domain.includes(\"vimeo.com\") || domain.includes(\"tiktok.com\")) return \"video\";\n\n // Code repositories\n if (domain.includes(\"github.com\") || domain.includes(\"gitlab.com\")) return \"code\";\n if (domain.includes(\"bitbucket.org\") || domain.includes(\"stackoverflow.com\")) return \"code\";\n\n // Academic\n if (domain.includes(\"arxiv.org\") || domain.includes(\"scholar.google\")) return \"academic\";\n if (domain.includes(\"pubmed\") || domain.includes(\"doi.org\")) return \"academic\";\n if (domain.includes(\"researchgate.net\") || domain.includes(\"academia.edu\")) return \"academic\";\n\n // News\n if (domain.includes(\"news.\") || domain.includes(\"reuters.com\")) return \"news\";\n if (domain.includes(\"bbc.com\") || domain.includes(\"cnn.com\")) return \"news\";\n if (domain.includes(\"nytimes.com\") || domain.includes(\"wsj.com\")) return \"news\";\n if (domain.includes(\"theguardian.com\") || domain.includes(\"washingtonpost.com\")) return \"news\";\n\n // Reference\n if (domain.includes(\"wikipedia.org\") || domain.includes(\"britannica.com\")) return \"reference\";\n if (domain.includes(\"merriam-webster.com\") || domain.includes(\"dictionary.com\")) return \"reference\";\n\n // Forums\n if (domain.includes(\"reddit.com\") || domain.includes(\"quora.com\")) return \"forum\";\n if (domain.includes(\"discourse\") || domain.includes(\"forum\")) return \"forum\";\n\n // Commerce\n if (domain.includes(\"amazon.\") || domain.includes(\"ebay.\")) return \"commerce\";\n if (domain.includes(\"shopify\") || domain.includes(\"etsy.com\")) return \"commerce\";\n\n // PDF check (by extension in URL)\n if (url.toLowerCase().endsWith(\".pdf\")) return \"pdf\";\n\n return \"web\";\n } catch {\n return \"unknown\";\n }\n}\n\n/**\n * Gets a human-readable platform name from domain.\n */\nexport function getPlatformName(url: string, domain?: string): string {\n const d = (domain || extractDomain(url)).toLowerCase();\n\n // Map known domains to platform names\n const platformMap: Record<string, string> = {\n \"twitter.com\": \"X\",\n \"x.com\": \"X\",\n \"facebook.com\": \"Facebook\",\n \"instagram.com\": \"Instagram\",\n \"linkedin.com\": \"LinkedIn\",\n \"youtube.com\": \"YouTube\",\n \"youtu.be\": \"YouTube\",\n \"twitch.tv\": \"Twitch\",\n \"github.com\": \"GitHub\",\n \"gitlab.com\": \"GitLab\",\n \"stackoverflow.com\": \"Stack Overflow\",\n \"reddit.com\": \"Reddit\",\n \"wikipedia.org\": \"Wikipedia\",\n \"arxiv.org\": \"arXiv\",\n \"medium.com\": \"Medium\",\n \"substack.com\": \"Substack\",\n \"notion.so\": \"Notion\",\n \"docs.google.com\": \"Google Docs\",\n \"drive.google.com\": \"Google Drive\",\n \"figma.com\": \"Figma\",\n \"streamscharts.com\": \"Streams Charts\",\n \"dexerto.com\": \"Dexerto\",\n };\n\n // Check for exact match first\n if (platformMap[d]) return platformMap[d];\n\n // Check if domain ends with or equals a known domain (e.g., \"en.wikipedia.org\" matches \"wikipedia.org\")\n for (const [key, name] of Object.entries(platformMap)) {\n if (d === key || d.endsWith(\".\" + key)) return name;\n }\n\n // Capitalize first letter of domain\n return d.charAt(0).toUpperCase() + d.slice(1);\n}\n\n// ============================================================================\n// Icons\n// ============================================================================\n\nconst CloseIcon = () => (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nconst ChevronRightIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst SpinnerIcon = () => (\n <svg\n className=\"animate-spin\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n);\n\n// ============================================================================\n// SourcesListItem Component\n// ============================================================================\n\n/**\n * Individual source item in the sources list.\n * Displays favicon, title, and domain/platform name.\n */\nexport const SourcesListItem = forwardRef<HTMLDivElement, SourcesListItemProps>(\n (\n {\n id,\n url,\n title,\n domain,\n sourceType,\n faviconUrl,\n citationNumbers,\n verificationStatus,\n onClick,\n className,\n showVerificationIndicator = false,\n showCitationBadges = false,\n renderFavicon,\n },\n ref\n ) => {\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (onClick) {\n onClick(\n { id, url, title, domain, sourceType, faviconUrl, citationNumbers, verificationStatus },\n e\n );\n } else {\n // Default: open URL in new tab\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n }\n },\n [onClick, id, url, title, domain, sourceType, faviconUrl, citationNumbers, verificationStatus]\n );\n\n const platformName = useMemo(() => getPlatformName(url, domain), [url, domain]);\n const favicon = useMemo(() => getFaviconUrl(url, faviconUrl), [url, faviconUrl]);\n const detectedType = useMemo(() => sourceType || detectSourceType(url), [sourceType, url]);\n\n const renderVerificationBadge = () => {\n if (!showVerificationIndicator || !verificationStatus) return null;\n\n const statusConfig = {\n verified: { icon: \"✓\", className: \"text-green-600 dark:text-green-500\" },\n partial: { icon: \"~\", className: \"text-amber-600 dark:text-amber-500\" },\n pending: { icon: \"…\", className: \"text-gray-400 dark:text-gray-500\" },\n failed: { icon: \"✗\", className: \"text-red-500 dark:text-red-400\" },\n unknown: { icon: \"?\", className: \"text-gray-400 dark:text-gray-500\" },\n };\n\n const config = statusConfig[verificationStatus];\n return (\n <span className={classNames(\"text-sm ml-1\", config.className)} aria-label={verificationStatus}>\n {config.icon}\n </span>\n );\n };\n\n return (\n <div\n ref={ref}\n data-source-id={id}\n data-source-type={detectedType}\n className={classNames(\n \"flex items-start gap-3 p-3 cursor-pointer transition-colors\",\n \"hover:bg-gray-50 dark:hover:bg-gray-800/50\",\n \"border-b border-gray-100 dark:border-gray-800 last:border-b-0\",\n className\n )}\n onClick={handleClick}\n role=\"link\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleClick(e as unknown as React.MouseEvent<HTMLDivElement>);\n }\n }}\n aria-label={`${title} from ${platformName}`}\n >\n {/* Favicon */}\n <div className=\"flex-shrink-0 mt-0.5\">\n {renderFavicon ? (\n renderFavicon({ id, url, title, domain, sourceType, faviconUrl, citationNumbers, verificationStatus })\n ) : (\n <img\n src={favicon}\n alt=\"\"\n className=\"w-5 h-5 rounded\"\n width={20}\n height={20}\n loading=\"lazy\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n )}\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n {/* Title */}\n <div className=\"flex items-center gap-1\">\n <span className=\"text-gray-900 dark:text-gray-100 font-medium text-sm leading-tight line-clamp-2\">\n {title}\n </span>\n {renderVerificationBadge()}\n </div>\n\n {/* Platform/Domain */}\n <div className=\"flex items-center gap-1.5 mt-0.5\">\n <span className=\"text-gray-500 dark:text-gray-400 text-xs\">\n {platformName}\n </span>\n {showCitationBadges && citationNumbers && citationNumbers.length > 0 && (\n <div className=\"flex items-center gap-1\">\n {citationNumbers.slice(0, 3).map((num) => (\n <span\n key={num}\n className=\"inline-flex items-center justify-center w-4 h-4 text-[10px] font-medium bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300 rounded\"\n >\n {num}\n </span>\n ))}\n {citationNumbers.length > 3 && (\n <span className=\"text-xs text-gray-400 dark:text-gray-500\">+{citationNumbers.length - 3}</span>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Arrow indicator */}\n <div className=\"flex-shrink-0 text-gray-400 dark:text-gray-500 mt-1\">\n <ChevronRightIcon />\n </div>\n </div>\n );\n }\n);\n\nSourcesListItem.displayName = \"SourcesListItem\";\n\n// ============================================================================\n// SourcesTrigger Component\n// ============================================================================\n\n/**\n * Compact trigger button that shows favicon previews and opens the sources list.\n * Matches the \"Sources\" button shown in the screenshots with stacked favicons.\n */\nexport const SourcesTrigger = forwardRef<HTMLButtonElement, SourcesTriggerProps>(\n ({ sources, maxIcons = 3, onClick, label = \"Sources\", className, isOpen }, ref) => {\n const displaySources = useMemo(() => sources.slice(0, maxIcons), [sources, maxIcons]);\n const hasMore = sources.length > maxIcons;\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={onClick}\n className={classNames(\n \"inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-sm\",\n \"bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300\",\n \"hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors\",\n \"focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\",\n className\n )}\n aria-expanded={isOpen}\n aria-haspopup=\"dialog\"\n >\n <span className=\"font-medium\">{label}</span>\n\n {/* Stacked favicons */}\n <div className=\"flex items-center -space-x-1\">\n {displaySources.map((source, i) => (\n <img\n key={source.id}\n src={getFaviconUrl(source.url, source.faviconUrl)}\n alt=\"\"\n className={classNames(\n \"w-4 h-4 rounded-full ring-2 ring-gray-100 dark:ring-gray-800\",\n i > 0 && \"-ml-1\"\n )}\n width={16}\n height={16}\n loading=\"lazy\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.opacity = \"0\";\n }}\n />\n ))}\n {hasMore && (\n <span className=\"w-4 h-4 rounded-full bg-gray-300 dark:bg-gray-600 ring-2 ring-gray-100 dark:ring-gray-800 flex items-center justify-center text-[9px] font-medium text-gray-600 dark:text-gray-300\">\n +{sources.length - maxIcons}\n </span>\n )}\n </div>\n </button>\n );\n }\n);\n\nSourcesTrigger.displayName = \"SourcesTrigger\";\n\n// ============================================================================\n// SourcesListComponent\n// ============================================================================\n\n/**\n * SourcesListComponent\n *\n * Displays an aggregated list of sources at the end of AI-generated content,\n * following the Anthropic/Claude \"Sources\" panel pattern.\n *\n * Features:\n * - Multiple display variants: panel, drawer (mobile), modal, inline\n * - Favicon + title + domain display for each source\n * - Grouping by domain/platform\n * - Loading and empty states\n * - Keyboard navigation support\n * - Portal rendering for drawer/modal variants\n *\n * @example\n * ```tsx\n * <SourcesListComponent\n * sources={[\n * { id: \"1\", url: \"https://twitch.tv/theo\", title: \"Theo - Twitch\", domain: \"twitch.tv\" },\n * { id: \"2\", url: \"https://linkedin.com/in/...\", title: \"Theodore Nguyen\", domain: \"linkedin.com\" },\n * ]}\n * variant=\"drawer\"\n * isOpen={isSourcesOpen}\n * onOpenChange={setIsSourcesOpen}\n * />\n * ```\n */\nexport const SourcesListComponent = forwardRef<HTMLDivElement, SourcesListProps>(\n (\n {\n sources,\n variant = \"drawer\",\n isOpen = true,\n onOpenChange,\n header = {},\n isLoading = false,\n emptyMessage = \"No sources available\",\n maxHeight,\n className,\n listClassName,\n onSourceClick,\n showVerificationIndicators = false,\n showCitationBadges = false,\n groupByDomain = false,\n renderItem,\n renderEmpty,\n renderLoading,\n },\n ref\n ) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n\n // Handle ESC key to close\n useEffect(() => {\n if (!isOpen || variant === \"inline\") return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onOpenChange?.(false);\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onOpenChange, variant]);\n\n // Portal mounting\n useEffect(() => {\n setMounted(true);\n }, []);\n\n // Group sources by domain if requested\n const groupedSources = useMemo(() => {\n if (!groupByDomain) return null;\n\n const groups: Record<string, SourcesListItemProps[]> = {};\n for (const source of sources) {\n const key = source.domain || extractDomain(source.url);\n if (!groups[key]) groups[key] = [];\n groups[key].push(source);\n }\n return groups;\n }, [sources, groupByDomain]);\n\n const handleClose = useCallback(() => {\n onOpenChange?.(false);\n }, [onOpenChange]);\n\n const handleBackdropClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n handleClose();\n }\n },\n [handleClose]\n );\n\n // Render header\n const renderHeader = () => {\n const { title = \"Sources\", showCloseButton = true, showCount = true, renderHeader: customRender } = header;\n\n if (customRender) {\n return customRender({ title, count: sources.length, onClose: handleClose });\n }\n\n return (\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n {showCloseButton && variant !== \"inline\" && (\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"p-1 -ml-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors\"\n aria-label=\"Close sources\"\n >\n <CloseIcon />\n </button>\n )}\n <h2 className=\"text-base font-semibold text-gray-900 dark:text-gray-100 flex-1 text-center\">\n {title}\n {showCount && (\n <span className=\"ml-2 text-sm font-normal text-gray-500 dark:text-gray-400\">\n ({sources.length})\n </span>\n )}\n </h2>\n {/* Spacer for centering when close button is present */}\n {showCloseButton && variant !== \"inline\" && <div className=\"w-8\" />}\n </div>\n );\n };\n\n // Render list content\n const renderListContent = () => {\n if (isLoading) {\n if (renderLoading) return renderLoading();\n return (\n <div className=\"flex items-center justify-center py-8 text-gray-500 dark:text-gray-400\">\n <SpinnerIcon />\n <span className=\"ml-2 text-sm\">Loading sources...</span>\n </div>\n );\n }\n\n if (sources.length === 0) {\n if (renderEmpty) return renderEmpty();\n return (\n <div className=\"flex items-center justify-center py-8 text-gray-500 dark:text-gray-400 text-sm\">\n {emptyMessage}\n </div>\n );\n }\n\n if (groupByDomain && groupedSources) {\n return (\n <div className={listClassName}>\n {Object.entries(groupedSources).map(([domain, domainSources]) => (\n <div key={domain}>\n <div className=\"px-4 py-2 text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider bg-gray-50 dark:bg-gray-800/50\">\n {getPlatformName(domainSources[0].url, domain)}\n </div>\n {domainSources.map((source, index) =>\n renderItem ? (\n renderItem(source, index)\n ) : (\n <SourcesListItem\n key={source.id}\n {...source}\n onClick={onSourceClick}\n showVerificationIndicator={showVerificationIndicators}\n showCitationBadges={showCitationBadges}\n />\n )\n )}\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div className={listClassName}>\n {sources.map((source, index) =>\n renderItem ? (\n renderItem(source, index)\n ) : (\n <SourcesListItem\n key={source.id}\n {...source}\n onClick={onSourceClick}\n showVerificationIndicator={showVerificationIndicators}\n showCitationBadges={showCitationBadges}\n />\n )\n )}\n </div>\n );\n };\n\n // Calculate max height style\n const maxHeightStyle = maxHeight\n ? { maxHeight: typeof maxHeight === \"number\" ? `${maxHeight}px` : maxHeight }\n : undefined;\n\n // Variant-specific rendering\n if (variant === \"inline\") {\n if (!isOpen) return null;\n return (\n <div\n ref={ref}\n className={classNames(\n \"bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700\",\n className\n )}\n style={maxHeightStyle}\n >\n {renderHeader()}\n <div className=\"overflow-y-auto\" style={maxHeightStyle}>\n {renderListContent()}\n </div>\n </div>\n );\n }\n\n if (variant === \"panel\") {\n if (!isOpen) return null;\n return (\n <div\n ref={ref}\n className={classNames(\n \"bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 shadow-lg\",\n className\n )}\n >\n {renderHeader()}\n <div className=\"overflow-y-auto\" style={maxHeightStyle || { maxHeight: \"400px\" }}>\n {renderListContent()}\n </div>\n </div>\n );\n }\n\n // Modal and drawer variants use portals\n if (!mounted || !isOpen) return null;\n\n const portalContent = (\n <div\n ref={ref}\n className={classNames(\n \"fixed inset-0 z-50\",\n variant === \"modal\" && \"flex items-center justify-center\"\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"sources-title\"\n >\n {/* Backdrop */}\n <div\n className={classNames(\n \"absolute inset-0 bg-black/40 dark:bg-black/60 transition-opacity\",\n isOpen ? \"opacity-100\" : \"opacity-0\"\n )}\n onClick={handleBackdropClick}\n aria-hidden=\"true\"\n />\n\n {/* Content */}\n {variant === \"drawer\" ? (\n <div\n ref={containerRef}\n className={classNames(\n \"absolute bottom-0 left-0 right-0 bg-white dark:bg-gray-900 rounded-t-2xl shadow-2xl\",\n \"transform transition-transform duration-300 ease-out\",\n isOpen ? \"translate-y-0\" : \"translate-y-full\",\n \"max-h-[80vh] flex flex-col\",\n className\n )}\n >\n {/* Drawer handle */}\n <div className=\"flex justify-center py-2\">\n <div className=\"w-10 h-1 bg-gray-300 dark:bg-gray-600 rounded-full\" />\n </div>\n {renderHeader()}\n <div className=\"overflow-y-auto flex-1\">\n {renderListContent()}\n </div>\n </div>\n ) : (\n <div\n ref={containerRef}\n className={classNames(\n \"relative bg-white dark:bg-gray-900 rounded-xl shadow-2xl\",\n \"transform transition-all duration-200\",\n isOpen ? \"opacity-100 scale-100\" : \"opacity-0 scale-95\",\n \"w-full max-w-md max-h-[80vh] flex flex-col mx-4\",\n className\n )}\n >\n {renderHeader()}\n <div className=\"overflow-y-auto flex-1\">\n {renderListContent()}\n </div>\n </div>\n )}\n </div>\n );\n\n return createPortal(portalContent, document.body);\n }\n);\n\nSourcesListComponent.displayName = \"SourcesListComponent\";\n\n// ============================================================================\n// Memoized Exports\n// ============================================================================\n\nexport const MemoizedSourcesListItem = memo(SourcesListItem);\nexport const MemoizedSourcesTrigger = memo(SourcesTrigger);\nexport const MemoizedSourcesListComponent = memo(SourcesListComponent);\n\n// ============================================================================\n// Utility Exports\n// ============================================================================\n\n/**\n * Converts SourceCitation array to SourcesListItemProps array.\n */\nexport function sourceCitationsToListItems(\n citations: Array<{\n url?: string;\n title?: string;\n domain?: string;\n sourceType?: SourceType;\n faviconUrl?: string;\n citationNumber?: number;\n }>\n): SourcesListItemProps[] {\n const sourceMap = new Map<string, SourcesListItemProps>();\n\n for (const citation of citations) {\n if (!citation.url) continue;\n\n const domain = citation.domain || extractDomain(citation.url);\n const key = citation.url;\n\n if (sourceMap.has(key)) {\n // Aggregate citation numbers\n const existing = sourceMap.get(key)!;\n if (citation.citationNumber && !existing.citationNumbers?.includes(citation.citationNumber)) {\n existing.citationNumbers = [...(existing.citationNumbers || []), citation.citationNumber];\n }\n } else {\n sourceMap.set(key, {\n id: key,\n url: citation.url,\n title: citation.title || domain,\n domain,\n sourceType: citation.sourceType || detectSourceType(citation.url),\n faviconUrl: citation.faviconUrl,\n citationNumbers: citation.citationNumber ? [citation.citationNumber] : [],\n });\n }\n }\n\n return Array.from(sourceMap.values());\n}\n\n/**\n * Hook for managing sources list state.\n */\nexport function useSourcesList(initialSources: SourcesListItemProps[] = []) {\n const [sources, setSources] = useState<SourcesListItemProps[]>(initialSources);\n const [isOpen, setIsOpen] = useState(false);\n\n const addSource = useCallback((source: SourcesListItemProps) => {\n setSources((prev) => {\n const exists = prev.some((s) => s.url === source.url);\n if (exists) return prev;\n return [...prev, source];\n });\n }, []);\n\n const removeSource = useCallback((id: string) => {\n setSources((prev) => prev.filter((s) => s.id !== id));\n }, []);\n\n const clearSources = useCallback(() => {\n setSources([]);\n }, []);\n\n return {\n sources,\n setSources,\n addSource,\n removeSource,\n clearSources,\n isOpen,\n setIsOpen,\n open: () => setIsOpen(true),\n close: () => setIsOpen(false),\n toggle: () => setIsOpen((prev) => !prev),\n };\n}\n","import React, { useCallback, useMemo, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { Citation } from \"../types/citation.js\";\nimport type { Verification } from \"../types/verification.js\";\nimport { CheckIcon, SpinnerIcon, WarningIcon } from \"./icons.js\";\nimport type {\n CitationDrawerItem,\n CitationDrawerItemProps,\n CitationDrawerProps,\n SourceCitationGroup,\n} from \"./types.js\";\nimport { cn } from \"./utils.js\";\n\n// =============================================================================\n// UTILITY FUNCTIONS\n// =============================================================================\n\n/**\n * Groups citations by their source domain/name.\n * Returns an array of SourceCitationGroup objects.\n */\nexport function groupCitationsBySource(\n citations: CitationDrawerItem[]\n): SourceCitationGroup[] {\n const groups = new Map<string, CitationDrawerItem[]>();\n\n for (const item of citations) {\n // Use domain or siteName as the grouping key (using main's field names)\n const groupKey =\n item.citation.domain ||\n item.citation.siteName ||\n item.citation.url ||\n \"unknown\";\n\n if (!groups.has(groupKey)) {\n groups.set(groupKey, []);\n }\n groups.get(groupKey)!.push(item);\n }\n\n // Convert map to array of SourceCitationGroup\n return Array.from(groups.entries()).map(([key, items]) => {\n const firstCitation = items[0].citation;\n return {\n sourceName:\n firstCitation.siteName ||\n firstCitation.domain ||\n extractDomain(firstCitation.url) ||\n \"Unknown Source\",\n sourceDomain: firstCitation.domain || extractDomain(firstCitation.url),\n sourceFavicon: firstCitation.faviconUrl || undefined,\n citations: items,\n additionalCount: items.length - 1,\n };\n });\n}\n\n/**\n * Extracts domain from a URL string.\n */\nfunction extractDomain(url?: string | null): string | undefined {\n if (!url) return undefined;\n try {\n const urlObj = new URL(url);\n return urlObj.hostname.replace(/^www\\./, \"\");\n } catch {\n return undefined;\n }\n}\n\n/**\n * Get verification status indicator info\n */\nfunction getStatusInfo(verification: Verification | null): {\n color: string;\n icon: React.ReactNode;\n label: string;\n} {\n const status = verification?.status;\n\n if (!status || status === \"pending\" || status === \"loading\") {\n return {\n color: \"text-gray-400\",\n icon: <SpinnerIcon />,\n label: \"Verifying\",\n };\n }\n\n if (status === \"not_found\") {\n return {\n color: \"text-amber-500\",\n icon: <WarningIcon />,\n label: \"Not found\",\n };\n }\n\n const isPartial =\n status === \"partial_text_found\" ||\n status === \"found_on_other_page\" ||\n status === \"found_on_other_line\" ||\n status === \"first_word_found\";\n\n if (isPartial) {\n return {\n color: \"text-amber-500\",\n icon: <CheckIcon />,\n label: \"Partial match\",\n };\n }\n\n // Verified statuses\n return {\n color: \"text-green-500\",\n icon: <CheckIcon />,\n label: \"Verified\",\n };\n}\n\n// =============================================================================\n// CITATION DRAWER ITEM COMPONENT\n// =============================================================================\n\n/**\n * Individual citation item displayed in the drawer.\n * Shows favicon, source name, article title, and snippet.\n */\nexport function CitationDrawerItemComponent({\n item,\n isLast = false,\n onClick,\n onReadMore,\n className,\n}: CitationDrawerItemProps) {\n const { citation, verification } = item;\n const statusInfo = getStatusInfo(verification);\n\n // Get display values with fallbacks (using main's field names)\n const sourceName =\n citation.siteName ||\n citation.domain ||\n extractDomain(citation.url) ||\n \"Source\";\n const articleTitle = citation.title || citation.anchorText || citation.fullPhrase;\n const snippet =\n citation.description ||\n verification?.actualContentSnippet ||\n verification?.verifiedMatchSnippet;\n const faviconUrl = citation.faviconUrl;\n\n const handleClick = useCallback(() => {\n onClick?.(item);\n }, [item, onClick]);\n\n const handleReadMore = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onReadMore?.(item);\n },\n [item, onReadMore]\n );\n\n return (\n <div\n className={cn(\n \"px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer transition-colors\",\n !isLast && \"border-b border-gray-200 dark:border-gray-700\",\n className\n )}\n onClick={handleClick}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleClick();\n }\n }}\n >\n <div className=\"flex items-start gap-3\">\n {/* Favicon */}\n <div className=\"flex-shrink-0 mt-0.5\">\n {faviconUrl ? (\n <img\n src={faviconUrl}\n alt=\"\"\n className=\"w-5 h-5 rounded object-contain\"\n loading=\"lazy\"\n onError={(e) => {\n // Replace with default icon on error\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n ) : (\n <div className=\"w-5 h-5 rounded bg-gray-200 dark:bg-gray-700 flex items-center justify-center\">\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\n {sourceName.charAt(0).toUpperCase()}\n </span>\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n {/* Source name with status indicator */}\n <div className=\"flex items-center gap-1.5\">\n <span className=\"text-xs font-medium text-gray-500 dark:text-gray-400\">\n {sourceName}\n </span>\n <span\n className={cn(\n \"inline-flex w-3 h-3\",\n statusInfo.color,\n verification?.status === \"pending\" ||\n verification?.status === \"loading\"\n ? \"animate-spin\"\n : \"\"\n )}\n title={statusInfo.label}\n >\n {statusInfo.icon}\n </span>\n </div>\n\n {/* Article title */}\n {articleTitle && (\n <h4 className=\"mt-1 text-sm font-medium text-gray-900 dark:text-gray-100 line-clamp-2\">\n {articleTitle}\n </h4>\n )}\n\n {/* Snippet */}\n {snippet && (\n <p className=\"mt-1 text-sm text-gray-600 dark:text-gray-400 line-clamp-2\">\n {snippet}\n {onReadMore && snippet.length > 100 && (\n <button\n onClick={handleReadMore}\n className=\"ml-1 text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300\"\n >\n Read more\n </button>\n )}\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// CITATION DRAWER COMPONENT\n// =============================================================================\n\n/**\n * CitationDrawer displays a collection of citations in a drawer/bottom sheet.\n * Similar to ChatGPT's citation drawer UI.\n *\n * @example Basic usage\n * ```tsx\n * const [isOpen, setIsOpen] = useState(false);\n * const citationGroups = groupCitationsBySource(citations);\n *\n * <CitationDrawer\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * citationGroups={citationGroups}\n * />\n * ```\n *\n * @example With click handlers\n * ```tsx\n * <CitationDrawer\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * citationGroups={citationGroups}\n * onCitationClick={(item) => window.open(item.citation.sourceUrl, '_blank')}\n * onReadMore={(item) => console.log('Read more:', item)}\n * />\n * ```\n */\nexport function CitationDrawer({\n isOpen,\n onClose,\n citationGroups,\n title = \"Citations\",\n showMoreSection = true,\n maxVisibleItems = 3,\n onCitationClick,\n onReadMore,\n className,\n position = \"bottom\",\n renderCitationItem,\n}: CitationDrawerProps) {\n const [showMore, setShowMore] = useState(false);\n\n // Flatten all citations from groups\n const allCitations = useMemo(() => {\n return citationGroups.flatMap((group) => group.citations);\n }, [citationGroups]);\n\n // Split into visible and \"more\" sections\n const visibleCitations = useMemo(() => {\n if (!showMoreSection || showMore) return allCitations;\n return allCitations.slice(0, maxVisibleItems);\n }, [allCitations, showMoreSection, showMore, maxVisibleItems]);\n\n const moreCitations = useMemo(() => {\n if (!showMoreSection || showMore) return [];\n return allCitations.slice(maxVisibleItems);\n }, [allCitations, showMoreSection, showMore, maxVisibleItems]);\n\n // Handle escape key\n React.useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n\n // Don't render if closed\n if (!isOpen) return null;\n\n const drawerContent = (\n <>\n {/* Backdrop */}\n <div\n className=\"fixed inset-0 bg-black/40 z-[9998] animate-in fade-in-0 duration-150\"\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n {/* Drawer */}\n <div\n className={cn(\n \"fixed z-[9999] bg-white dark:bg-gray-900 shadow-xl\",\n \"animate-in duration-200\",\n position === \"bottom\" && \"inset-x-0 bottom-0 max-h-[80vh] rounded-t-2xl slide-in-from-bottom-4\",\n position === \"right\" && \"inset-y-0 right-0 w-full max-w-md slide-in-from-right-4\",\n className\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n {/* Handle bar (mobile) */}\n {position === \"bottom\" && (\n <div className=\"flex justify-center pt-3 pb-1\">\n <div className=\"w-10 h-1 rounded-full bg-gray-300 dark:bg-gray-600\" />\n </div>\n )}\n\n {/* Header */}\n <div className=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between\">\n <h2 className=\"text-base font-semibold text-gray-900 dark:text-gray-100\">\n {title}\n </h2>\n <button\n onClick={onClose}\n className=\"p-1.5 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\"\n aria-label=\"Close\"\n >\n <svg\n className=\"w-5 h-5 text-gray-500 dark:text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n {/* Citation list */}\n <div className=\"overflow-y-auto max-h-[calc(80vh-100px)]\">\n {visibleCitations.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-gray-500 dark:text-gray-400\">\n No citations to display\n </div>\n ) : (\n <>\n {visibleCitations.map((item, index) =>\n renderCitationItem ? (\n <React.Fragment key={item.citationKey}>\n {renderCitationItem(item)}\n </React.Fragment>\n ) : (\n <CitationDrawerItemComponent\n key={item.citationKey}\n item={item}\n isLast={\n index === visibleCitations.length - 1 &&\n moreCitations.length === 0\n }\n onClick={onCitationClick}\n onReadMore={onReadMore}\n />\n )\n )}\n\n {/* More section */}\n {moreCitations.length > 0 && !showMore && (\n <div className=\"px-4 py-3 border-t border-gray-200 dark:border-gray-700\">\n <button\n onClick={() => setShowMore(true)}\n className=\"text-sm font-medium text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300\"\n >\n More ({moreCitations.length})\n </button>\n </div>\n )}\n\n {/* Expanded \"more\" citations */}\n {showMore &&\n moreCitations.map((item, index) =>\n renderCitationItem ? (\n <React.Fragment key={item.citationKey}>\n {renderCitationItem(item)}\n </React.Fragment>\n ) : (\n <CitationDrawerItemComponent\n key={item.citationKey}\n item={item}\n isLast={index === moreCitations.length - 1}\n onClick={onCitationClick}\n onReadMore={onReadMore}\n />\n )\n )}\n </>\n )}\n </div>\n </div>\n </>\n );\n\n // Render via portal\n return createPortal(drawerContent, document.body);\n}\n\n// =============================================================================\n// HOOK FOR MANAGING DRAWER STATE\n// =============================================================================\n\n/**\n * Hook for managing citation drawer state.\n *\n * @example\n * ```tsx\n * const { isOpen, openDrawer, closeDrawer, citationGroups, addCitation } = useCitationDrawer();\n *\n * // Add citations\n * addCitation({ citationKey: \"1\", citation, verification });\n *\n * // Open drawer\n * <button onClick={openDrawer}>View Citations</button>\n *\n * // Render drawer\n * <CitationDrawer\n * isOpen={isOpen}\n * onClose={closeDrawer}\n * citationGroups={citationGroups}\n * />\n * ```\n */\nexport function useCitationDrawer() {\n const [isOpen, setIsOpen] = useState(false);\n const [citations, setCitations] = useState<CitationDrawerItem[]>([]);\n\n const openDrawer = useCallback(() => setIsOpen(true), []);\n const closeDrawer = useCallback(() => setIsOpen(false), []);\n const toggleDrawer = useCallback(() => setIsOpen((prev) => !prev), []);\n\n const addCitation = useCallback((item: CitationDrawerItem) => {\n setCitations((prev) => {\n // Don't add duplicates\n if (prev.some((c) => c.citationKey === item.citationKey)) {\n return prev;\n }\n return [...prev, item];\n });\n }, []);\n\n const removeCitation = useCallback((citationKey: string) => {\n setCitations((prev) => prev.filter((c) => c.citationKey !== citationKey));\n }, []);\n\n const clearCitations = useCallback(() => {\n setCitations([]);\n }, []);\n\n const setCitationsList = useCallback((items: CitationDrawerItem[]) => {\n setCitations(items);\n }, []);\n\n const citationGroups = useMemo(\n () => groupCitationsBySource(citations),\n [citations]\n );\n\n return {\n isOpen,\n openDrawer,\n closeDrawer,\n toggleDrawer,\n citations,\n citationGroups,\n addCitation,\n removeCitation,\n clearCitations,\n setCitations: setCitationsList,\n };\n}\n\n// =============================================================================\n// EXPORTS\n// =============================================================================\n\nexport type { CitationDrawerItem, CitationDrawerProps, SourceCitationGroup };\n","/**\n * PrefetchedPopoverImage\n *\n * Uses React 19.2's Activity component to pre-render popover images before\n * they're visible. This ensures images are already decoded and ready to display\n * when the user hovers over a citation, eliminating the empty popover flash.\n *\n * The Activity component allows React to:\n * - Pre-render the image in \"hidden\" mode while the user isn't hovering\n * - Instantly reveal the already-rendered content when switching to \"visible\"\n * - Defer updates to hidden content so they don't block visible UI\n *\n * Falls back to a simple Fragment wrapper if Activity is not available (React < 19.2).\n *\n * @see https://react.dev/blog/2025/10/01/react-19-2\n */\nimport React, { memo } from \"react\";\n\n// React 19.2+ Activity component for prefetching - falls back to Fragment if unavailable\nconst Activity =\n (React as { Activity?: React.ComponentType<{ mode: \"visible\" | \"hidden\"; children: React.ReactNode }> }).Activity ??\n (({ children }: { mode: \"visible\" | \"hidden\"; children: React.ReactNode }) => <>{children}</>);\n\ninterface PrefetchedPopoverImageProps {\n /** Whether the popover (and image) should be visible */\n isVisible: boolean;\n /** Base64 image source (data URI) */\n src: string;\n /** Alt text for accessibility */\n alt: string;\n /** Optional click handler for the image */\n onClick?: () => void;\n /** Optional className for the container */\n className?: string;\n /** Image style constraints */\n imageStyle?: React.CSSProperties;\n}\n\n/**\n * Renders an image that's pre-rendered in the background before being shown.\n *\n * Uses React 19.2's Activity component to keep the image rendered but hidden,\n * so when the user hovers, the image appears instantly without a loading flash.\n *\n * @example\n * ```tsx\n * <PrefetchedPopoverImage\n * isVisible={isHovering}\n * src={verification.verificationImageBase64}\n * alt=\"Citation verification\"\n * onClick={() => setExpandedImageSrc(src)}\n * />\n * ```\n */\nexport function PrefetchedPopoverImage({\n isVisible,\n src,\n alt,\n onClick,\n className,\n imageStyle,\n}: PrefetchedPopoverImageProps) {\n // The Activity component pre-renders children in \"hidden\" mode\n // When isVisible becomes true, it switches to \"visible\" mode instantly\n // The image is already rendered/decoded, so no flash occurs\n return (\n <Activity mode={isVisible ? \"visible\" : \"hidden\"}>\n <div className={className}>\n <button\n type=\"button\"\n className=\"group block cursor-zoom-in relative overflow-hidden rounded-md bg-gray-50 dark:bg-gray-800\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick?.();\n }}\n aria-label=\"Click to view full size\"\n >\n <img\n src={src}\n alt={alt}\n className=\"block rounded-md\"\n style={\n imageStyle ?? {\n maxWidth: \"min(70vw, 384px)\",\n maxHeight: \"min(50vh, 300px)\",\n width: \"auto\",\n height: \"auto\",\n objectFit: \"contain\",\n }\n }\n // Don't use lazy loading - we want to prefetch\n loading=\"eager\"\n // Decode async to not block main thread during prefetch\n decoding=\"async\"\n />\n </button>\n </div>\n </Activity>\n );\n}\n\n/**\n * Memoized version of PrefetchedPopoverImage.\n * Use this when the parent re-renders frequently.\n */\nexport const MemoizedPrefetchedPopoverImage = memo(PrefetchedPopoverImage);\n\n/**\n * Hook to prefetch an image into browser cache.\n * This is a simpler alternative when Activity isn't available or needed.\n *\n * @example\n * ```tsx\n * const prefetchImage = usePrefetchImage();\n *\n * // Prefetch when verification arrives\n * useEffect(() => {\n * if (verification?.verificationImageBase64) {\n * prefetchImage(verification.verificationImageBase64);\n * }\n * }, [verification?.verificationImageBase64]);\n * ```\n */\nexport function usePrefetchImage() {\n const prefetchImage = React.useCallback((src: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve();\n img.onerror = reject;\n img.src = src;\n });\n }, []);\n\n return prefetchImage;\n}\n\n/**\n * Prefetches multiple images concurrently.\n * Useful for batch prefetching all verification images.\n *\n * @example\n * ```tsx\n * // Prefetch all images when verifications load\n * useEffect(() => {\n * const srcs = verifications\n * .filter(v => v.verificationImageBase64)\n * .map(v => v.verificationImageBase64!);\n * prefetchImages(srcs);\n * }, [verifications]);\n * ```\n */\nexport async function prefetchImages(srcs: string[]): Promise<void[]> {\n const promises = srcs.map(\n (src) =>\n new Promise<void>((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve();\n img.onerror = reject;\n img.src = src;\n })\n );\n return Promise.all(promises);\n}\n","import React, { useEffect, useState, useMemo } from \"react\";\nimport { useSmartDiff } from \"./useSmartDiff.js\";\nimport { cn } from \"./utils.js\";\nimport { CheckIcon } from \"./icons.js\";\nimport { SplitDiffDisplay, MatchQualityBar, CollapsibleText, getContextualStatusMessage } from \"./SplitDiffDisplay.js\";\nimport type { SearchStatus } from \"../types/search.js\";\nimport type { DiffDisplayMode } from \"./SplitDiffDisplay.js\";\n\ninterface VerificationTabsProps {\n expected: string; // The AI's Claim\n actual: string; // The Source Text Found\n label?: string;\n renderCopyButton?: (text: string, position: \"expected\" | \"found\") => React.ReactNode;\n emptyText?: string;\n // NEW PROPS from PRD\n /** Verification status for contextual messages */\n status?: SearchStatus | null;\n /** Expected anchorText to highlight */\n anchorText?: string;\n /** Found anchorText to highlight */\n verifiedKeySpan?: string;\n /** Default display mode */\n defaultMode?: DiffDisplayMode;\n /** Expected page number (for status messages) */\n expectedPage?: number | null;\n /** Actual page number found (for status messages) */\n actualPage?: number | null;\n /** Show match quality indicator */\n showMatchQuality?: boolean;\n /** Maximum length before collapsing text */\n maxCollapsedLength?: number;\n}\n\ntype TabType = \"found\" | \"diff\" | \"expected\";\n\n// Sub-component: The individual tab button\nconst TabButton = ({ isActive, onClick, label }: { isActive: boolean; onClick: () => void; label: string }) => (\n <button\n onClick={e => {\n e.stopPropagation(); // Prevent tooltip from closing or dragging\n onClick();\n }}\n className={cn(\n \"px-3 py-1.5 text-sm font-medium rounded-md transition-colors\",\n \"focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1\",\n isActive\n ? \"bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300\"\n : \"text-gray-600 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-200 dark:hover:bg-gray-800\"\n )}\n type=\"button\"\n data-active={isActive}\n >\n {label}\n </button>\n);\n\n// Sub-component: Mode toggle button for switching between inline and split\nconst ModeToggle = ({\n mode,\n onModeChange,\n}: {\n mode: \"inline\" | \"split\";\n onModeChange: (mode: \"inline\" | \"split\") => void;\n}) => (\n <div className=\"flex items-center gap-1 ml-auto\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onModeChange(\"inline\");\n }}\n className={cn(\n \"p-1 rounded transition-colors\",\n mode === \"inline\"\n ? \"bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300\"\n : \"text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-400\"\n )}\n title=\"Inline diff view\"\n aria-label=\"Inline diff view\"\n >\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 6h16M4 12h16M4 18h16\" />\n </svg>\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onModeChange(\"split\");\n }}\n className={cn(\n \"p-1 rounded transition-colors\",\n mode === \"split\"\n ? \"bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300\"\n : \"text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-400\"\n )}\n title=\"Split view\"\n aria-label=\"Split view\"\n >\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 6h16M4 12h16M4 18h7\" />\n </svg>\n </button>\n </div>\n);\n\nexport const VerificationTabs: React.FC<VerificationTabsProps> = ({\n expected,\n actual,\n label,\n renderCopyButton,\n emptyText = \"No text found\",\n // New props\n status,\n anchorText,\n verifiedKeySpan,\n defaultMode = \"auto\",\n expectedPage,\n actualPage,\n showMatchQuality = true,\n maxCollapsedLength = 200,\n}) => {\n const { diffResult, isHighVariance, hasDiff, similarity } = useSmartDiff(expected, actual);\n\n const [activeTab, setActiveTab] = useState<TabType>(\"diff\");\n const [diffMode, setDiffMode] = useState<\"inline\" | \"split\">(() => {\n if (defaultMode === \"inline\") return \"inline\";\n if (defaultMode === \"split\") return \"split\";\n // Auto mode: default based on variance\n return isHighVariance ? \"split\" : \"inline\";\n });\n\n // Update mode when variance changes (for auto mode)\n useEffect(() => {\n if (defaultMode === \"auto\") {\n setDiffMode(isHighVariance ? \"split\" : \"inline\");\n }\n }, [isHighVariance, defaultMode]);\n\n useEffect(() => {\n if (isHighVariance) {\n setActiveTab(\"diff\"); // Stay on diff tab but use split view\n } else {\n setActiveTab(\"diff\");\n }\n }, [isHighVariance, expected, actual]);\n\n // Get contextual status message\n const statusMessage = useMemo(() => {\n return getContextualStatusMessage(status, expectedPage, actualPage);\n }, [status, expectedPage, actualPage]);\n\n const renderFoundContent = () => (\n <div data-testid=\"tab-content-found\" className=\"mt-3\">\n {actual ? (\n <div className=\"relative\">\n {renderCopyButton && <div className=\"absolute top-2 right-2\">{renderCopyButton(actual, \"found\")}</div>}\n <div className=\"p-3 bg-gray-50 dark:bg-gray-800 rounded-md text-sm text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words\">\n <CollapsibleText\n text={actual}\n maxLength={maxCollapsedLength}\n anchorText={verifiedKeySpan}\n anchorTextClass=\"bg-green-200 dark:bg-green-800/50 px-0.5 rounded border-b-2 border-green-400 dark:border-green-500\"\n />\n </div>\n </div>\n ) : (\n <span data-testid=\"empty-text\" className=\"text-sm text-gray-500 dark:text-gray-400 italic\">\n {emptyText}\n </span>\n )}\n </div>\n );\n\n const isExactMatch = !hasDiff && Boolean(actual) && Boolean(expected);\n\n if (isExactMatch) {\n return (\n <div data-testid=\"verification-tabs\" data-exact-match=\"true\" className=\"space-y-2\">\n {label && <div className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">{label}</div>}\n\n <div data-testid=\"exact-match-badge\" className=\"inline-flex items-center gap-1.5 px-2.5 py-1 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 rounded-full text-sm font-medium\">\n <span className=\"size-2\">\n <CheckIcon />\n </span>\n <span>Exact match</span>\n </div>\n\n <div>{renderFoundContent()}</div>\n </div>\n );\n }\n\n return (\n <div data-testid=\"verification-tabs\" className=\"space-y-2\">\n {label && <div data-testid=\"verification-label\" className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">{label}</div>}\n\n {/* Status message for partial matches */}\n {statusMessage && status && status !== \"found\" && status !== \"pending\" && status !== \"loading\" && (\n <div data-testid=\"status-message\" className={cn(\n \"text-xs font-medium px-2 py-1 rounded-md inline-flex items-center gap-1.5\",\n status === \"not_found\"\n ? \"bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400\"\n : \"bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400\"\n )}>\n {status !== \"not_found\" && (\n <span className=\"size-2.5\">\n <CheckIcon />\n </span>\n )}\n {statusMessage}\n </div>\n )}\n\n <div data-testid=\"tabs-container\">\n <div data-testid=\"tabs-nav\" className=\"flex gap-1 p-1 bg-gray-100 dark:bg-gray-800 rounded-lg items-center\">\n <TabButton label=\"Expected\" isActive={activeTab === \"expected\"} onClick={() => setActiveTab(\"expected\")} />\n <TabButton label=\"Diff\" isActive={activeTab === \"diff\"} onClick={() => setActiveTab(\"diff\")} />\n <TabButton label=\"Found\" isActive={activeTab === \"found\"} onClick={() => setActiveTab(\"found\")} />\n {activeTab === \"diff\" && hasDiff && (\n <ModeToggle mode={diffMode} onModeChange={setDiffMode} />\n )}\n </div>\n </div>\n\n <div data-testid=\"tabs-content\">\n {activeTab === \"found\" && renderFoundContent()}\n\n {activeTab === \"expected\" && (\n <div data-testid=\"tab-content-expected\" className=\"mt-3\">\n <div className=\"relative\">\n {renderCopyButton && (\n <div className=\"absolute top-2 right-2\">{renderCopyButton(expected, \"expected\")}</div>\n )}\n <div className=\"p-3 bg-gray-50 dark:bg-gray-800 rounded-md text-sm text-gray-700 dark:text-gray-300 font-mono whitespace-pre-wrap break-words\">\n <CollapsibleText\n text={expected}\n maxLength={maxCollapsedLength}\n anchorText={anchorText}\n anchorTextClass=\"bg-blue-200 dark:bg-blue-800/50 px-0.5 rounded border-b-2 border-blue-400 dark:border-blue-500\"\n />\n </div>\n </div>\n </div>\n )}\n\n {activeTab === \"diff\" && (\n <div data-testid=\"tab-content-diff\" className=\"mt-3\">\n {!hasDiff ? (\n <div data-testid=\"exact-match-indicator\" className=\"inline-flex items-center gap-1.5 text-green-600 dark:text-green-500 text-sm\">\n <span className=\"size-2\">\n <CheckIcon />\n </span>\n <span>Exact Match</span>\n </div>\n ) : diffMode === \"split\" ? (\n // Split view mode\n <SplitDiffDisplay\n expected={expected}\n actual={actual}\n mode=\"split\"\n showMatchQuality={showMatchQuality}\n maxCollapsedLength={maxCollapsedLength}\n anchorTextExpected={anchorText}\n anchorTextFound={verifiedKeySpan}\n status={status}\n similarity={similarity}\n />\n ) : (\n // Inline diff mode\n <div data-testid=\"diff-result\" className=\"space-y-2\">\n {showMatchQuality && (\n <MatchQualityBar similarity={similarity} className=\"mb-2\" />\n )}\n <div className=\"p-3 bg-gray-50 dark:bg-gray-800 rounded-md text-sm font-mono whitespace-pre-wrap break-words\">\n {diffResult.map((block, i) => (\n <div\n key={i}\n className={cn(\n block.type === \"added\" && \"bg-green-50 dark:bg-green-900/20\",\n block.type === \"removed\" && \"bg-red-50 dark:bg-red-900/20\",\n )}\n >\n {block.parts.map((part, j) => {\n if (part.removed) {\n return (\n <span\n key={j}\n data-diff-type=\"removed\"\n className=\"bg-red-200 dark:bg-red-800/50 text-red-800 dark:text-red-200 line-through\"\n title=\"Expected but not found\"\n >\n {part.value}\n </span>\n );\n }\n if (part.added) {\n return (\n <span\n key={j}\n data-diff-type=\"added\"\n className=\"bg-green-200 dark:bg-green-800/50 text-green-800 dark:text-green-200\"\n title=\"Actually found in source\"\n >\n {part.value}\n </span>\n );\n }\n return (\n <span key={j} className=\"text-gray-700 dark:text-gray-300\">\n {part.value}\n </span>\n );\n })}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n"]}