{"version":3,"sources":["../src/utils/cn.ts","../src/utils/pdfjs-init.ts","../src/utils/document-loader.ts","../src/utils/highlight-storage.ts","../src/store/viewer-store.ts","../src/store/annotation-store.ts","../src/utils/convenience.ts","../src/utils/export-annotations.ts","../src/utils/student-storage.ts","../src/utils/agent-api.ts","../src/utils/text-search.ts","../src/utils/coordinates.ts","../src/utils/page-turn-sound.ts","../src/utils/mobile-config.ts","../src/utils/camera-math.ts","../src/utils/index.ts","../src/store/search-store.ts","../src/store/agent-store.ts","../src/store/student-store.ts","../src/store/narration-store.ts","../src/store/index.ts","../src/hooks/PDFViewerContext.tsx","../src/hooks/usePDFViewer.ts","../src/hooks/usePageNavigation.ts","../src/hooks/useZoom.ts","../src/hooks/useTextSelection.ts","../src/hooks/useHighlights.ts","../src/hooks/useAnnotations.ts","../src/hooks/useTouchGestures.ts","../src/plugins/PluginManager.ts","../src/hooks/usePlugins.ts","../src/hooks/useAgentContext.ts","../src/hooks/useAskAbout.ts","../src/hooks/useBookmarks.ts","../src/hooks/useQuickNotes.ts","../src/hooks/useStudentProgress.ts","../src/hooks/index.ts","../src/components/Toolbar/Toolbar.tsx","../src/components/Toolbar/MobileToolbar.tsx","../src/components/Toolbar/index.ts","../src/components/Sidebar/ThumbnailPanel.tsx","../src/components/Sidebar/SearchPanel.tsx","../src/components/Sidebar/OutlinePanel.tsx","../src/components/Sidebar/HighlightsPanel.tsx","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/MobileSidebar.tsx","../src/components/Sidebar/BookmarksPanel.tsx","../src/components/Sidebar/TakeawaysPanel.tsx","../src/components/Sidebar/index.ts","../src/components/AnnotationToolbar/AnnotationToolbar.tsx","../src/components/AnnotationToolbar/index.ts","../src/components/PDFPage/CanvasLayer.tsx","../src/components/PDFPage/TextLayer.tsx","../src/components/PDFPage/HighlightLayer.tsx","../src/components/PDFPage/AnnotationLayer.tsx","../src/components/PDFPage/PDFPage.tsx","../src/components/PDFPage/FocusRegionLayer.tsx","../src/components/PDFPage/index.ts","../src/components/PDFLoadingScreen/PDFLoadingScreen.tsx","../src/components/PDFLoadingScreen/index.ts","../src/components/PDFViewer/PageSkeleton.tsx","../src/components/SelectionToolbar/SelectionToolbar.tsx","../src/components/SelectionToolbar/index.ts","../src/components/HighlightPopover/HighlightPopover.tsx","../src/components/HighlightPopover/index.ts","../src/components/PDFViewer/DocumentContainer.tsx","../src/components/PDFViewer/VirtualizedDocumentContainer.tsx","../src/components/PDFViewer/ContinuousScrollContainer.tsx","../src/components/PDFViewer/DualPageContainer.tsx","../src/components/PDFViewer/BookModeContainer.tsx","../src/components/FloatingZoomControls/FloatingZoomControls.tsx","../src/components/FloatingZoomControls/index.ts","../src/components/PDFViewer/PDFViewerClient.tsx","../src/components/PDFViewer/PDFViewer.tsx","../src/components/PDFViewer/index.ts","../src/index.ts","../src/components/index.ts","../src/components/Annotations/StickyNote.tsx","../src/components/Annotations/DrawingCanvas.tsx","../src/components/Annotations/ShapeRenderer.tsx","../src/components/Annotations/QuickNoteButton.tsx","../src/components/Annotations/QuickNotePopover.tsx","../src/components/AskAbout/AskAboutOverlay.tsx","../src/components/AskAbout/AskAboutTrigger.tsx","../src/components/Minimap/Minimap.tsx","../src/components/PDFThumbnailNav/PDFThumbnailNav.tsx","../src/components/ErrorBoundary/PDFErrorBoundary.tsx","../src/components/TutorMode/TutorModeContainer.tsx","../src/components/TutorMode/CameraView.tsx","../src/components/TutorMode/CinemaLayer.tsx","../src/components/TutorMode/SpotlightMask.tsx","../src/components/TutorMode/tokens.ts","../src/components/TutorMode/AnimatedUnderline.tsx","../src/components/TutorMode/AnimatedHighlight.tsx","../src/components/TutorMode/PulseOverlay.tsx","../src/components/TutorMode/CalloutArrow.tsx","../src/components/TutorMode/BoxOverlay.tsx","../src/components/TutorMode/GhostReferenceOverlay.tsx","../src/components/TutorMode/GhostReference.tsx","../src/components/TutorMode/LabelOverlay.tsx","../src/components/TutorMode/StickyLabel.tsx","../src/components/TutorMode/CalloutLabelOverlay.tsx","../src/components/TutorMode/SubtitleBar.tsx","../src/director/storyboard-engine.ts","../src/director/storyboard-schema.ts","../src/director/prompts.ts","../src/director/sse-parser.ts","../src/director/llm-director.ts","../src/director/embedding-fallback.ts","../src/director/transformers-embedding.ts","../src/plugins/index.ts"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\n\n/**\n * Utility for merging class names with support for conditionals.\n * Uses clsx under the hood.\n */\nexport function cn(...inputs: ClassValue[]): string {\n  return clsx(inputs);\n}\n","import * as pdfjsLib from 'pdfjs-dist';\n\nlet isInitialized = false;\nlet initializationPromise: Promise<void> | null = null;\n\nexport interface PDFJSInitOptions {\n  /** Custom worker source URL */\n  workerSrc?: string;\n  /** Whether to use the fake worker (for testing) */\n  useFakeWorker?: boolean;\n}\n\n/**\n * Initialize pdf.js with the worker.\n * This should be called before loading any PDFs.\n */\nexport async function initializePDFJS(options: PDFJSInitOptions = {}): Promise<void> {\n  if (isInitialized) {\n    return;\n  }\n\n  if (initializationPromise) {\n    return initializationPromise;\n  }\n\n  initializationPromise = (async () => {\n    if (options.useFakeWorker) {\n      // Use fake worker for testing\n      pdfjsLib.GlobalWorkerOptions.workerSrc = '';\n    } else if (options.workerSrc) {\n      // Use custom worker source\n      pdfjsLib.GlobalWorkerOptions.workerSrc = options.workerSrc;\n    } else {\n      // Use the CDN worker for reliability\n      const version = pdfjsLib.version;\n      pdfjsLib.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${version}/pdf.worker.min.mjs`;\n    }\n\n    isInitialized = true;\n  })();\n\n  return initializationPromise;\n}\n\n/**\n * Check if pdf.js is initialized\n */\nexport function isPDFJSInitialized(): boolean {\n  return isInitialized;\n}\n\n/**\n * Reset initialization state (for testing)\n */\nexport function resetPDFJS(): void {\n  isInitialized = false;\n  initializationPromise = null;\n}\n\nexport { pdfjsLib };\n","import type { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist';\nimport { pdfjsLib, initializePDFJS } from './pdfjs-init';\n\nexport interface LoadDocumentOptions {\n  /** URL or data of the PDF */\n  src: string | ArrayBuffer | Uint8Array;\n  /** Custom worker source */\n  workerSrc?: string;\n  /** Password for encrypted PDFs */\n  password?: string;\n  /** Callback for loading progress */\n  onProgress?: (progress: { loaded: number; total: number }) => void;\n  /** Enable range requests for faster loading (default: true) */\n  enableRangeRequests?: boolean;\n  /** Enable streaming for progressive display (default: true) */\n  enableStreaming?: boolean;\n  /** Cache the document data (default: true) */\n  cacheDocument?: boolean;\n  /** AbortSignal for cancellation */\n  signal?: AbortSignal;\n}\n\nexport interface LoadDocumentWithCallbacksOptions extends LoadDocumentOptions {\n  /** Callback when document structure is ready (XRef parsed) */\n  onDocumentReady?: (document: PDFDocumentProxy, numPages: number) => void;\n  /** Callback when the first page is loaded and ready to render */\n  onFirstPageReady?: (page: PDFPageProxy) => void;\n}\n\nexport interface LoadDocumentWithCallbacksResult {\n  /** Promise that resolves when loading is complete */\n  promise: Promise<LoadDocumentResult>;\n  /** Function to cancel loading */\n  cancel: () => void;\n}\n\nexport interface LoadDocumentResult {\n  document: PDFDocumentProxy;\n  numPages: number;\n}\n\n// Document cache to prevent duplicate loading\nconst documentCache = new Map<string, PDFDocumentProxy>();\n\n/**\n * Load a PDF document from a URL or data buffer.\n *\n * Optimizations:\n * - Range requests allow loading only the parts needed (faster initial load)\n * - Streaming allows pages to render as data arrives\n * - Document caching prevents duplicate fetches\n * - Worker handles parsing off the main thread\n */\nexport async function loadDocument(options: LoadDocumentOptions): Promise<LoadDocumentResult> {\n  const {\n    src,\n    workerSrc,\n    password,\n    onProgress,\n    enableRangeRequests = true,\n    enableStreaming = true,\n    cacheDocument = true,\n    signal,\n  } = options;\n\n  // Check if already aborted\n  if (signal?.aborted) {\n    throw new DOMException('Aborted', 'AbortError');\n  }\n\n  // Initialize pdf.js if not already done\n  await initializePDFJS({ workerSrc });\n\n  // Check if aborted during initialization\n  if (signal?.aborted) {\n    throw new DOMException('Aborted', 'AbortError');\n  }\n\n  // Check cache for URL-based documents\n  const cacheKey = typeof src === 'string' ? src : null;\n  if (cacheKey && cacheDocument && documentCache.has(cacheKey)) {\n    const cachedDoc = documentCache.get(cacheKey)!;\n    // Verify the cached doc is still valid (not destroyed)\n    try {\n      // Check if document looks valid - numPages should be > 0\n      // Also check internal state if available\n      const numPages = cachedDoc.numPages;\n      // @ts-expect-error - checking internal destroyed state\n      const isDestroyed = cachedDoc._transport?.destroyed || cachedDoc.destroyed;\n      if (numPages > 0 && !isDestroyed) {\n        return {\n          document: cachedDoc,\n          numPages,\n        };\n      }\n      // Invalid document, remove from cache\n      documentCache.delete(cacheKey);\n    } catch {\n      // Document was destroyed or invalid, remove from cache and reload\n      documentCache.delete(cacheKey);\n    }\n  }\n\n  // Prepare loading parameters\n  const loadingParams: Record<string, unknown> = {\n    password,\n    // Performance optimizations\n    isEvalSupported: false,\n    useSystemFonts: true,\n    // Enable range requests for faster initial load\n    // This allows PDF.js to request only the parts of the PDF it needs\n    disableRange: !enableRangeRequests,\n    // Enable streaming for progressive rendering\n    disableStream: !enableStreaming,\n    // Don't fetch the entire document upfront\n    disableAutoFetch: true,\n  };\n\n  // Set source based on type\n  if (typeof src === 'string') {\n    loadingParams.url = src;\n  } else {\n    loadingParams.data = src;\n  }\n\n  const loadingTask = pdfjsLib.getDocument(loadingParams);\n\n  // Handle abort signal\n  let abortHandler: (() => void) | null = null;\n  if (signal) {\n    abortHandler = () => {\n      loadingTask.destroy();\n    };\n    signal.addEventListener('abort', abortHandler);\n  }\n\n  // Handle progress\n  if (onProgress) {\n    loadingTask.onProgress = ({ loaded, total }: { loaded: number; total: number }) => {\n      onProgress({ loaded, total });\n    };\n  }\n\n  let document: PDFDocumentProxy;\n  try {\n    document = await loadingTask.promise;\n  } catch (error) {\n    // Clean up abort handler\n    if (signal && abortHandler) {\n      signal.removeEventListener('abort', abortHandler);\n    }\n\n    // Check if this was an abort\n    if (signal?.aborted) {\n      throw new DOMException('Aborted', 'AbortError');\n    }\n\n    // Re-throw original error\n    throw error;\n  }\n\n  // Clean up abort handler\n  if (signal && abortHandler) {\n    signal.removeEventListener('abort', abortHandler);\n  }\n\n  // Check if aborted after loading completed\n  if (signal?.aborted) {\n    document.destroy();\n    throw new DOMException('Aborted', 'AbortError');\n  }\n\n  // Cache the document\n  if (cacheKey && cacheDocument) {\n    documentCache.set(cacheKey, document);\n  }\n\n  return {\n    document,\n    numPages: document.numPages,\n  };\n}\n\n/**\n * Get a specific page from a PDF document.\n */\nexport async function getPage(\n  document: PDFDocumentProxy,\n  pageNumber: number\n): Promise<PDFPageProxy> {\n  if (pageNumber < 1 || pageNumber > document.numPages) {\n    throw new Error(`Invalid page number: ${pageNumber}. Document has ${document.numPages} pages.`);\n  }\n\n  return document.getPage(pageNumber);\n}\n\n/**\n * Get text content from a PDF page.\n */\nexport async function getPageTextContent(page: PDFPageProxy) {\n  return page.getTextContent();\n}\n\n/**\n * Get the outline (table of contents) from a PDF document.\n */\nexport async function getOutline(document: PDFDocumentProxy) {\n  return document.getOutline();\n}\n\n/**\n * Get metadata from a PDF document.\n */\nexport async function getMetadata(document: PDFDocumentProxy) {\n  return document.getMetadata();\n}\n\n/**\n * Clear a document from cache.\n */\nexport function clearDocumentCache(url?: string): void {\n  if (url) {\n    const doc = documentCache.get(url);\n    if (doc) {\n      doc.destroy();\n      documentCache.delete(url);\n    }\n  } else {\n    // Clear all\n    for (const doc of documentCache.values()) {\n      doc.destroy();\n    }\n    documentCache.clear();\n  }\n}\n\n/**\n * Load a PDF document with streaming callbacks for progressive loading.\n *\n * This function provides callbacks that fire at different stages of loading:\n * - onDocumentReady: Fires when the document structure (XRef) is parsed\n * - onFirstPageReady: Fires when the first page is loaded and ready to render\n *\n * This enables showing the PDF viewer UI immediately and rendering the first\n * page as soon as it's available, while the rest of the document loads in\n * the background.\n */\nexport function loadDocumentWithCallbacks(\n  options: LoadDocumentWithCallbacksOptions\n): LoadDocumentWithCallbacksResult {\n  const {\n    src,\n    workerSrc,\n    password,\n    onProgress,\n    onDocumentReady,\n    onFirstPageReady,\n    enableRangeRequests = true,\n    enableStreaming = true,\n    cacheDocument = true,\n    signal,\n  } = options;\n\n  // Create internal abort controller\n  const abortController = new AbortController();\n\n  // Link external signal if provided\n  if (signal) {\n    signal.addEventListener('abort', () => abortController.abort());\n  }\n\n  const promise = (async () => {\n    // Check if already aborted\n    if (abortController.signal.aborted) {\n      throw new DOMException('Aborted', 'AbortError');\n    }\n\n    // Initialize pdf.js if not already done\n    await initializePDFJS({ workerSrc });\n\n    // Check if aborted during initialization\n    if (abortController.signal.aborted) {\n      throw new DOMException('Aborted', 'AbortError');\n    }\n\n    // Check cache for URL-based documents\n    const cacheKey = typeof src === 'string' ? src : null;\n    if (cacheKey && cacheDocument && documentCache.has(cacheKey)) {\n      const cachedDoc = documentCache.get(cacheKey)!;\n      try {\n        const numPages = cachedDoc.numPages;\n        // @ts-expect-error - checking internal destroyed state\n        const isDestroyed = cachedDoc._transport?.destroyed || cachedDoc.destroyed;\n        if (numPages > 0 && !isDestroyed) {\n          // Fire callbacks for cached document\n          onDocumentReady?.(cachedDoc, numPages);\n\n          // Load first page\n          if (onFirstPageReady && numPages > 0) {\n            try {\n              const firstPage = await cachedDoc.getPage(1);\n              if (!abortController.signal.aborted) {\n                onFirstPageReady(firstPage);\n              }\n            } catch {\n              // First page load failed, but document is still valid\n            }\n          }\n\n          return {\n            document: cachedDoc,\n            numPages,\n          };\n        }\n        documentCache.delete(cacheKey);\n      } catch {\n        documentCache.delete(cacheKey);\n      }\n    }\n\n    // Prepare loading parameters\n    const loadingParams: Record<string, unknown> = {\n      password,\n      isEvalSupported: false,\n      useSystemFonts: true,\n      disableRange: !enableRangeRequests,\n      disableStream: !enableStreaming,\n      disableAutoFetch: true,\n    };\n\n    if (typeof src === 'string') {\n      loadingParams.url = src;\n    } else {\n      loadingParams.data = src;\n    }\n\n    const loadingTask = pdfjsLib.getDocument(loadingParams);\n\n    // Handle abort signal\n    const abortHandler = () => {\n      loadingTask.destroy();\n    };\n    abortController.signal.addEventListener('abort', abortHandler);\n\n    // Handle progress\n    if (onProgress) {\n      loadingTask.onProgress = ({ loaded, total }: { loaded: number; total: number }) => {\n        if (!abortController.signal.aborted) {\n          onProgress({ loaded, total });\n        }\n      };\n    }\n\n    let document: PDFDocumentProxy;\n    try {\n      document = await loadingTask.promise;\n    } catch (error) {\n      abortController.signal.removeEventListener('abort', abortHandler);\n\n      if (abortController.signal.aborted) {\n        throw new DOMException('Aborted', 'AbortError');\n      }\n\n      throw error;\n    }\n\n    abortController.signal.removeEventListener('abort', abortHandler);\n\n    if (abortController.signal.aborted) {\n      document.destroy();\n      throw new DOMException('Aborted', 'AbortError');\n    }\n\n    // Document is ready - fire callback\n    const numPages = document.numPages;\n    onDocumentReady?.(document, numPages);\n\n    // Load first page immediately and fire callback\n    if (onFirstPageReady && numPages > 0) {\n      try {\n        const firstPage = await document.getPage(1);\n        if (!abortController.signal.aborted) {\n          onFirstPageReady(firstPage);\n        }\n      } catch {\n        // First page load failed, but document is still valid\n      }\n    }\n\n    // Cache the document\n    if (cacheKey && cacheDocument) {\n      documentCache.set(cacheKey, document);\n    }\n\n    return {\n      document,\n      numPages,\n    };\n  })();\n\n  return {\n    promise,\n    cancel: () => abortController.abort(),\n  };\n}\n\n/**\n * Preload a PDF document into cache without returning it.\n * Useful for prefetching documents the user might view next.\n */\nexport async function preloadDocument(url: string): Promise<void> {\n  if (documentCache.has(url)) return;\n\n  await loadDocument({ src: url, cacheDocument: true });\n}\n","import type { Highlight, HighlightColor } from '../types';\n\nconst STORAGE_PREFIX = 'pdf-reader-highlights';\n\n/**\n * Generate a storage key for a document.\n * Uses documentId to uniquely identify each PDF's highlights.\n */\nfunction getStorageKey(documentId: string): string {\n  return `${STORAGE_PREFIX}:${documentId}`;\n}\n\n/**\n * Check if localStorage is available (SSR-safe).\n */\nfunction isStorageAvailable(): boolean {\n  if (typeof window === 'undefined') return false;\n  try {\n    const test = '__storage_test__';\n    localStorage.setItem(test, test);\n    localStorage.removeItem(test);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Serializable version of a highlight for storage.\n * Dates are stored as ISO strings.\n */\ninterface StoredHighlight {\n  id: string;\n  pageNumber: number;\n  rects: Array<{ x: number; y: number; width: number; height: number }>;\n  color: HighlightColor;\n  text: string;\n  comment?: string;\n  createdAt: string;\n  updatedAt: string;\n}\n\n/**\n * Convert a Highlight to storable format.\n */\nfunction toStoredHighlight(highlight: Highlight): StoredHighlight {\n  return {\n    ...highlight,\n    createdAt: highlight.createdAt.toISOString(),\n    updatedAt: highlight.updatedAt.toISOString(),\n  };\n}\n\n/**\n * Convert a stored highlight back to a Highlight.\n */\nfunction fromStoredHighlight(stored: StoredHighlight): Highlight {\n  return {\n    ...stored,\n    createdAt: new Date(stored.createdAt),\n    updatedAt: new Date(stored.updatedAt),\n  };\n}\n\n/**\n * Save highlights to localStorage for a specific document.\n *\n * @param documentId - Unique identifier for the document (e.g., URL hash, filename)\n * @param highlights - Array of highlights to save\n * @returns true if save succeeded, false otherwise\n */\nexport function saveHighlights(documentId: string, highlights: Highlight[]): boolean {\n  if (!isStorageAvailable()) {\n    console.warn('localStorage not available, highlights will not persist');\n    return false;\n  }\n\n  try {\n    const key = getStorageKey(documentId);\n    const storedHighlights = highlights.map(toStoredHighlight);\n    localStorage.setItem(key, JSON.stringify(storedHighlights));\n    return true;\n  } catch (error) {\n    console.error('Failed to save highlights:', error);\n    return false;\n  }\n}\n\n/**\n * Load highlights from localStorage for a specific document.\n *\n * @param documentId - Unique identifier for the document\n * @returns Array of highlights, empty array if none found or error\n */\nexport function loadHighlights(documentId: string): Highlight[] {\n  if (!isStorageAvailable()) {\n    return [];\n  }\n\n  try {\n    const key = getStorageKey(documentId);\n    const stored = localStorage.getItem(key);\n\n    if (!stored) {\n      return [];\n    }\n\n    const parsed = JSON.parse(stored) as StoredHighlight[];\n    return parsed.map(fromStoredHighlight);\n  } catch (error) {\n    console.error('Failed to load highlights:', error);\n    return [];\n  }\n}\n\n/**\n * Remove all highlights for a specific document from localStorage.\n *\n * @param documentId - Unique identifier for the document\n * @returns true if removal succeeded, false otherwise\n */\nexport function clearHighlights(documentId: string): boolean {\n  if (!isStorageAvailable()) {\n    return false;\n  }\n\n  try {\n    const key = getStorageKey(documentId);\n    localStorage.removeItem(key);\n    return true;\n  } catch (error) {\n    console.error('Failed to clear highlights:', error);\n    return false;\n  }\n}\n\n/**\n * Get all document IDs that have stored highlights.\n *\n * @returns Array of document IDs\n */\nexport function getAllDocumentIds(): string[] {\n  if (!isStorageAvailable()) {\n    return [];\n  }\n\n  const ids: string[] = [];\n  const prefixLength = STORAGE_PREFIX.length + 1; // +1 for the colon\n\n  for (let i = 0; i < localStorage.length; i++) {\n    const key = localStorage.key(i);\n    if (key?.startsWith(STORAGE_PREFIX + ':')) {\n      ids.push(key.slice(prefixLength));\n    }\n  }\n\n  return ids;\n}\n\n/**\n * Export highlights as a JSON string.\n * Includes metadata for import/export portability.\n *\n * @param highlights - Array of highlights to export\n * @returns JSON string representation\n */\nexport function exportHighlightsAsJSON(highlights: Highlight[]): string {\n  const exportData = {\n    version: 1,\n    exportedAt: new Date().toISOString(),\n    highlights: highlights.map(toStoredHighlight),\n  };\n\n  return JSON.stringify(exportData, null, 2);\n}\n\n/**\n * Import highlights from a JSON string.\n *\n * @param json - JSON string to import\n * @returns Array of highlights, or null if invalid\n */\nexport function importHighlightsFromJSON(json: string): Highlight[] | null {\n  try {\n    const data = JSON.parse(json);\n\n    // Handle both direct array format and wrapped format\n    let highlights: StoredHighlight[];\n    if (Array.isArray(data)) {\n      highlights = data;\n    } else if (data.highlights && Array.isArray(data.highlights)) {\n      highlights = data.highlights;\n    } else {\n      return null;\n    }\n\n    return highlights.map(fromStoredHighlight);\n  } catch (error) {\n    console.error('Failed to import highlights:', error);\n    return null;\n  }\n}\n\n/**\n * Export highlights as Markdown format.\n * Groups by page and includes text, comments, and metadata.\n *\n * @param highlights - Array of highlights to export\n * @param documentTitle - Optional document title for the header\n * @returns Markdown string representation\n */\nexport function exportHighlightsAsMarkdown(\n  highlights: Highlight[],\n  documentTitle?: string\n): string {\n  const lines: string[] = [];\n\n  // Header\n  lines.push(`# ${documentTitle || 'PDF Highlights'}`);\n  lines.push('');\n  lines.push(`Exported on ${new Date().toLocaleDateString()}`);\n  lines.push('');\n\n  if (highlights.length === 0) {\n    lines.push('_No highlights_');\n    return lines.join('\\n');\n  }\n\n  // Group by page\n  const byPage = new Map<number, Highlight[]>();\n  highlights.forEach((h) => {\n    if (!byPage.has(h.pageNumber)) {\n      byPage.set(h.pageNumber, []);\n    }\n    byPage.get(h.pageNumber)!.push(h);\n  });\n\n  // Sort pages\n  const sortedPages = Array.from(byPage.keys()).sort((a, b) => a - b);\n\n  // Render each page group\n  sortedPages.forEach((pageNumber) => {\n    lines.push(`## Page ${pageNumber}`);\n    lines.push('');\n\n    const pageHighlights = byPage.get(pageNumber)!;\n    // Sort highlights by vertical position\n    pageHighlights.sort((a, b) => (a.rects[0]?.y ?? 0) - (b.rects[0]?.y ?? 0));\n\n    pageHighlights.forEach((highlight) => {\n      // Color indicator as emoji\n      const colorEmoji = {\n        yellow: '🟡',\n        green: '🟢',\n        blue: '🔵',\n        pink: '🩷',\n        orange: '🟠',\n      }[highlight.color];\n\n      lines.push(`${colorEmoji} > ${highlight.text}`);\n\n      if (highlight.comment) {\n        lines.push('');\n        lines.push(`**Note:** ${highlight.comment}`);\n      }\n\n      lines.push('');\n    });\n  });\n\n  // Summary\n  lines.push('---');\n  lines.push(`*${highlights.length} highlight${highlights.length !== 1 ? 's' : ''} total*`);\n\n  return lines.join('\\n');\n}\n\n/**\n * Generate a document ID from a URL or file path.\n * Creates a consistent hash for the same document.\n *\n * @param source - URL or file path\n * @returns Document ID string\n */\nexport function generateDocumentId(source: string | ArrayBuffer | Uint8Array): string {\n  if (typeof source === 'string') {\n    // For URLs, use a simplified hash\n    let hash = 0;\n    for (let i = 0; i < source.length; i++) {\n      const char = source.charCodeAt(i);\n      hash = ((hash << 5) - hash) + char;\n      hash = hash & hash; // Convert to 32bit integer\n    }\n    return `doc-${Math.abs(hash).toString(36)}`;\n  }\n\n  // For binary data, use size-based ID (not ideal but simple)\n  const size = source instanceof ArrayBuffer ? source.byteLength : source.length;\n  return `doc-binary-${size}`;\n}\n","import { createStore } from 'zustand/vanilla';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport type { ViewerState, ViewerActions, ViewMode, Theme, SidebarPanel, ScrollMode, DocumentLoadingState, StreamingProgress } from '../types';\n\nconst ZOOM_LEVELS = [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0];\nconst MIN_SCALE = 0.1;\nconst MAX_SCALE = 10;\nconst SCROLL_TIMEOUT_MS = 3000;\n\nexport type ViewerStore = ViewerState & ViewerActions;\n\n// Map to hold Promise resolvers for scroll requests\nconst scrollCallbacks = new Map<string, { resolve: () => void; timeoutId: ReturnType<typeof setTimeout> }>();\n\n// Generate unique request ID\nlet requestCounter = 0;\nfunction generateRequestId(): string {\n  return `scroll-${Date.now()}-${++requestCounter}`;\n}\n\nconst initialState: ViewerState = {\n  // Document state\n  document: null,\n  numPages: 0,\n  isLoading: false,\n  loadingProgress: null,\n  error: null,\n\n  // Progressive loading state\n  documentLoadingState: 'idle',\n  firstPageReady: false,\n  streamingProgress: null,\n\n  // Navigation state\n  currentPage: 1,\n  scale: 1.0,\n  rotation: 0,\n\n  // Scroll coordination\n  scrollToPageRequest: null,\n\n  // UI state\n  viewMode: 'single',\n  scrollMode: 'single',\n  theme: 'light',\n  sidebarOpen: false,\n  sidebarPanel: 'thumbnails',\n\n  // Feature states\n  isFullscreen: false,\n  isPresentationMode: false,\n};\n\nexport function createViewerStore(initialOverrides: Partial<ViewerState> = {}) {\n  return createStore<ViewerStore>()((set, get) => ({\n    ...initialState,\n    ...initialOverrides,\n\n    // Document actions\n    setDocument: (document: PDFDocumentProxy | null) => {\n      if (document) {\n        set({\n          document,\n          numPages: document.numPages,\n          isLoading: false,\n          loadingProgress: null,\n          error: null,\n          currentPage: 1,\n          documentLoadingState: 'ready',\n        });\n      } else {\n        set({\n          document: null,\n          numPages: 0,\n          isLoading: false,\n          loadingProgress: null,\n          documentLoadingState: 'idle',\n          firstPageReady: false,\n          streamingProgress: null,\n        });\n      }\n    },\n\n    setLoading: (isLoading: boolean, progress?: ViewerState['loadingProgress']) => {\n      set({\n        isLoading,\n        loadingProgress: isLoading ? (progress ?? { phase: 'initializing' }) : null,\n      });\n    },\n\n    setLoadingProgress: (progress: ViewerState['loadingProgress']) => {\n      set({ loadingProgress: progress });\n    },\n\n    setError: (error: Error | null) => {\n      set({ error, isLoading: false, loadingProgress: null, documentLoadingState: error ? 'error' : 'idle' });\n    },\n\n    // Progressive loading actions\n    setDocumentLoadingState: (documentLoadingState: DocumentLoadingState) => {\n      set({ documentLoadingState });\n    },\n\n    setFirstPageReady: (firstPageReady: boolean) => {\n      set({ firstPageReady });\n    },\n\n    setStreamingProgress: (streamingProgress: StreamingProgress | null) => {\n      set({ streamingProgress });\n    },\n\n    // Navigation actions\n    setCurrentPage: (page: number) => {\n      const { numPages } = get();\n      if (page >= 1 && page <= numPages) {\n        set({ currentPage: page });\n      }\n    },\n\n    goToPage: (page: number) => {\n      const { numPages } = get();\n      const validPage = Math.max(1, Math.min(page, numPages));\n      set({ currentPage: validPage });\n    },\n\n    nextPage: () => {\n      const { currentPage, numPages } = get();\n      if (currentPage < numPages) {\n        set({ currentPage: currentPage + 1 });\n      }\n    },\n\n    previousPage: () => {\n      const { currentPage } = get();\n      if (currentPage > 1) {\n        set({ currentPage: currentPage - 1 });\n      }\n    },\n\n    // Scroll coordination actions\n    requestScrollToPage: (page: number, behavior: 'smooth' | 'instant' = 'smooth') => {\n      const { numPages } = get();\n      const validPage = Math.max(1, Math.min(page, numPages));\n\n      return new Promise<void>((resolve) => {\n        const requestId = generateRequestId();\n\n        // Set up timeout fallback\n        const timeoutId = setTimeout(() => {\n          const callback = scrollCallbacks.get(requestId);\n          if (callback) {\n            scrollCallbacks.delete(requestId);\n            callback.resolve();\n          }\n          // Clear the request if it's still pending\n          const currentRequest = get().scrollToPageRequest;\n          if (currentRequest?.requestId === requestId) {\n            set({ scrollToPageRequest: null });\n          }\n        }, SCROLL_TIMEOUT_MS);\n\n        // Store the callback\n        scrollCallbacks.set(requestId, { resolve, timeoutId });\n\n        // Set the scroll request and update current page\n        set({\n          currentPage: validPage,\n          scrollToPageRequest: {\n            page: validPage,\n            requestId,\n            behavior,\n          },\n        });\n      });\n    },\n\n    completeScrollRequest: (requestId: string) => {\n      const callback = scrollCallbacks.get(requestId);\n      if (callback) {\n        clearTimeout(callback.timeoutId);\n        scrollCallbacks.delete(requestId);\n        callback.resolve();\n      }\n\n      // Clear the request if it matches\n      const currentRequest = get().scrollToPageRequest;\n      if (currentRequest?.requestId === requestId) {\n        set({ scrollToPageRequest: null });\n      }\n    },\n\n    // Zoom actions\n    setScale: (scale: number) => {\n      const clampedScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));\n      set({ scale: clampedScale });\n    },\n\n    zoomIn: () => {\n      const { scale } = get();\n      const currentIndex = ZOOM_LEVELS.findIndex((z) => z >= scale);\n      const nextIndex = Math.min(currentIndex + 1, ZOOM_LEVELS.length - 1);\n      set({ scale: ZOOM_LEVELS[nextIndex] ?? MAX_SCALE });\n    },\n\n    zoomOut: () => {\n      const { scale } = get();\n      const currentIndex = ZOOM_LEVELS.findIndex((z) => z >= scale);\n      const prevIndex = Math.max(currentIndex - 1, 0);\n      set({ scale: ZOOM_LEVELS[prevIndex] ?? MIN_SCALE });\n    },\n\n    fitToWidth: () => {\n      // This will be calculated by the component based on container width\n      // For now, just set a reasonable default\n      set({ scale: 1.0 });\n    },\n\n    fitToPage: () => {\n      // This will be calculated by the component based on container size\n      // For now, just set a reasonable default\n      set({ scale: 1.0 });\n    },\n\n    // Rotation actions\n    setRotation: (rotation: number) => {\n      // Normalize rotation to 0, 90, 180, or 270\n      const normalizedRotation = ((rotation % 360) + 360) % 360;\n      set({ rotation: normalizedRotation });\n    },\n\n    rotateClockwise: () => {\n      const { rotation } = get();\n      set({ rotation: (rotation + 90) % 360 });\n    },\n\n    rotateCounterClockwise: () => {\n      const { rotation } = get();\n      set({ rotation: (rotation - 90 + 360) % 360 });\n    },\n\n    // UI actions\n    setViewMode: (viewMode: ViewMode) => {\n      set({ viewMode });\n    },\n\n    setScrollMode: (scrollMode: ScrollMode) => {\n      set({ scrollMode });\n    },\n\n    setTheme: (theme: Theme) => {\n      set({ theme });\n    },\n\n    toggleSidebar: () => {\n      const { sidebarOpen } = get();\n      set({ sidebarOpen: !sidebarOpen });\n    },\n\n    setSidebarPanel: (sidebarPanel: SidebarPanel) => {\n      set({ sidebarPanel, sidebarOpen: sidebarPanel !== null });\n    },\n\n    setFullscreen: (isFullscreen: boolean) => {\n      set({ isFullscreen });\n    },\n\n    // Reset\n    reset: () => {\n      const { document } = get();\n      if (document) {\n        document.destroy();\n      }\n      set(initialState);\n    },\n  }));\n}\n\n// Type for the store\nexport type ViewerStoreApi = ReturnType<typeof createViewerStore>;\n","import { createStore } from 'zustand/vanilla';\nimport type { Highlight, Annotation, HighlightColor, DrawingPath } from '../types';\n\nexport type AnnotationTool = 'note' | 'draw' | 'shape' | null;\nexport type ShapeType = 'rect' | 'circle' | 'arrow' | 'line';\n\nexport interface AnnotationState {\n  highlights: Highlight[];\n  annotations: Annotation[];\n  selectedHighlightId: string | null;\n  selectedAnnotationId: string | null;\n  activeHighlightColor: HighlightColor;\n  isHighlightMode: boolean;\n  isAnnotationMode: boolean;\n\n  // Drawing state\n  activeAnnotationTool: AnnotationTool;\n  activeShapeType: ShapeType;\n  drawingColor: string;\n  drawingStrokeWidth: number;\n  currentDrawingPath: DrawingPath | null;\n  currentDrawingPage: number | null;\n}\n\nexport interface AnnotationActions {\n  // Highlight actions\n  addHighlight: (highlight: Omit<Highlight, 'id' | 'createdAt' | 'updatedAt'>) => Highlight;\n  updateHighlight: (id: string, updates: Partial<Highlight>) => void;\n  removeHighlight: (id: string) => void;\n  selectHighlight: (id: string | null) => void;\n  setActiveHighlightColor: (color: HighlightColor) => void;\n  getHighlightsByPage: (pageNumber: number) => Highlight[];\n\n  // Annotation actions\n  addAnnotation: (annotation: Omit<Annotation, 'id' | 'createdAt' | 'updatedAt'>) => Annotation;\n  updateAnnotation: (id: string, updates: Partial<Annotation>) => void;\n  removeAnnotation: (id: string) => void;\n  selectAnnotation: (id: string | null) => void;\n  getAnnotationsByPage: (pageNumber: number) => Annotation[];\n\n  // Mode actions\n  setHighlightMode: (enabled: boolean) => void;\n  setAnnotationMode: (enabled: boolean) => void;\n\n  // Drawing tool actions\n  setActiveAnnotationTool: (tool: AnnotationTool) => void;\n  setActiveShapeType: (shapeType: ShapeType) => void;\n  setDrawingColor: (color: string) => void;\n  setDrawingStrokeWidth: (width: number) => void;\n\n  // Drawing path actions\n  startDrawing: (pageNumber: number, point: { x: number; y: number }) => void;\n  addDrawingPoint: (point: { x: number; y: number }) => void;\n  finishDrawing: () => Annotation | null;\n  cancelDrawing: () => void;\n\n  // Export/Import\n  exportHighlights: () => string;\n  importHighlights: (json: string) => void;\n  exportAnnotations: () => string;\n  importAnnotations: (json: string) => void;\n\n  // Reset\n  clearAll: () => void;\n}\n\nexport type AnnotationStore = AnnotationState & AnnotationActions;\n\nconst initialState: AnnotationState = {\n  highlights: [],\n  annotations: [],\n  selectedHighlightId: null,\n  selectedAnnotationId: null,\n  activeHighlightColor: 'yellow',\n  isHighlightMode: false,\n  isAnnotationMode: false,\n\n  // Drawing state defaults\n  activeAnnotationTool: null,\n  activeShapeType: 'rect',\n  drawingColor: '#ef4444',\n  drawingStrokeWidth: 2,\n  currentDrawingPath: null,\n  currentDrawingPage: null,\n};\n\nfunction generateId(): string {\n  return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\nexport function createAnnotationStore(initialOverrides: Partial<AnnotationState> = {}) {\n  return createStore<AnnotationStore>()((set, get) => ({\n    ...initialState,\n    ...initialOverrides,\n\n    // Highlight actions\n    addHighlight: (highlight) => {\n      const newHighlight: Highlight = {\n        ...highlight,\n        id: generateId(),\n        createdAt: new Date(),\n        updatedAt: new Date(),\n      };\n      set((state) => ({\n        highlights: [...state.highlights, newHighlight],\n      }));\n      return newHighlight;\n    },\n\n    updateHighlight: (id, updates) => {\n      set((state) => ({\n        highlights: state.highlights.map((h) =>\n          h.id === id ? { ...h, ...updates, updatedAt: new Date() } : h\n        ),\n      }));\n    },\n\n    removeHighlight: (id) => {\n      set((state) => ({\n        highlights: state.highlights.filter((h) => h.id !== id),\n        selectedHighlightId: state.selectedHighlightId === id ? null : state.selectedHighlightId,\n      }));\n    },\n\n    selectHighlight: (id) => {\n      set({ selectedHighlightId: id });\n    },\n\n    setActiveHighlightColor: (color) => {\n      set({ activeHighlightColor: color });\n    },\n\n    getHighlightsByPage: (pageNumber) => {\n      return get().highlights.filter((h) => h.pageNumber === pageNumber);\n    },\n\n    // Annotation actions\n    addAnnotation: (annotation) => {\n      const newAnnotation = {\n        ...annotation,\n        id: generateId(),\n        createdAt: new Date(),\n        updatedAt: new Date(),\n      } as Annotation;\n      set((state) => ({\n        annotations: [...state.annotations, newAnnotation],\n      }));\n      return newAnnotation;\n    },\n\n    updateAnnotation: (id, updates) => {\n      set((state) => ({\n        annotations: state.annotations.map((a) =>\n          a.id === id ? { ...a, ...updates, updatedAt: new Date() } : a\n        ) as Annotation[],\n      }));\n    },\n\n    removeAnnotation: (id) => {\n      set((state) => ({\n        annotations: state.annotations.filter((a) => a.id !== id),\n        selectedAnnotationId: state.selectedAnnotationId === id ? null : state.selectedAnnotationId,\n      }));\n    },\n\n    selectAnnotation: (id) => {\n      set({ selectedAnnotationId: id });\n    },\n\n    getAnnotationsByPage: (pageNumber) => {\n      return get().annotations.filter((a) => a.pageNumber === pageNumber);\n    },\n\n    // Mode actions\n    setHighlightMode: (enabled) => {\n      set({\n        isHighlightMode: enabled,\n        isAnnotationMode: enabled ? false : get().isAnnotationMode,\n        activeAnnotationTool: enabled ? null : get().activeAnnotationTool,\n      });\n    },\n\n    setAnnotationMode: (enabled) => {\n      set({\n        isAnnotationMode: enabled,\n        isHighlightMode: enabled ? false : get().isHighlightMode,\n      });\n    },\n\n    // Drawing tool actions\n    setActiveAnnotationTool: (tool) => {\n      set({\n        activeAnnotationTool: tool,\n        isAnnotationMode: tool !== null,\n        isHighlightMode: false,\n        currentDrawingPath: null,\n        currentDrawingPage: null,\n      });\n    },\n\n    setActiveShapeType: (shapeType) => {\n      set({ activeShapeType: shapeType });\n    },\n\n    setDrawingColor: (color) => {\n      set({ drawingColor: color });\n    },\n\n    setDrawingStrokeWidth: (width) => {\n      set({ drawingStrokeWidth: Math.max(1, Math.min(20, width)) });\n    },\n\n    // Drawing path actions\n    startDrawing: (pageNumber, point) => {\n      set({\n        currentDrawingPath: { points: [point] },\n        currentDrawingPage: pageNumber,\n      });\n    },\n\n    addDrawingPoint: (point) => {\n      const { currentDrawingPath } = get();\n      if (currentDrawingPath) {\n        set({\n          currentDrawingPath: {\n            points: [...currentDrawingPath.points, point],\n          },\n        });\n      }\n    },\n\n    finishDrawing: () => {\n      const { currentDrawingPath, currentDrawingPage, activeAnnotationTool, drawingColor, drawingStrokeWidth } = get();\n\n      if (!currentDrawingPath || currentDrawingPage === null || activeAnnotationTool !== 'draw') {\n        set({ currentDrawingPath: null, currentDrawingPage: null });\n        return null;\n      }\n\n      // Only create annotation if we have at least 2 points\n      if (currentDrawingPath.points.length < 2) {\n        set({ currentDrawingPath: null, currentDrawingPage: null });\n        return null;\n      }\n\n      const newAnnotation = {\n        type: 'drawing' as const,\n        pageNumber: currentDrawingPage,\n        paths: [currentDrawingPath],\n        color: drawingColor,\n        strokeWidth: drawingStrokeWidth,\n        id: generateId(),\n        createdAt: new Date(),\n        updatedAt: new Date(),\n      };\n\n      set((state) => ({\n        annotations: [...state.annotations, newAnnotation],\n        currentDrawingPath: null,\n        currentDrawingPage: null,\n      }));\n\n      return newAnnotation;\n    },\n\n    cancelDrawing: () => {\n      set({ currentDrawingPath: null, currentDrawingPage: null });\n    },\n\n    // Export/Import\n    exportHighlights: () => {\n      const highlights = get().highlights;\n      return JSON.stringify(highlights, null, 2);\n    },\n\n    importHighlights: (json) => {\n      try {\n        const highlights = JSON.parse(json) as Highlight[];\n        set({ highlights });\n      } catch {\n        console.error('Failed to import highlights');\n      }\n    },\n\n    exportAnnotations: () => {\n      const annotations = get().annotations;\n      return JSON.stringify(annotations, null, 2);\n    },\n\n    importAnnotations: (json) => {\n      try {\n        const annotations = JSON.parse(json) as Annotation[];\n        set({ annotations });\n      } catch {\n        console.error('Failed to import annotations');\n      }\n    },\n\n    // Reset\n    clearAll: () => {\n      set({\n        ...initialState,\n        // Preserve user preferences\n        drawingColor: get().drawingColor,\n        drawingStrokeWidth: get().drawingStrokeWidth,\n        activeHighlightColor: get().activeHighlightColor,\n      });\n    },\n  }));\n}\n\nexport type AnnotationStoreApi = ReturnType<typeof createAnnotationStore>;\n","import { createRoot, Root } from 'react-dom/client';\nimport { createElement } from 'react';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport { PDFViewer } from '../components/PDFViewer';\nimport { createViewerStore } from '../store/viewer-store';\nimport { createAnnotationStore } from '../store/annotation-store';\nimport { loadDocument } from './document-loader';\nimport type {\n  Highlight,\n  Annotation,\n  Theme,\n  ViewMode,\n  SidebarPanel,\n  PDFViewerProps,\n  PDFDocumentLoadedEvent,\n} from '../types';\n\nexport interface PDFViewerControllerOptions {\n  /** Initial page number */\n  initialPage?: number;\n  /** Initial scale/zoom level */\n  initialScale?: number;\n  /** Theme mode */\n  theme?: Theme;\n  /** Whether to show the toolbar */\n  showToolbar?: boolean;\n  /** Whether to show the sidebar */\n  showSidebar?: boolean;\n  /** Custom onDocumentLoad callback */\n  onDocumentLoad?: (doc: PDFDocumentProxy) => void;\n  /** Custom onPageChange callback */\n  onPageChange?: (page: number) => void;\n  /** Custom onScaleChange callback */\n  onScaleChange?: (scale: number) => void;\n  /** Custom onError callback */\n  onError?: (error: Error) => void;\n  /** PDF source - URL, ArrayBuffer, or Uint8Array */\n  src?: string | ArrayBuffer | Uint8Array;\n}\n\nexport interface PDFViewerController {\n  // Document operations\n  loadDocument(src: string | ArrayBuffer | Uint8Array): Promise<void>;\n  getDocument(): PDFDocumentProxy | null;\n\n  // Navigation\n  goToPage(page: number): void;\n  nextPage(): void;\n  previousPage(): void;\n  getCurrentPage(): number;\n  getTotalPages(): number;\n\n  // Zoom\n  setZoom(scale: number): void;\n  zoomIn(): void;\n  zoomOut(): void;\n  fitToWidth(): void;\n  fitToPage(): void;\n  getZoom(): number;\n\n  // Rotation\n  setRotation(rotation: number): void;\n  rotateClockwise(): void;\n  rotateCounterClockwise(): void;\n  getRotation(): number;\n\n  // Theme & View\n  setTheme(theme: Theme): void;\n  getTheme(): Theme;\n  setViewMode(mode: ViewMode): void;\n  getViewMode(): ViewMode;\n\n  // Sidebar\n  toggleSidebar(): void;\n  setSidebarPanel(panel: SidebarPanel): void;\n  isSidebarOpen(): boolean;\n\n  // Highlights\n  getHighlights(): Highlight[];\n  addHighlight(highlight: Omit<Highlight, 'id' | 'createdAt' | 'updatedAt'>): Highlight;\n  removeHighlight(id: string): void;\n  exportHighlights(): string;\n  importHighlights(json: string): void;\n\n  // Annotations\n  getAnnotations(): Annotation[];\n  addAnnotation(annotation: Omit<Annotation, 'id' | 'createdAt' | 'updatedAt'>): Annotation;\n  removeAnnotation(id: string): void;\n  exportAnnotations(): string;\n  importAnnotations(json: string): void;\n\n  // Events\n  on<K extends keyof PDFViewerEventHandlers>(\n    event: K,\n    handler: PDFViewerEventHandlers[K]\n  ): () => void;\n\n  // Lifecycle\n  destroy(): void;\n}\n\ninterface PDFViewerEventHandlers {\n  pagechange: (page: number) => void;\n  scalechange: (scale: number) => void;\n  documentload: (doc: PDFDocumentProxy) => void;\n  error: (error: Error) => void;\n}\n\ntype EventType = keyof PDFViewerEventHandlers;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype EventHandler = (data: any) => void;\n\n/**\n * Create a PDF viewer instance for non-React usage\n */\nexport function createPDFViewer(\n  container: HTMLElement,\n  options: PDFViewerControllerOptions = {}\n): PDFViewerController {\n  // Create stores\n  const viewerStore = createViewerStore();\n  const annotationStore = createAnnotationStore();\n\n  // Event handlers\n  const eventHandlers: Map<EventType, Set<EventHandler>> = new Map();\n\n  // React root\n  let root: Root | null = null;\n  let isDestroyed = false;\n\n  // Helper to emit events\n  const emit = (event: EventType, data: unknown) => {\n    const handlers = eventHandlers.get(event);\n    if (handlers) {\n      handlers.forEach((handler) => handler(data));\n    }\n  };\n\n  // Render the viewer\n  const render = (src?: string | ArrayBuffer | Uint8Array) => {\n    if (isDestroyed) return;\n\n    if (!root) {\n      root = createRoot(container);\n    }\n\n    const props: PDFViewerProps = {\n      src: src || '',\n      initialPage: options.initialPage,\n      initialScale: options.initialScale,\n      theme: options.theme,\n      showToolbar: options.showToolbar,\n      showSidebar: options.showSidebar,\n      onDocumentLoad: (event: PDFDocumentLoadedEvent) => {\n        options.onDocumentLoad?.(event.document);\n        emit('documentload', event.document);\n      },\n      onPageChange: (page: number) => {\n        options.onPageChange?.(page);\n        emit('pagechange', page);\n      },\n      onScaleChange: (scale: number) => {\n        options.onScaleChange?.(scale);\n        emit('scalechange', scale);\n      },\n      onError: (error: Error) => {\n        options.onError?.(error);\n        emit('error', error);\n      },\n    };\n\n    root.render(createElement(PDFViewer, props));\n  };\n\n  // Initialize with empty render if no src provided\n  if (options.src) {\n    render(options.src);\n  }\n\n  // Controller implementation\n  const controller: PDFViewerController = {\n    // Document operations\n    async loadDocument(src: string | ArrayBuffer | Uint8Array) {\n      render(src);\n      // Wait for document to load\n      const result = await loadDocument({ src });\n      viewerStore.getState().setDocument(result.document);\n    },\n\n    getDocument() {\n      return viewerStore.getState().document;\n    },\n\n    // Navigation\n    goToPage(page: number) {\n      viewerStore.getState().goToPage(page);\n    },\n\n    nextPage() {\n      viewerStore.getState().nextPage();\n    },\n\n    previousPage() {\n      viewerStore.getState().previousPage();\n    },\n\n    getCurrentPage() {\n      return viewerStore.getState().currentPage;\n    },\n\n    getTotalPages() {\n      return viewerStore.getState().numPages;\n    },\n\n    // Zoom\n    setZoom(scale: number) {\n      viewerStore.getState().setScale(scale);\n    },\n\n    zoomIn() {\n      viewerStore.getState().zoomIn();\n    },\n\n    zoomOut() {\n      viewerStore.getState().zoomOut();\n    },\n\n    fitToWidth() {\n      viewerStore.getState().fitToWidth();\n    },\n\n    fitToPage() {\n      viewerStore.getState().fitToPage();\n    },\n\n    getZoom() {\n      return viewerStore.getState().scale;\n    },\n\n    // Rotation\n    setRotation(rotation: number) {\n      viewerStore.getState().setRotation(rotation);\n    },\n\n    rotateClockwise() {\n      viewerStore.getState().rotateClockwise();\n    },\n\n    rotateCounterClockwise() {\n      viewerStore.getState().rotateCounterClockwise();\n    },\n\n    getRotation() {\n      return viewerStore.getState().rotation;\n    },\n\n    // Theme & View\n    setTheme(theme: Theme) {\n      viewerStore.getState().setTheme(theme);\n    },\n\n    getTheme() {\n      return viewerStore.getState().theme;\n    },\n\n    setViewMode(mode: ViewMode) {\n      viewerStore.getState().setViewMode(mode);\n    },\n\n    getViewMode() {\n      return viewerStore.getState().viewMode;\n    },\n\n    // Sidebar\n    toggleSidebar() {\n      viewerStore.getState().toggleSidebar();\n    },\n\n    setSidebarPanel(panel: SidebarPanel) {\n      viewerStore.getState().setSidebarPanel(panel);\n    },\n\n    isSidebarOpen() {\n      return viewerStore.getState().sidebarOpen;\n    },\n\n    // Highlights\n    getHighlights() {\n      return annotationStore.getState().highlights;\n    },\n\n    addHighlight(highlight) {\n      return annotationStore.getState().addHighlight(highlight);\n    },\n\n    removeHighlight(id: string) {\n      annotationStore.getState().removeHighlight(id);\n    },\n\n    exportHighlights() {\n      return annotationStore.getState().exportHighlights();\n    },\n\n    importHighlights(json: string) {\n      annotationStore.getState().importHighlights(json);\n    },\n\n    // Annotations\n    getAnnotations() {\n      return annotationStore.getState().annotations;\n    },\n\n    addAnnotation(annotation) {\n      return annotationStore.getState().addAnnotation(annotation);\n    },\n\n    removeAnnotation(id: string) {\n      annotationStore.getState().removeAnnotation(id);\n    },\n\n    exportAnnotations() {\n      return annotationStore.getState().exportAnnotations();\n    },\n\n    importAnnotations(json: string) {\n      annotationStore.getState().importAnnotations(json);\n    },\n\n    // Events\n    on<K extends keyof PDFViewerEventHandlers>(event: K, handler: PDFViewerEventHandlers[K]) {\n      if (!eventHandlers.has(event)) {\n        eventHandlers.set(event, new Set());\n      }\n      eventHandlers.get(event)!.add(handler as EventHandler);\n\n      // Return unsubscribe function\n      return () => {\n        eventHandlers.get(event)?.delete(handler as EventHandler);\n      };\n    },\n\n    // Lifecycle\n    destroy() {\n      if (isDestroyed) return;\n      isDestroyed = true;\n\n      // Clear event handlers\n      eventHandlers.clear();\n\n      // Unmount React\n      if (root) {\n        root.unmount();\n        root = null;\n      }\n\n      // Reset stores\n      viewerStore.getState().reset();\n      annotationStore.getState().clearAll();\n    },\n  };\n\n  return controller;\n}\n\n/**\n * Initialize a PDF viewer with minimal configuration\n */\nexport async function quickViewer(\n  container: HTMLElement | string,\n  src: string | ArrayBuffer | Uint8Array,\n  options: Partial<PDFViewerControllerOptions> = {}\n): Promise<PDFViewerController> {\n  // Resolve container\n  const element =\n    typeof container === 'string'\n      ? document.querySelector<HTMLElement>(container)\n      : container;\n\n  if (!element) {\n    throw new Error(`Container element not found: ${container}`);\n  }\n\n  // Create and load\n  const viewer = createPDFViewer(element, { ...options, src });\n  return viewer;\n}\n","import type { Highlight } from '../types';\nimport type { Bookmark, QuickNote, Takeaway } from '../types/agent-context';\n\nexport interface ExportData {\n  highlights?: Highlight[];\n  bookmarks?: Bookmark[];\n  quickNotes?: QuickNote[];\n  takeaways?: Takeaway[];\n  documentTitle?: string;\n}\n\n/**\n * Export all annotations as a comprehensive Markdown document.\n * Organizes content by page with highlights, notes, bookmarks, and takeaways.\n */\nexport function exportAnnotationsAsMarkdown(data: ExportData): string {\n  const { highlights = [], bookmarks = [], quickNotes = [], takeaways = [], documentTitle } = data;\n\n  const lines: string[] = [];\n\n  // Header\n  lines.push(`# ${documentTitle || 'PDF Study Notes'}`);\n  lines.push('');\n  lines.push(`Exported on ${new Date().toLocaleDateString()} at ${new Date().toLocaleTimeString()}`);\n  lines.push('');\n\n  // Summary statistics\n  const stats: string[] = [];\n  if (highlights.length > 0) stats.push(`${highlights.length} highlight${highlights.length !== 1 ? 's' : ''}`);\n  if (bookmarks.length > 0) stats.push(`${bookmarks.length} bookmark${bookmarks.length !== 1 ? 's' : ''}`);\n  if (quickNotes.length > 0) stats.push(`${quickNotes.length} note${quickNotes.length !== 1 ? 's' : ''}`);\n  if (takeaways.length > 0) stats.push(`${takeaways.length} takeaway${takeaways.length !== 1 ? 's' : ''}`);\n\n  if (stats.length > 0) {\n    lines.push(`**Summary:** ${stats.join(', ')}`);\n    lines.push('');\n  }\n\n  // Collect all page numbers that have content\n  const allPages = new Set<number>();\n  highlights.forEach((h) => allPages.add(h.pageNumber));\n  bookmarks.forEach((b) => allPages.add(b.pageNumber));\n  quickNotes.forEach((n) => allPages.add(n.pageNumber));\n  takeaways.forEach((t) => allPages.add(t.pageNumber));\n\n  if (allPages.size === 0) {\n    lines.push('_No annotations yet._');\n    return lines.join('\\n');\n  }\n\n  // Sort pages\n  const sortedPages = Array.from(allPages).sort((a, b) => a - b);\n\n  // Render each page\n  sortedPages.forEach((pageNumber) => {\n    lines.push(`## Page ${pageNumber}`);\n    lines.push('');\n\n    // Bookmarks for this page\n    const pageBookmarks = bookmarks.filter((b) => b.pageNumber === pageNumber);\n    if (pageBookmarks.length > 0) {\n      pageBookmarks.forEach((bookmark) => {\n        lines.push(`**Bookmark:** ${bookmark.label || 'Page ' + bookmark.pageNumber}`);\n        if (bookmark.userNote) {\n          lines.push(`> ${bookmark.userNote}`);\n        }\n        if (bookmark.agentContext) {\n          lines.push(`> *AI context: \"${bookmark.agentContext}\"*`);\n        }\n        lines.push('');\n      });\n    }\n\n    // Takeaways for this page\n    const pageTakeaways = takeaways.filter((t) => t.pageNumber === pageNumber);\n    if (pageTakeaways.length > 0) {\n      lines.push('### Key Takeaways');\n      lines.push('');\n      pageTakeaways.forEach((takeaway) => {\n        const icon = takeaway.source === 'agent' ? '🤖' : '📝';\n        lines.push(`${icon} ${takeaway.summary}`);\n        lines.push('');\n      });\n    }\n\n    // Highlights for this page\n    const pageHighlights = highlights.filter((h) => h.pageNumber === pageNumber);\n    if (pageHighlights.length > 0) {\n      lines.push('### Highlights');\n      lines.push('');\n      pageHighlights.sort((a, b) => (a.rects[0]?.y ?? 0) - (b.rects[0]?.y ?? 0));\n      pageHighlights.forEach((highlight) => {\n        const sourceIcon = highlight.source === 'agent' ? '🤖' : '';\n        const colorEmoji = {\n          yellow: '🟡',\n          green: '🟢',\n          blue: '🔵',\n          pink: '🩷',\n          orange: '🟠',\n        }[highlight.color];\n\n        lines.push(`${colorEmoji}${sourceIcon} > ${highlight.text}`);\n        if (highlight.comment) {\n          lines.push(`> **Note:** ${highlight.comment}`);\n        }\n        lines.push('');\n      });\n    }\n\n    // Quick notes for this page\n    const pageNotes = quickNotes.filter((n) => n.pageNumber === pageNumber);\n    if (pageNotes.length > 0) {\n      lines.push('### Notes');\n      lines.push('');\n      pageNotes.forEach((note) => {\n        lines.push(`📝 ${note.content}`);\n        if (note.agentLastStatement) {\n          lines.push(`> *Written while AI discussed: \"${note.agentLastStatement}\"*`);\n        }\n        lines.push('');\n      });\n    }\n\n    lines.push('---');\n    lines.push('');\n  });\n\n  // Footer\n  lines.push('');\n  lines.push('*Generated by PDF Reader with Student Learning Features*');\n\n  return lines.join('\\n');\n}\n\n/**\n * Export all annotations as JSON.\n */\nexport function exportAnnotationsAsJSON(data: ExportData): string {\n  const exportPayload = {\n    version: 1,\n    exportedAt: new Date().toISOString(),\n    documentTitle: data.documentTitle,\n    highlights: data.highlights?.map((h) => ({\n      ...h,\n      createdAt: h.createdAt.toISOString(),\n      updatedAt: h.updatedAt.toISOString(),\n    })),\n    bookmarks: data.bookmarks?.map((b) => ({\n      ...b,\n      timestamp: b.timestamp.toISOString(),\n    })),\n    quickNotes: data.quickNotes?.map((n) => ({\n      ...n,\n      timestamp: n.timestamp.toISOString(),\n    })),\n    takeaways: data.takeaways?.map((t) => ({\n      ...t,\n      timestamp: t.timestamp.toISOString(),\n    })),\n  };\n\n  return JSON.stringify(exportPayload, null, 2);\n}\n\n/**\n * Download content as a file.\n */\nexport function downloadFile(content: string, filename: string, mimeType: string): void {\n  const blob = new Blob([content], { type: mimeType });\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = filename;\n  document.body.appendChild(a);\n  a.click();\n  document.body.removeChild(a);\n  URL.revokeObjectURL(url);\n}\n\n/**\n * Export annotations as Markdown and trigger download.\n */\nexport function downloadAnnotationsAsMarkdown(data: ExportData, filename = 'study-notes.md'): void {\n  const content = exportAnnotationsAsMarkdown(data);\n  downloadFile(content, filename, 'text/markdown');\n}\n\n/**\n * Export annotations as JSON and trigger download.\n */\nexport function downloadAnnotationsAsJSON(data: ExportData, filename = 'annotations.json'): void {\n  const content = exportAnnotationsAsJSON(data);\n  downloadFile(content, filename, 'application/json');\n}\n","import type { Bookmark, QuickNote, Takeaway } from '../types/agent-context';\n\nconst STORAGE_PREFIX = 'pdf-reader-student';\n\n/**\n * Check if localStorage is available (SSR-safe).\n */\nfunction isStorageAvailable(): boolean {\n  if (typeof window === 'undefined') return false;\n  try {\n    const test = '__storage_test__';\n    localStorage.setItem(test, test);\n    localStorage.removeItem(test);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Generate a storage key for a document.\n */\nfunction getStorageKey(documentId: string, type: string): string {\n  return `${STORAGE_PREFIX}:${documentId}:${type}`;\n}\n\n// Serialization interfaces\ninterface StoredBookmark extends Omit<Bookmark, 'timestamp'> {\n  timestamp: string;\n}\n\ninterface StoredQuickNote extends Omit<QuickNote, 'timestamp'> {\n  timestamp: string;\n}\n\ninterface StoredTakeaway extends Omit<Takeaway, 'timestamp'> {\n  timestamp: string;\n}\n\nexport interface StoredStudentData {\n  bookmarks: StoredBookmark[];\n  quickNotes: StoredQuickNote[];\n  takeaways: StoredTakeaway[];\n  visitedPages: number[];\n  progress: number;\n  lastAccessed: string;\n}\n\nexport interface StudentData {\n  bookmarks: Bookmark[];\n  quickNotes: QuickNote[];\n  takeaways: Takeaway[];\n  visitedPages: Set<number>;\n  progress: number;\n  lastAccessed: Date;\n}\n\n/**\n * Save student data to localStorage.\n */\nexport function saveStudentData(documentId: string, data: StudentData): boolean {\n  if (!isStorageAvailable()) {\n    console.warn('localStorage not available, student data will not persist');\n    return false;\n  }\n\n  try {\n    const storedData: StoredStudentData = {\n      bookmarks: data.bookmarks.map((b) => ({\n        ...b,\n        timestamp: b.timestamp.toISOString(),\n      })),\n      quickNotes: data.quickNotes.map((n) => ({\n        ...n,\n        timestamp: n.timestamp.toISOString(),\n      })),\n      takeaways: data.takeaways.map((t) => ({\n        ...t,\n        timestamp: t.timestamp.toISOString(),\n      })),\n      visitedPages: Array.from(data.visitedPages),\n      progress: data.progress,\n      lastAccessed: new Date().toISOString(),\n    };\n\n    localStorage.setItem(getStorageKey(documentId, 'data'), JSON.stringify(storedData));\n    return true;\n  } catch (error) {\n    console.error('Failed to save student data:', error);\n    return false;\n  }\n}\n\n/**\n * Load student data from localStorage.\n */\nexport function loadStudentData(documentId: string): StudentData | null {\n  if (!isStorageAvailable()) {\n    return null;\n  }\n\n  try {\n    const stored = localStorage.getItem(getStorageKey(documentId, 'data'));\n    if (!stored) {\n      return null;\n    }\n\n    const data: StoredStudentData = JSON.parse(stored);\n\n    return {\n      bookmarks: data.bookmarks.map((b) => ({\n        ...b,\n        timestamp: new Date(b.timestamp),\n      })),\n      quickNotes: data.quickNotes.map((n) => ({\n        ...n,\n        timestamp: new Date(n.timestamp),\n      })),\n      takeaways: data.takeaways.map((t) => ({\n        ...t,\n        timestamp: new Date(t.timestamp),\n      })),\n      visitedPages: new Set(data.visitedPages),\n      progress: data.progress,\n      lastAccessed: new Date(data.lastAccessed),\n    };\n  } catch (error) {\n    console.error('Failed to load student data:', error);\n    return null;\n  }\n}\n\n/**\n * Clear student data for a specific document.\n */\nexport function clearStudentData(documentId: string): boolean {\n  if (!isStorageAvailable()) {\n    return false;\n  }\n\n  try {\n    localStorage.removeItem(getStorageKey(documentId, 'data'));\n    return true;\n  } catch (error) {\n    console.error('Failed to clear student data:', error);\n    return false;\n  }\n}\n\n/**\n * Get all document IDs that have stored student data.\n */\nexport function getAllStudentDataDocumentIds(): string[] {\n  if (!isStorageAvailable()) {\n    return [];\n  }\n\n  const ids: string[] = [];\n  const prefixWithColon = STORAGE_PREFIX + ':';\n\n  for (let i = 0; i < localStorage.length; i++) {\n    const key = localStorage.key(i);\n    if (key?.startsWith(prefixWithColon) && key.endsWith(':data')) {\n      const id = key.slice(prefixWithColon.length, -5); // Remove prefix and ':data' suffix\n      ids.push(id);\n    }\n  }\n\n  return ids;\n}\n\n/**\n * Get storage usage statistics.\n */\nexport function getStorageStats(): { usedBytes: number; itemCount: number } {\n  if (!isStorageAvailable()) {\n    return { usedBytes: 0, itemCount: 0 };\n  }\n\n  let usedBytes = 0;\n  let itemCount = 0;\n\n  for (let i = 0; i < localStorage.length; i++) {\n    const key = localStorage.key(i);\n    if (key?.startsWith(STORAGE_PREFIX)) {\n      const value = localStorage.getItem(key);\n      if (value) {\n        usedBytes += key.length + value.length;\n        itemCount++;\n      }\n    }\n  }\n\n  return { usedBytes, itemCount };\n}\n","import type { StoreApi } from 'zustand/vanilla';\nimport type { AgentStore } from '../store/agent-store';\nimport type { StudentStore } from '../store/student-store';\nimport type { ViewerStore } from '../store/viewer-store';\nimport type { AnnotationStore } from '../store/annotation-store';\nimport type {\n  AgentAPI,\n  AgentContext,\n  FocusedRegion,\n  Takeaway,\n  AgentHighlightParams,\n} from '../types/agent-context';\nimport type { HighlightColor } from '../types';\n\nexport interface AgentAPIStores {\n  agentStore: StoreApi<AgentStore>;\n  studentStore: StoreApi<StudentStore>;\n  viewerStore: StoreApi<ViewerStore>;\n  annotationStore: StoreApi<AnnotationStore>;\n}\n\n/**\n * Create a standalone Agent API for external AI agent integration.\n * This allows external agents to interact with the PDF viewer without\n * needing direct access to React hooks.\n *\n * @example\n * ```typescript\n * import { createAgentAPI } from 'pdfjs-reader-core';\n *\n * // Get stores from the context (this would typically be done in a React component)\n * const api = createAgentAPI(stores);\n *\n * // Now the external agent can use the API\n * api.setAgentContext({ lastStatement: \"The mitochondria is the powerhouse of the cell\" });\n * api.focusRegion({ pageNumber: 1, x: 100, y: 200, width: 300, height: 50, style: 'pulse' });\n * api.addTakeaway(1, \"Key concept: Cell energy production\");\n * ```\n */\nexport function createAgentAPI(stores: AgentAPIStores): AgentAPI {\n  const { agentStore, studentStore, viewerStore, annotationStore } = stores;\n\n  let focusRegionIdCounter = 0;\n\n  const generateFocusRegionId = (): string => {\n    return `api-focus-${++focusRegionIdCounter}-${Date.now()}`;\n  };\n\n  const api: AgentAPI = {\n    focusRegion: (region: Omit<FocusedRegion, 'id'>) => {\n      const id = generateFocusRegionId();\n      const focusedRegion: FocusedRegion = {\n        ...region,\n        id,\n        style: region.style ?? 'pulse',\n      };\n\n      const state = agentStore.getState();\n      agentStore.setState({\n        focusedRegions: [...state.focusedRegions, focusedRegion],\n      });\n\n      // Set up auto-clear if timeout is specified\n      if (region.autoClearTimeout && region.autoClearTimeout > 0) {\n        setTimeout(() => {\n          api.clearFocusedRegion(id);\n        }, region.autoClearTimeout);\n      }\n\n      return id;\n    },\n\n    clearFocusedRegion: (id?: string) => {\n      if (id) {\n        const state = agentStore.getState();\n        agentStore.setState({\n          focusedRegions: state.focusedRegions.filter((r) => r.id !== id),\n        });\n      } else {\n        agentStore.setState({ focusedRegions: [] });\n      }\n    },\n\n    addTakeaway: (pageNumber: number, summary: string, metadata?: Record<string, unknown>) => {\n      const takeaway: Takeaway = {\n        id: `takeaway-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n        pageNumber,\n        summary,\n        timestamp: new Date(),\n        source: 'agent',\n        metadata,\n      };\n\n      const state = studentStore.getState();\n      studentStore.setState({\n        takeaways: [...state.takeaways, takeaway],\n      });\n\n      return takeaway;\n    },\n\n    setAgentContext: (context: Partial<AgentContext>) => {\n      const currentContext = agentStore.getState().currentContext;\n      agentStore.setState({\n        currentContext: {\n          ...currentContext,\n          ...context,\n          timestamp: context.timestamp ?? new Date(),\n        } as AgentContext,\n      });\n    },\n\n    addAgentHighlight: (params: AgentHighlightParams) => {\n      const highlightId = `agent-hl-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n      const now = new Date();\n\n      const state = annotationStore.getState();\n      annotationStore.setState({\n        highlights: [\n          ...state.highlights,\n          {\n            id: highlightId,\n            pageNumber: params.pageNumber,\n            rects: params.rects,\n            text: params.text,\n            color: params.color ?? ('blue' as HighlightColor),\n            comment: params.comment,\n            createdAt: now,\n            updatedAt: now,\n            source: 'agent',\n          },\n        ],\n      });\n\n      return highlightId;\n    },\n\n    goToPage: (pageNumber: number) => {\n      viewerStore.getState().goToPage(pageNumber);\n    },\n\n    getCurrentPage: () => {\n      return viewerStore.getState().currentPage;\n    },\n\n    getAgentContext: () => {\n      return agentStore.getState().currentContext;\n    },\n  };\n\n  return api;\n}\n\n/**\n * Convenience type for the return value of createAgentAPI\n */\nexport type AgentAPIInstance = ReturnType<typeof createAgentAPI>;\n","import type { PDFDocumentProxy } from 'pdfjs-dist';\nimport type { HighlightRect } from '../types';\n\n// ============================================================================\n// Text Search Utility Types\n// ============================================================================\n\nexport interface TextMatch {\n  /** The matched text */\n  text: string;\n  /** Position rects on the page */\n  rects: HighlightRect[];\n  /** Page number where the match was found */\n  pageNumber: number;\n  /** Character index where the match starts in the page text */\n  startIndex: number;\n}\n\nexport interface FindTextOptions {\n  /** Case sensitive search (default: false) */\n  caseSensitive?: boolean;\n  /** Match whole words only (default: false) */\n  wholeWord?: boolean;\n}\n\nexport interface CharPosition {\n  char: string;\n  rect: HighlightRect;\n}\n\n/** Internal text item representation */\ninterface TextItem {\n  text: string;\n  transform: number[];\n  width: number;\n  height: number;\n}\n\n// ============================================================================\n// Text Search Functions\n// ============================================================================\n\n/**\n * Extract text content with text items from a PDF page.\n * Uses proper text item tracking for accurate positioning.\n */\nexport async function extractPageText(\n  document: PDFDocumentProxy,\n  pageNumber: number\n): Promise<{ fullText: string; textItems: TextItem[]; viewport: { width: number; height: number } }> {\n  const page = await document.getPage(pageNumber);\n  const textContent = await page.getTextContent();\n  const viewport = page.getViewport({ scale: 1 });\n\n  let fullText = '';\n  const textItems: TextItem[] = [];\n\n  for (const item of textContent.items) {\n    if ('str' in item && item.str) {\n      textItems.push({\n        text: item.str,\n        transform: item.transform as number[],\n        width: (item.width as number) ?? 0,\n        height: (item.height as number) ?? 12,\n      });\n      fullText += item.str;\n    }\n  }\n\n  return { fullText, textItems, viewport };\n}\n\n/**\n * Calculate the bounding rectangles for a text match by tracking text item offsets.\n */\nfunction calculateMatchRects(\n  textItems: TextItem[],\n  startOffset: number,\n  length: number,\n  viewport: { width: number; height: number }\n): HighlightRect[] {\n  const rects: HighlightRect[] = [];\n  let currentOffset = 0;\n\n  for (const item of textItems) {\n    const itemStart = currentOffset;\n    const itemEnd = currentOffset + item.text.length;\n\n    // Check if this item overlaps with our match\n    if (itemEnd > startOffset && itemStart < startOffset + length) {\n      const [, , c, d, tx, ty] = item.transform;\n\n      // Convert PDF coordinates to viewport coordinates\n      const x = tx;\n      const y = viewport.height - ty;\n\n      // Approximate height from transform matrix\n      const height = Math.sqrt(c * c + d * d);\n\n      // Calculate the portion of this item that's part of the match\n      const matchStartInItem = Math.max(0, startOffset - itemStart);\n      const matchEndInItem = Math.min(item.text.length, startOffset + length - itemStart);\n      const charWidth = item.text.length > 0 ? item.width / item.text.length : item.width;\n      const matchWidth = charWidth * (matchEndInItem - matchStartInItem);\n      const matchX = x + charWidth * matchStartInItem;\n\n      // Adjust Y position: ty is the baseline, we need to position highlight\n      // lower to align with the actual text glyphs (not the baseline)\n      const yOffset = height * 0.30; // Shift down by 30% of height\n\n      rects.push({\n        x: matchX,\n        y: y - height + yOffset,\n        width: matchWidth,\n        height: height,\n      });\n    }\n\n    currentOffset = itemEnd;\n  }\n\n  return rects;\n}\n\n/**\n * Find all occurrences of text on a specific page.\n */\nexport async function findTextOnPage(\n  document: PDFDocumentProxy,\n  pageNumber: number,\n  query: string,\n  options: FindTextOptions = {}\n): Promise<TextMatch[]> {\n  const { caseSensitive = false, wholeWord = false } = options;\n\n  if (!query || pageNumber < 1 || pageNumber > document.numPages) {\n    return [];\n  }\n\n  const { fullText, textItems, viewport } = await extractPageText(document, pageNumber);\n  const matches: TextMatch[] = [];\n\n  const searchText = caseSensitive ? query : query.toLowerCase();\n  const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();\n\n  let startIndex = 0;\n\n  while (true) {\n    const matchIndex = textToSearch.indexOf(searchText, startIndex);\n    if (matchIndex === -1) break;\n\n    // Check whole word if required\n    if (wholeWord) {\n      const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : ' ';\n      const afterChar = matchIndex + query.length < textToSearch.length\n        ? textToSearch[matchIndex + query.length]\n        : ' ';\n\n      if (/\\w/.test(beforeChar) || /\\w/.test(afterChar)) {\n        startIndex = matchIndex + 1;\n        continue;\n      }\n    }\n\n    // Calculate rects by finding which text items contain the match\n    const matchRects = calculateMatchRects(textItems, matchIndex, query.length, viewport);\n\n    if (matchRects.length > 0) {\n      matches.push({\n        text: fullText.substring(matchIndex, matchIndex + query.length),\n        rects: matchRects,\n        pageNumber,\n        startIndex: matchIndex,\n      });\n    }\n\n    startIndex = matchIndex + 1;\n  }\n\n  return matches;\n}\n\n/**\n * Find all occurrences of text across multiple pages.\n */\nexport async function findTextInDocument(\n  document: PDFDocumentProxy,\n  query: string,\n  options: FindTextOptions & { pageRange?: number[] } = {}\n): Promise<TextMatch[]> {\n  const { pageRange, ...findOptions } = options;\n\n  const pagesToSearch = pageRange ?? Array.from({ length: document.numPages }, (_, i) => i + 1);\n  const allMatches: TextMatch[] = [];\n\n  for (const pageNum of pagesToSearch) {\n    if (pageNum < 1 || pageNum > document.numPages) continue;\n\n    try {\n      const matches = await findTextOnPage(document, pageNum, query, findOptions);\n      allMatches.push(...matches);\n    } catch {\n      // Skip pages that fail to load\n    }\n  }\n\n  return allMatches;\n}\n\n/**\n * Merge adjacent rects into larger rects.\n */\nexport function mergeAdjacentRects(rects: HighlightRect[]): HighlightRect[] {\n  if (rects.length === 0) return [];\n\n  const sorted = [...rects].sort((a, b) => a.y - b.y || a.x - b.x);\n  const merged: HighlightRect[] = [];\n  let current = { ...sorted[0] };\n\n  for (let i = 1; i < sorted.length; i++) {\n    const rect = sorted[i];\n    // If same line (similar y) and adjacent x\n    if (Math.abs(rect.y - current.y) < 2 && rect.x <= current.x + current.width + 2) {\n      // Extend current\n      const newRight = Math.max(current.x + current.width, rect.x + rect.width);\n      current.width = newRight - current.x;\n      current.height = Math.max(current.height, rect.height);\n    } else {\n      merged.push(current);\n      current = { ...rect };\n    }\n  }\n  merged.push(current);\n\n  return merged;\n}\n\n/**\n * Get the full text content of a page as a string.\n */\nexport async function getPageText(\n  document: PDFDocumentProxy,\n  pageNumber: number\n): Promise<string> {\n  if (pageNumber < 1 || pageNumber > document.numPages) {\n    return '';\n  }\n\n  const page = await document.getPage(pageNumber);\n  const textContent = await page.getTextContent();\n\n  return textContent.items\n    .filter((item): item is (typeof textContent.items[number] & { str: string }) => 'str' in item)\n    .map(item => item.str)\n    .join('');\n}\n\n/**\n * Count occurrences of text on a page without extracting positions.\n */\nexport async function countTextOnPage(\n  document: PDFDocumentProxy,\n  pageNumber: number,\n  query: string,\n  options: FindTextOptions = {}\n): Promise<number> {\n  const { caseSensitive = false, wholeWord = false } = options;\n\n  if (!query || pageNumber < 1 || pageNumber > document.numPages) {\n    return 0;\n  }\n\n  const text = await getPageText(document, pageNumber);\n  const searchText = caseSensitive ? query : query.toLowerCase();\n  const textToSearch = caseSensitive ? text : text.toLowerCase();\n\n  let count = 0;\n  let startIndex = 0;\n\n  while (true) {\n    const matchIndex = textToSearch.indexOf(searchText, startIndex);\n    if (matchIndex === -1) break;\n\n    if (wholeWord) {\n      const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : ' ';\n      const afterChar = matchIndex + query.length < textToSearch.length\n        ? textToSearch[matchIndex + query.length]\n        : ' ';\n\n      if (/\\w/.test(beforeChar) || /\\w/.test(afterChar)) {\n        startIndex = matchIndex + 1;\n        continue;\n      }\n    }\n\n    count++;\n    startIndex = matchIndex + 1;\n  }\n\n  return count;\n}\n","// ============================================================================\n// Coordinate Conversion Utilities\n// ============================================================================\n\n/**\n * Convert PDF coordinates to viewport (screen) coordinates.\n * PDF coordinates have origin at bottom-left, viewport at top-left.\n *\n * @param x - X coordinate in PDF space\n * @param y - Y coordinate in PDF space\n * @param scale - Current zoom scale\n * @param pageHeight - Height of the page in PDF units\n * @returns Viewport coordinates { x, y }\n */\nexport function pdfToViewport(\n  x: number,\n  y: number,\n  scale: number,\n  pageHeight: number\n): { x: number; y: number } {\n  return {\n    x: x * scale,\n    y: (pageHeight - y) * scale,\n  };\n}\n\n/**\n * Convert viewport (screen) coordinates to PDF coordinates.\n * Viewport coordinates have origin at top-left, PDF at bottom-left.\n *\n * @param x - X coordinate in viewport space\n * @param y - Y coordinate in viewport space\n * @param scale - Current zoom scale\n * @param pageHeight - Height of the page in PDF units\n * @returns PDF coordinates { x, y }\n */\nexport function viewportToPDF(\n  x: number,\n  y: number,\n  scale: number,\n  pageHeight: number\n): { x: number; y: number } {\n  return {\n    x: x / scale,\n    y: pageHeight - y / scale,\n  };\n}\n\n/**\n * Convert percentage-based coordinates to PDF coordinates.\n * Useful for positioning elements based on relative position.\n *\n * @param xPercent - X coordinate as percentage (0-100)\n * @param yPercent - Y coordinate as percentage (0-100)\n * @param pageWidth - Width of the page in PDF units\n * @param pageHeight - Height of the page in PDF units\n * @returns PDF coordinates { x, y }\n */\nexport function percentToPDF(\n  xPercent: number,\n  yPercent: number,\n  pageWidth: number,\n  pageHeight: number\n): { x: number; y: number } {\n  return {\n    x: (xPercent / 100) * pageWidth,\n    y: (yPercent / 100) * pageHeight,\n  };\n}\n\n/**\n * Convert PDF coordinates to percentage-based coordinates.\n *\n * @param x - X coordinate in PDF space\n * @param y - Y coordinate in PDF space\n * @param pageWidth - Width of the page in PDF units\n * @param pageHeight - Height of the page in PDF units\n * @returns Percentage coordinates { x, y } (0-100)\n */\nexport function pdfToPercent(\n  x: number,\n  y: number,\n  pageWidth: number,\n  pageHeight: number\n): { x: number; y: number } {\n  return {\n    x: (x / pageWidth) * 100,\n    y: (y / pageHeight) * 100,\n  };\n}\n\n/**\n * Convert percentage coordinates to viewport (screen) pixels.\n *\n * @param xPercent - X coordinate as percentage (0-100)\n * @param yPercent - Y coordinate as percentage (0-100)\n * @param pageWidth - Width of the page in PDF units\n * @param pageHeight - Height of the page in PDF units\n * @param scale - Current zoom scale\n * @returns Viewport coordinates { x, y }\n */\nexport function percentToViewport(\n  xPercent: number,\n  yPercent: number,\n  pageWidth: number,\n  pageHeight: number,\n  scale: number\n): { x: number; y: number } {\n  return {\n    x: (xPercent / 100) * pageWidth * scale,\n    y: (yPercent / 100) * pageHeight * scale,\n  };\n}\n\n/**\n * Convert viewport (screen) pixels to percentage coordinates.\n *\n * @param x - X coordinate in viewport space\n * @param y - Y coordinate in viewport space\n * @param pageWidth - Width of the page in PDF units\n * @param pageHeight - Height of the page in PDF units\n * @param scale - Current zoom scale\n * @returns Percentage coordinates { x, y } (0-100)\n */\nexport function viewportToPercent(\n  x: number,\n  y: number,\n  pageWidth: number,\n  pageHeight: number,\n  scale: number\n): { x: number; y: number } {\n  return {\n    x: (x / (pageWidth * scale)) * 100,\n    y: (y / (pageHeight * scale)) * 100,\n  };\n}\n\n/**\n * Apply rotation to coordinates.\n * Rotates point around the center of the page.\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param rotation - Rotation in degrees (0, 90, 180, 270)\n * @param pageWidth - Width of the page\n * @param pageHeight - Height of the page\n * @returns Rotated coordinates { x, y }\n */\nexport function applyRotation(\n  x: number,\n  y: number,\n  rotation: number,\n  pageWidth: number,\n  pageHeight: number\n): { x: number; y: number } {\n  const normalizedRotation = ((rotation % 360) + 360) % 360;\n\n  switch (normalizedRotation) {\n    case 90:\n      return { x: y, y: pageWidth - x };\n    case 180:\n      return { x: pageWidth - x, y: pageHeight - y };\n    case 270:\n      return { x: pageHeight - y, y: x };\n    default:\n      return { x, y };\n  }\n}\n\n/**\n * Remove rotation from coordinates.\n * Inverse of applyRotation.\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param rotation - Rotation in degrees (0, 90, 180, 270)\n * @param pageWidth - Width of the page (original, before rotation)\n * @param pageHeight - Height of the page (original, before rotation)\n * @returns Unrotated coordinates { x, y }\n */\nexport function removeRotation(\n  x: number,\n  y: number,\n  rotation: number,\n  pageWidth: number,\n  pageHeight: number\n): { x: number; y: number } {\n  const normalizedRotation = ((rotation % 360) + 360) % 360;\n\n  // Apply inverse rotation\n  switch (normalizedRotation) {\n    case 90:\n      return { x: pageWidth - y, y: x };\n    case 180:\n      return { x: pageWidth - x, y: pageHeight - y };\n    case 270:\n      return { x: y, y: pageHeight - x };\n    default:\n      return { x, y };\n  }\n}\n\n/**\n * Calculate the bounding box dimensions after rotation.\n *\n * @param width - Original width\n * @param height - Original height\n * @param rotation - Rotation in degrees\n * @returns Rotated dimensions { width, height }\n */\nexport function getRotatedDimensions(\n  width: number,\n  height: number,\n  rotation: number\n): { width: number; height: number } {\n  const normalizedRotation = ((rotation % 360) + 360) % 360;\n\n  if (normalizedRotation === 90 || normalizedRotation === 270) {\n    return { width: height, height: width };\n  }\n\n  return { width, height };\n}\n\n/**\n * Convert a rectangle from one coordinate space to another.\n *\n * @param rect - Rectangle with x, y, width, height\n * @param fromScale - Source scale\n * @param toScale - Target scale\n * @returns Scaled rectangle\n */\nexport function scaleRect(\n  rect: { x: number; y: number; width: number; height: number },\n  fromScale: number,\n  toScale: number\n): { x: number; y: number; width: number; height: number } {\n  const ratio = toScale / fromScale;\n  return {\n    x: rect.x * ratio,\n    y: rect.y * ratio,\n    width: rect.width * ratio,\n    height: rect.height * ratio,\n  };\n}\n\n/**\n * Check if a point is inside a rectangle.\n *\n * @param point - Point coordinates { x, y }\n * @param rect - Rectangle { x, y, width, height }\n * @returns True if point is inside rectangle\n */\nexport function isPointInRect(\n  point: { x: number; y: number },\n  rect: { x: number; y: number; width: number; height: number }\n): boolean {\n  return (\n    point.x >= rect.x &&\n    point.x <= rect.x + rect.width &&\n    point.y >= rect.y &&\n    point.y <= rect.y + rect.height\n  );\n}\n\n/**\n * Check if two rectangles intersect.\n *\n * @param rectA - First rectangle\n * @param rectB - Second rectangle\n * @returns True if rectangles intersect\n */\nexport function doRectsIntersect(\n  rectA: { x: number; y: number; width: number; height: number },\n  rectB: { x: number; y: number; width: number; height: number }\n): boolean {\n  return !(\n    rectA.x + rectA.width < rectB.x ||\n    rectB.x + rectB.width < rectA.x ||\n    rectA.y + rectA.height < rectB.y ||\n    rectB.y + rectB.height < rectA.y\n  );\n}\n\n/**\n * Get the intersection of two rectangles.\n *\n * @param rectA - First rectangle\n * @param rectB - Second rectangle\n * @returns Intersection rectangle or null if no intersection\n */\nexport function getRectIntersection(\n  rectA: { x: number; y: number; width: number; height: number },\n  rectB: { x: number; y: number; width: number; height: number }\n): { x: number; y: number; width: number; height: number } | null {\n  const x = Math.max(rectA.x, rectB.x);\n  const y = Math.max(rectA.y, rectB.y);\n  const right = Math.min(rectA.x + rectA.width, rectB.x + rectB.width);\n  const bottom = Math.min(rectA.y + rectA.height, rectB.y + rectB.height);\n\n  if (right <= x || bottom <= y) {\n    return null;\n  }\n\n  return {\n    x,\n    y,\n    width: right - x,\n    height: bottom - y,\n  };\n}\n","/**\n * Page turn sound effect using Web Audio API.\n * Synthesizes a realistic paper-turning sound without requiring external audio files.\n */\n\nlet audioContext: AudioContext | null = null;\n\nfunction getAudioContext(): AudioContext | null {\n  if (typeof window === 'undefined') return null;\n  if (!audioContext) {\n    try {\n      audioContext = new (window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext)();\n    } catch {\n      return null;\n    }\n  }\n  return audioContext;\n}\n\n/**\n * Play a synthesized page-turn sound effect.\n * Uses filtered noise to simulate the sound of a paper page turning.\n */\nexport function playPageTurnSound(volume = 0.3): void {\n  const ctx = getAudioContext();\n  if (!ctx) return;\n\n  // Resume context if suspended (browser autoplay policy)\n  if (ctx.state === 'suspended') {\n    ctx.resume();\n  }\n\n  const now = ctx.currentTime;\n  const duration = 0.35;\n\n  // Create noise buffer for the paper rustle\n  const bufferSize = Math.floor(ctx.sampleRate * duration);\n  const noiseBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);\n  const data = noiseBuffer.getChannelData(0);\n\n  for (let i = 0; i < bufferSize; i++) {\n    data[i] = (Math.random() * 2 - 1);\n  }\n\n  // Noise source\n  const noiseSource = ctx.createBufferSource();\n  noiseSource.buffer = noiseBuffer;\n\n  // Bandpass filter to shape noise into paper-like sound\n  const bandpass = ctx.createBiquadFilter();\n  bandpass.type = 'bandpass';\n  bandpass.frequency.setValueAtTime(3000, now);\n  bandpass.frequency.exponentialRampToValueAtTime(800, now + duration * 0.6);\n  bandpass.Q.setValueAtTime(0.8, now);\n\n  // Highpass to remove low rumble\n  const highpass = ctx.createBiquadFilter();\n  highpass.type = 'highpass';\n  highpass.frequency.setValueAtTime(400, now);\n  highpass.frequency.linearRampToValueAtTime(200, now + duration);\n\n  // Envelope for the rustle\n  const envelope = ctx.createGain();\n  envelope.gain.setValueAtTime(0, now);\n  envelope.gain.linearRampToValueAtTime(volume * 0.6, now + 0.02);\n  envelope.gain.setValueAtTime(volume * 0.6, now + 0.05);\n  envelope.gain.linearRampToValueAtTime(volume, now + duration * 0.3);\n  envelope.gain.exponentialRampToValueAtTime(0.001, now + duration);\n\n  // Second noise burst for the \"snap\" at the end of the turn\n  const snapBuffer = ctx.createBuffer(1, Math.floor(ctx.sampleRate * 0.08), ctx.sampleRate);\n  const snapData = snapBuffer.getChannelData(0);\n  for (let i = 0; i < snapData.length; i++) {\n    snapData[i] = (Math.random() * 2 - 1);\n  }\n\n  const snapSource = ctx.createBufferSource();\n  snapSource.buffer = snapBuffer;\n\n  const snapFilter = ctx.createBiquadFilter();\n  snapFilter.type = 'bandpass';\n  snapFilter.frequency.setValueAtTime(2000, now);\n  snapFilter.Q.setValueAtTime(1.5, now);\n\n  const snapEnvelope = ctx.createGain();\n  snapEnvelope.gain.setValueAtTime(0, now);\n  snapEnvelope.gain.setValueAtTime(0, now + duration * 0.7);\n  snapEnvelope.gain.linearRampToValueAtTime(volume * 0.8, now + duration * 0.75);\n  snapEnvelope.gain.exponentialRampToValueAtTime(0.001, now + duration);\n\n  // Connect noise chain\n  noiseSource.connect(bandpass);\n  bandpass.connect(highpass);\n  highpass.connect(envelope);\n  envelope.connect(ctx.destination);\n\n  // Connect snap chain\n  snapSource.connect(snapFilter);\n  snapFilter.connect(snapEnvelope);\n  snapEnvelope.connect(ctx.destination);\n\n  // Play\n  noiseSource.start(now);\n  noiseSource.stop(now + duration);\n  snapSource.start(now);\n  snapSource.stop(now + duration);\n}\n","/**\n * Mobile-specific configuration and optimizations for PDF rendering.\n * Provides adaptive settings based on device capabilities.\n */\n\n// ============================================================================\n// Device Detection\n// ============================================================================\n\nexport interface DeviceCapabilities {\n  /** Whether the device is a mobile/tablet */\n  isMobile: boolean;\n  /** Whether the device supports touch */\n  isTouch: boolean;\n  /** Device pixel ratio */\n  devicePixelRatio: number;\n  /** Estimated device memory in GB (if available) */\n  deviceMemory: number | null;\n  /** Number of logical CPU cores */\n  hardwareConcurrency: number;\n  /** Whether the device is considered low-end */\n  isLowEnd: boolean;\n  /** Connection type if available */\n  connectionType: 'slow' | 'fast' | 'unknown';\n  /** Screen size category */\n  screenSize: 'small' | 'medium' | 'large';\n}\n\n/**\n * Detect device capabilities for adaptive rendering.\n */\nexport function detectDeviceCapabilities(): DeviceCapabilities {\n  if (typeof window === 'undefined') {\n    // SSR fallback - assume desktop\n    return {\n      isMobile: false,\n      isTouch: false,\n      devicePixelRatio: 1,\n      deviceMemory: null,\n      hardwareConcurrency: 4,\n      isLowEnd: false,\n      connectionType: 'unknown',\n      screenSize: 'large',\n    };\n  }\n\n  const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n    navigator.userAgent\n  ) || window.matchMedia('(max-width: 768px)').matches;\n\n  const isTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n\n  const devicePixelRatio = window.devicePixelRatio || 1;\n\n  // Device memory API (Chrome only)\n  const deviceMemory = (navigator as Navigator & { deviceMemory?: number }).deviceMemory ?? null;\n\n  const hardwareConcurrency = navigator.hardwareConcurrency || 2;\n\n  // Screen size detection\n  const screenWidth = window.screen.width;\n  const screenSize: 'small' | 'medium' | 'large' =\n    screenWidth < 640 ? 'small' : screenWidth < 1024 ? 'medium' : 'large';\n\n  // Connection type detection\n  const connection = (navigator as Navigator & { connection?: { effectiveType?: string } }).connection;\n  let connectionType: 'slow' | 'fast' | 'unknown' = 'unknown';\n  if (connection?.effectiveType) {\n    connectionType = ['slow-2g', '2g', '3g'].includes(connection.effectiveType) ? 'slow' : 'fast';\n  }\n\n  // Determine if low-end device\n  const isLowEnd =\n    (deviceMemory !== null && deviceMemory < 4) ||\n    hardwareConcurrency <= 2 ||\n    (isMobile && devicePixelRatio > 2 && screenSize === 'small');\n\n  return {\n    isMobile,\n    isTouch,\n    devicePixelRatio,\n    deviceMemory,\n    hardwareConcurrency,\n    isLowEnd,\n    connectionType,\n    screenSize,\n  };\n}\n\n/**\n * Detect iOS mobile (iPhone/iPad/iPod), including modern iPadOS that reports\n * as Mac in its user-agent string.\n *\n * Used as the default trigger for extra-conservative TutorMode behaviours\n * (e.g. single-active-overlay mode in StoryboardEngine), because iOS Safari's\n * WebKit GPU compositor is the device family with the hardest crash ceiling\n * — per-canvas 16.78 MP cap, unforgiving stacking-context rules around\n * `will-change`, and a shared memory envelope with the OS.\n *\n * NOTE: returns `false` under SSR. Safe to call from module top-level but\n * prefer calling lazily (e.g. in a class constructor) so it runs once on\n * the client after hydration.\n */\nexport function isIOSMobile(): boolean {\n  if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n    return false;\n  }\n  const ua = navigator.userAgent || '';\n  // iPhone / iPad / iPod (UA-honest case)\n  if (/iPhone|iPad|iPod/i.test(ua)) return true;\n  // iPadOS 13+ lies: UA says \"Macintosh\" but maxTouchPoints > 1 on touch iPads.\n  // Exclude real Macs (no touch, or maxTouchPoints === 0).\n  const isAppleTouch =\n    /Mac/i.test(ua) &&\n    typeof navigator.maxTouchPoints === 'number' &&\n    navigator.maxTouchPoints > 1;\n  return isAppleTouch;\n}\n\n// ============================================================================\n// Render Quality Settings\n// ============================================================================\n\nexport type RenderQuality = 'low' | 'medium' | 'high' | 'auto';\n\nexport interface RenderConfig {\n  /** Canvas scale factor (relative to device pixel ratio) */\n  canvasScaleFactor: number;\n  /** Maximum canvas dimension in pixels */\n  maxCanvasDimension: number;\n  /** Number of pages to preload around current page */\n  overscanPages: number;\n  /** Maximum pages to keep in memory */\n  maxPagesInMemory: number;\n  /** Debounce delay for scroll events (ms) */\n  scrollDebounceMs: number;\n  /** Whether to use low-resolution preview during scroll */\n  useLowResPreview: boolean;\n  /** Delay before rendering full resolution after scroll stops (ms) */\n  fullResDelayMs: number;\n  /** Whether to disable text layer on mobile for performance */\n  disableTextLayerOnScroll: boolean;\n  /** Render priority for current page vs adjacent pages */\n  currentPagePriority: number;\n  /** Whether to use requestIdleCallback for non-critical rendering */\n  useIdleCallback: boolean;\n  /** Maximum concurrent render operations */\n  maxConcurrentRenders: number;\n}\n\n/**\n * Get render configuration based on quality setting and device capabilities.\n */\nexport function getRenderConfig(\n  quality: RenderQuality = 'auto',\n  capabilities?: DeviceCapabilities\n): RenderConfig {\n  const caps = capabilities ?? detectDeviceCapabilities();\n\n  // Auto quality selection based on device\n  if (quality === 'auto') {\n    if (caps.isLowEnd) {\n      quality = 'low';\n    } else if (caps.isMobile) {\n      quality = 'medium';\n    } else {\n      quality = 'high';\n    }\n  }\n\n  // Render at FULL device pixel ratio so canvas pixels match physical pixels.\n  // Anything less and CSS upscales the backing store, which is the Safari\n  // \"blurry PDF\" complaint. Memory safety is enforced via `maxCanvasDimension`\n  // (and `calculateOptimalCanvasDimensions`), which only kicks in when a page\n  // would actually exceed iOS Safari's per-canvas pixel budget — typically\n  // only at deep zoom, not at default scale.\n  switch (quality) {\n    case 'low':\n      return {\n        canvasScaleFactor: caps.devicePixelRatio,\n        // 3072² ≈ 9 MP — fits a full-DPR US Letter (DPR=3 → 1836×2376) at\n        // default scale and caps at deep zoom on memory-constrained iPhones.\n        maxCanvasDimension: 3072,\n        overscanPages: 1,\n        maxPagesInMemory: 3,\n        scrollDebounceMs: 100,\n        useLowResPreview: true,\n        fullResDelayMs: 300,\n        disableTextLayerOnScroll: true,\n        currentPagePriority: 10,\n        useIdleCallback: true,\n        maxConcurrentRenders: 1,\n      };\n\n    case 'medium':\n      return {\n        canvasScaleFactor: caps.devicePixelRatio,\n        // 4096² ≈ 16 MP — within iOS Safari per-canvas budget across versions.\n        maxCanvasDimension: 4096,\n        overscanPages: 2,\n        maxPagesInMemory: 5,\n        scrollDebounceMs: 50,\n        useLowResPreview: true,\n        fullResDelayMs: 150,\n        disableTextLayerOnScroll: true,\n        currentPagePriority: 5,\n        useIdleCallback: true,\n        maxConcurrentRenders: 2,\n      };\n\n    case 'high':\n    default:\n      return {\n        canvasScaleFactor: caps.devicePixelRatio,\n        maxCanvasDimension: 8192,\n        overscanPages: 3,\n        maxPagesInMemory: 10,\n        scrollDebounceMs: 16,\n        useLowResPreview: false,\n        fullResDelayMs: 0,\n        disableTextLayerOnScroll: false,\n        currentPagePriority: 1,\n        useIdleCallback: false,\n        maxConcurrentRenders: 4,\n      };\n  }\n}\n\n// ============================================================================\n// Memory Management\n// ============================================================================\n\nexport interface MemoryStatus {\n  /** Whether memory pressure is detected */\n  isUnderPressure: boolean;\n  /** Used JS heap size in MB (if available) */\n  usedHeapMB: number | null;\n  /** Total JS heap size in MB (if available) */\n  totalHeapMB: number | null;\n  /** Heap usage percentage (if available) */\n  heapUsagePercent: number | null;\n}\n\n/**\n * Check current memory status (Chrome only).\n */\nexport function getMemoryStatus(): MemoryStatus {\n  if (typeof window === 'undefined') {\n    return {\n      isUnderPressure: false,\n      usedHeapMB: null,\n      totalHeapMB: null,\n      heapUsagePercent: null,\n    };\n  }\n\n  const memory = (performance as Performance & {\n    memory?: {\n      usedJSHeapSize: number;\n      totalJSHeapSize: number;\n      jsHeapSizeLimit: number;\n    };\n  }).memory;\n\n  if (!memory) {\n    return {\n      isUnderPressure: false,\n      usedHeapMB: null,\n      totalHeapMB: null,\n      heapUsagePercent: null,\n    };\n  }\n\n  const usedHeapMB = memory.usedJSHeapSize / (1024 * 1024);\n  const totalHeapMB = memory.totalJSHeapSize / (1024 * 1024);\n  const heapUsagePercent = (memory.usedJSHeapSize / memory.jsHeapSizeLimit) * 100;\n\n  // Consider under pressure if using more than 70% of heap limit\n  const isUnderPressure = heapUsagePercent > 70;\n\n  return {\n    isUnderPressure,\n    usedHeapMB,\n    totalHeapMB,\n    heapUsagePercent,\n  };\n}\n\n// ============================================================================\n// Render Queue\n// ============================================================================\n\ninterface RenderTask {\n  id: string;\n  pageNumber: number;\n  priority: number;\n  execute: () => Promise<void>;\n  cancel?: () => void;\n}\n\n/**\n * Manages render tasks with priority and concurrency limits.\n * Prevents overwhelming mobile devices with too many concurrent renders.\n */\nexport class RenderQueue {\n  private queue: RenderTask[] = [];\n  private activeCount = 0;\n  private maxConcurrent: number;\n  private isProcessing = false;\n  private cancelledIds = new Set<string>();\n\n  constructor(maxConcurrent: number = 2) {\n    this.maxConcurrent = maxConcurrent;\n  }\n\n  /**\n   * Add a render task to the queue.\n   */\n  enqueue(task: RenderTask): void {\n    // Remove any existing task for the same page\n    this.queue = this.queue.filter((t) => t.pageNumber !== task.pageNumber);\n    this.cancelledIds.delete(task.id);\n\n    // Insert by priority (lower = higher priority)\n    const insertIndex = this.queue.findIndex((t) => t.priority > task.priority);\n    if (insertIndex === -1) {\n      this.queue.push(task);\n    } else {\n      this.queue.splice(insertIndex, 0, task);\n    }\n\n    this.processQueue();\n  }\n\n  /**\n   * Cancel a pending render task.\n   */\n  cancel(id: string): void {\n    this.cancelledIds.add(id);\n    const task = this.queue.find((t) => t.id === id);\n    if (task?.cancel) {\n      task.cancel();\n    }\n    this.queue = this.queue.filter((t) => t.id !== id);\n  }\n\n  /**\n   * Cancel all pending tasks for pages not in the visible set.\n   */\n  cancelExcept(visiblePageNumbers: number[]): void {\n    const visibleSet = new Set(visiblePageNumbers);\n    const toCancel = this.queue.filter((t) => !visibleSet.has(t.pageNumber));\n    for (const task of toCancel) {\n      this.cancel(task.id);\n    }\n  }\n\n  /**\n   * Clear all pending tasks.\n   */\n  clear(): void {\n    for (const task of this.queue) {\n      if (task.cancel) {\n        task.cancel();\n      }\n      this.cancelledIds.add(task.id);\n    }\n    this.queue = [];\n  }\n\n  /**\n   * Update max concurrent renders (useful for adapting to memory pressure).\n   */\n  setMaxConcurrent(max: number): void {\n    this.maxConcurrent = max;\n  }\n\n  private async processQueue(): Promise<void> {\n    if (this.isProcessing) return;\n    this.isProcessing = true;\n\n    while (this.queue.length > 0 && this.activeCount < this.maxConcurrent) {\n      const task = this.queue.shift();\n      if (!task || this.cancelledIds.has(task.id)) continue;\n\n      this.activeCount++;\n\n      // Execute without awaiting to allow concurrent processing\n      task\n        .execute()\n        .catch((error) => {\n          // Ignore cancellation errors\n          if (error?.name !== 'RenderingCancelledException') {\n            console.warn(`Render task ${task.id} failed:`, error);\n          }\n        })\n        .finally(() => {\n          this.activeCount--;\n          this.processQueue();\n        });\n    }\n\n    this.isProcessing = false;\n  }\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Throttle function calls to limit execution frequency.\n */\nexport function throttle<T extends (...args: Parameters<T>) => void>(\n  func: T,\n  limit: number\n): (...args: Parameters<T>) => void {\n  let inThrottle = false;\n  let lastArgs: Parameters<T> | null = null;\n\n  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\n    if (!inThrottle) {\n      func.apply(this, args);\n      inThrottle = true;\n      setTimeout(() => {\n        inThrottle = false;\n        if (lastArgs) {\n          func.apply(this, lastArgs);\n          lastArgs = null;\n        }\n      }, limit);\n    } else {\n      lastArgs = args;\n    }\n  };\n}\n\n/**\n * Debounce function calls to delay execution until after a pause.\n */\nexport function debounce<T extends (...args: Parameters<T>) => void>(\n  func: T,\n  wait: number\n): (...args: Parameters<T>) => void {\n  let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n  return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\n    if (timeoutId !== null) {\n      clearTimeout(timeoutId);\n    }\n    timeoutId = setTimeout(() => {\n      func.apply(this, args);\n      timeoutId = null;\n    }, wait);\n  };\n}\n\n/**\n * Request idle callback with fallback for browsers that don't support it.\n */\nexport function requestIdleCallbackCompat(\n  callback: () => void,\n  options?: { timeout?: number }\n): number {\n  if (typeof window === 'undefined') {\n    // SSR fallback\n    return 0;\n  }\n\n  if ('requestIdleCallback' in window) {\n    return (window as Window & { requestIdleCallback: (cb: () => void, opts?: { timeout?: number }) => number }).requestIdleCallback(callback, options);\n  }\n\n  // Fallback to setTimeout for browsers without requestIdleCallback\n  return setTimeout(callback, options?.timeout ?? 1) as unknown as number;\n}\n\n/**\n * Cancel idle callback with fallback.\n */\nexport function cancelIdleCallbackCompat(id: number): void {\n  if (typeof window === 'undefined') {\n    return;\n  }\n\n  if ('cancelIdleCallback' in window) {\n    (window as Window & { cancelIdleCallback: (id: number) => void }).cancelIdleCallback(id);\n  } else {\n    clearTimeout(id);\n  }\n}\n\n/**\n * Calculate optimal canvas dimensions respecting max dimension limits.\n */\nexport function calculateOptimalCanvasDimensions(\n  width: number,\n  height: number,\n  scaleFactor: number,\n  maxDimension: number\n): { width: number; height: number; actualScale: number } {\n  let canvasWidth = Math.floor(width * scaleFactor);\n  let canvasHeight = Math.floor(height * scaleFactor);\n  let actualScale = scaleFactor;\n\n  // Check if either dimension exceeds the max\n  if (canvasWidth > maxDimension || canvasHeight > maxDimension) {\n    const scaleToFit = Math.min(maxDimension / canvasWidth, maxDimension / canvasHeight);\n    canvasWidth = Math.floor(canvasWidth * scaleToFit);\n    canvasHeight = Math.floor(canvasHeight * scaleToFit);\n    actualScale = scaleFactor * scaleToFit;\n  }\n\n  return { width: canvasWidth, height: canvasHeight, actualScale };\n}\n\n// ============================================================================\n// Global Instance\n// ============================================================================\n\nlet globalCapabilities: DeviceCapabilities | null = null;\nlet globalRenderConfig: RenderConfig | null = null;\nlet globalRenderQueue: RenderQueue | null = null;\n\n/**\n * Get or initialize global device capabilities (cached).\n */\nexport function getDeviceCapabilities(): DeviceCapabilities {\n  if (!globalCapabilities) {\n    globalCapabilities = detectDeviceCapabilities();\n  }\n  return globalCapabilities;\n}\n\n/**\n * Get or initialize global render config (cached).\n */\nexport function getGlobalRenderConfig(quality: RenderQuality = 'auto'): RenderConfig {\n  if (!globalRenderConfig) {\n    const caps = getDeviceCapabilities();\n    globalRenderConfig = getRenderConfig(quality, caps);\n  }\n  return globalRenderConfig;\n}\n\n/**\n * Get or initialize global render queue.\n */\nexport function getGlobalRenderQueue(): RenderQueue {\n  if (!globalRenderQueue) {\n    const config = getGlobalRenderConfig();\n    globalRenderQueue = new RenderQueue(config.maxConcurrentRenders);\n  }\n  return globalRenderQueue;\n}\n\n/**\n * Reset global instances (useful for testing or config changes).\n */\nexport function resetMobileConfig(): void {\n  globalCapabilities = null;\n  globalRenderConfig = null;\n  if (globalRenderQueue) {\n    globalRenderQueue.clear();\n    globalRenderQueue = null;\n  }\n}\n","import type { BBoxCoords, PageDimensionsDpi } from '../types/bbox';\n\nexport interface ViewportSize {\n  width: number;\n  height: number;\n}\n\nexport interface CameraTarget {\n  /** scale multiplier relative to fit-page scale */\n  scale: number;\n  /** translate in pixels (screen-space), to center the target block in the viewport */\n  x: number;\n  /** translate in pixels */\n  y: number;\n}\n\n/** Returns the scale that makes a page fit the viewport (contain, not cover). */\nexport function fitPageScale(\n  page: PageDimensionsDpi,\n  viewport: ViewportSize,\n): number {\n  const sx = viewport.width / page.width;\n  const sy = viewport.height / page.height;\n  return Math.min(sx, sy);\n}\n\n/**\n * Compute a camera target that frames a block's bbox with the requested\n * scale multiplier (1 = fit the block tightly with padding; 1.5 = a little\n * smaller frame = more zoom; <1 = more context).\n *\n * Coordinates are in PDF units — padding is also in PDF units.\n */\nexport function computeCameraForBlock(\n  bbox: BBoxCoords,\n  page: PageDimensionsDpi,\n  viewport: ViewportSize,\n  opts: { targetScale?: number; paddingPdf?: number } = {},\n): CameraTarget {\n  const targetScale = opts.targetScale ?? 1.5;\n  const paddingPdf = opts.paddingPdf ?? 80;\n\n  const [x1, y1, x2, y2] = bbox;\n  const blockW = Math.max(1, x2 - x1 + paddingPdf * 2);\n  const blockH = Math.max(1, y2 - y1 + paddingPdf * 2);\n  const blockCX = (x1 + x2) / 2;\n  const blockCY = (y1 + y2) / 2;\n\n  const fitBlock = Math.min(viewport.width / blockW, viewport.height / blockH);\n  const scale = fitBlock * targetScale;\n\n  const pageCX = page.width / 2;\n  const pageCY = page.height / 2;\n\n  const x = (pageCX - blockCX) * scale;\n  const y = (pageCY - blockCY) * scale;\n\n  return { scale, x, y };\n}\n\n/** Fit-page camera target (no pan). */\nexport function fitPageTarget(\n  page: PageDimensionsDpi,\n  viewport: ViewportSize,\n): CameraTarget {\n  return { scale: fitPageScale(page, viewport), x: 0, y: 0 };\n}\n\n/**\n * Clamp a camera target so the page doesn't drift fully off-screen at high scale.\n * Ensures the visible area of the viewport still intersects the page.\n */\nexport function clampCamera(\n  target: CameraTarget,\n  page: PageDimensionsDpi,\n  viewport: ViewportSize,\n): CameraTarget {\n  const pageWScreen = page.width * target.scale;\n  const pageHScreen = page.height * target.scale;\n  const maxOffsetX = Math.max(0, (pageWScreen - viewport.width) / 2);\n  const maxOffsetY = Math.max(0, (pageHScreen - viewport.height) / 2);\n  return {\n    scale: target.scale,\n    x: Math.max(-maxOffsetX, Math.min(maxOffsetX, target.x)),\n    y: Math.max(-maxOffsetY, Math.min(maxOffsetY, target.y)),\n  };\n}\n","export { cn } from './cn';\nexport { initializePDFJS, isPDFJSInitialized, resetPDFJS, pdfjsLib } from './pdfjs-init';\nexport {\n  loadDocument,\n  loadDocumentWithCallbacks,\n  getPage,\n  getPageTextContent,\n  getOutline,\n  getMetadata,\n  clearDocumentCache,\n  preloadDocument,\n  type LoadDocumentOptions,\n  type LoadDocumentResult,\n  type LoadDocumentWithCallbacksOptions,\n  type LoadDocumentWithCallbacksResult,\n} from './document-loader';\nexport {\n  saveHighlights,\n  loadHighlights,\n  clearHighlights,\n  getAllDocumentIds,\n  exportHighlightsAsJSON,\n  importHighlightsFromJSON,\n  exportHighlightsAsMarkdown,\n  generateDocumentId,\n} from './highlight-storage';\nexport {\n  createPDFViewer,\n  quickViewer,\n  type PDFViewerController,\n  type PDFViewerControllerOptions,\n} from './convenience';\n\n// Student Learning Utils\nexport {\n  exportAnnotationsAsMarkdown,\n  exportAnnotationsAsJSON,\n  downloadAnnotationsAsMarkdown,\n  downloadAnnotationsAsJSON,\n  downloadFile,\n  type ExportData,\n} from './export-annotations';\n\nexport {\n  saveStudentData,\n  loadStudentData,\n  clearStudentData,\n  getAllStudentDataDocumentIds,\n  getStorageStats,\n  type StoredStudentData,\n  type StudentData,\n} from './student-storage';\n\nexport {\n  createAgentAPI,\n  type AgentAPIStores,\n  type AgentAPIInstance,\n} from './agent-api';\n\n// Text Search Utilities\nexport {\n  extractPageText,\n  findTextOnPage,\n  findTextInDocument,\n  mergeAdjacentRects,\n  getPageText,\n  countTextOnPage,\n  type TextMatch,\n  type FindTextOptions,\n  type CharPosition,\n} from './text-search';\n\n// Coordinate Utilities\nexport {\n  pdfToViewport,\n  viewportToPDF,\n  percentToPDF,\n  pdfToPercent,\n  percentToViewport,\n  viewportToPercent,\n  applyRotation,\n  removeRotation,\n  getRotatedDimensions,\n  scaleRect,\n  isPointInRect,\n  doRectsIntersect,\n  getRectIntersection,\n} from './coordinates';\n\n// Page Turn Sound\nexport { playPageTurnSound } from './page-turn-sound';\n\n// Mobile Optimizations\nexport {\n  detectDeviceCapabilities,\n  getDeviceCapabilities,\n  getRenderConfig,\n  getGlobalRenderConfig,\n  getMemoryStatus,\n  getGlobalRenderQueue,\n  resetMobileConfig,\n  calculateOptimalCanvasDimensions,\n  throttle,\n  debounce,\n  requestIdleCallbackCompat,\n  cancelIdleCallbackCompat,\n  RenderQueue,\n  type DeviceCapabilities,\n  type RenderQuality,\n  type RenderConfig,\n  type MemoryStatus,\n} from './mobile-config';\n\nexport {\n  fitPageScale,\n  fitPageTarget,\n  computeCameraForBlock,\n  clampCamera,\n  type ViewportSize,\n  type CameraTarget,\n} from './camera-math';\n","import { createStore } from 'zustand/vanilla';\nimport type { SearchState, SearchResult, HighlightRect } from '../types';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\n\n// Define local text item interface to avoid pdfjs-dist type issues\ninterface TextContentItem {\n  str?: string;\n  transform?: number[];\n  width?: number;\n  height?: number;\n}\n\nexport interface SearchActions {\n  setQuery: (query: string) => void;\n  search: (document: PDFDocumentProxy) => Promise<void>;\n  clearSearch: () => void;\n  nextResult: () => void;\n  previousResult: () => void;\n  goToResult: (index: number) => void;\n  setCaseSensitive: (value: boolean) => void;\n  setWholeWord: (value: boolean) => void;\n  toggleCaseSensitive: () => void;\n  toggleWholeWord: () => void;\n  getCurrentResult: () => SearchResult | null;\n}\n\nexport type SearchStore = SearchState & SearchActions;\n\nconst initialState: SearchState = {\n  query: '',\n  results: [],\n  currentResultIndex: -1,\n  isSearching: false,\n  caseSensitive: false,\n  wholeWord: false,\n};\n\nfunction isTextItem(item: TextContentItem): item is TextContentItem & { str: string; transform: number[]; width: number; height: number } {\n  return typeof item.str === 'string';\n}\n\nexport function createSearchStore(initialOverrides: Partial<SearchState> = {}) {\n  return createStore<SearchStore>()((set, get) => ({\n    ...initialState,\n    ...initialOverrides,\n\n    setQuery: (query) => {\n      set({ query });\n    },\n\n    search: async (document) => {\n      const { query, caseSensitive, wholeWord } = get();\n\n      if (!query.trim()) {\n        set({ results: [], currentResultIndex: -1, isSearching: false });\n        return;\n      }\n\n      set({ isSearching: true, results: [], currentResultIndex: -1 });\n\n      const results: SearchResult[] = [];\n      const numPages = document.numPages;\n\n      // Prepare search pattern\n      const searchText = caseSensitive ? query : query.toLowerCase();\n\n      for (let pageNum = 1; pageNum <= numPages; pageNum++) {\n        try {\n          const page = await document.getPage(pageNum);\n          const textContent = await page.getTextContent();\n          const viewport = page.getViewport({ scale: 1 });\n\n          // Combine all text items on the page\n          let pageText = '';\n          const textItems: Array<{ text: string; transform: number[]; width: number; height: number }> = [];\n\n          for (const item of textContent.items as TextContentItem[]) {\n            if (isTextItem(item)) {\n              textItems.push({\n                text: item.str,\n                transform: item.transform,\n                width: item.width,\n                height: item.height,\n              });\n              pageText += item.str;\n            }\n          }\n\n          // Search in page text\n          const textToSearch = caseSensitive ? pageText : pageText.toLowerCase();\n          let matchIndex = 0;\n          let startIndex = 0;\n\n          while ((startIndex = textToSearch.indexOf(searchText, startIndex)) !== -1) {\n            // Check whole word condition\n            if (wholeWord) {\n              const before = startIndex > 0 ? textToSearch[startIndex - 1] : ' ';\n              const after = startIndex + searchText.length < textToSearch.length\n                ? textToSearch[startIndex + searchText.length]\n                : ' ';\n\n              if (/\\w/.test(before) || /\\w/.test(after)) {\n                startIndex++;\n                continue;\n              }\n            }\n\n            // Find the text items that contain this match\n            const matchText = pageText.substring(startIndex, startIndex + query.length);\n            const rects = calculateMatchRects(textItems, startIndex, query.length, viewport);\n\n            results.push({\n              pageNumber: pageNum,\n              matchIndex: matchIndex++,\n              text: matchText,\n              rects,\n            });\n\n            startIndex++;\n          }\n        } catch (error) {\n          console.error(`Error searching page ${pageNum}:`, error);\n        }\n      }\n\n      set({\n        results,\n        currentResultIndex: results.length > 0 ? 0 : -1,\n        isSearching: false,\n      });\n    },\n\n    clearSearch: () => {\n      set(initialState);\n    },\n\n    nextResult: () => {\n      const { results, currentResultIndex } = get();\n      if (results.length === 0) return;\n\n      const nextIndex = (currentResultIndex + 1) % results.length;\n      set({ currentResultIndex: nextIndex });\n    },\n\n    previousResult: () => {\n      const { results, currentResultIndex } = get();\n      if (results.length === 0) return;\n\n      const prevIndex = currentResultIndex <= 0 ? results.length - 1 : currentResultIndex - 1;\n      set({ currentResultIndex: prevIndex });\n    },\n\n    goToResult: (index) => {\n      const { results } = get();\n      if (index >= 0 && index < results.length) {\n        set({ currentResultIndex: index });\n      }\n    },\n\n    setCaseSensitive: (value) => {\n      set({ caseSensitive: value });\n    },\n\n    setWholeWord: (value) => {\n      set({ wholeWord: value });\n    },\n\n    toggleCaseSensitive: () => {\n      set((state) => ({ caseSensitive: !state.caseSensitive }));\n    },\n\n    toggleWholeWord: () => {\n      set((state) => ({ wholeWord: !state.wholeWord }));\n    },\n\n    getCurrentResult: () => {\n      const { results, currentResultIndex } = get();\n      if (currentResultIndex >= 0 && currentResultIndex < results.length) {\n        return results[currentResultIndex];\n      }\n      return null;\n    },\n  }));\n}\n\n/**\n * Calculate the bounding rectangles for a text match.\n * This is a simplified implementation that may need refinement for complex layouts.\n */\nfunction calculateMatchRects(\n  textItems: Array<{ text: string; transform: number[]; width: number; height: number }>,\n  startOffset: number,\n  length: number,\n  viewport: { width: number; height: number }\n): HighlightRect[] {\n  const rects: HighlightRect[] = [];\n  let currentOffset = 0;\n\n  for (const item of textItems) {\n    const itemStart = currentOffset;\n    const itemEnd = currentOffset + item.text.length;\n\n    // Check if this item overlaps with our match\n    if (itemEnd > startOffset && itemStart < startOffset + length) {\n      const [, , c, d, tx, ty] = item.transform;\n\n      // Convert PDF coordinates to viewport coordinates\n      const x = tx;\n      const y = viewport.height - ty;\n\n      // Approximate height from transform matrix\n      const height = Math.sqrt(c * c + d * d);\n\n      // Calculate the portion of this item that's part of the match\n      const matchStartInItem = Math.max(0, startOffset - itemStart);\n      const matchEndInItem = Math.min(item.text.length, startOffset + length - itemStart);\n      const matchWidth = (item.width / item.text.length) * (matchEndInItem - matchStartInItem);\n      const matchX = x + (item.width / item.text.length) * matchStartInItem;\n\n      // Adjust Y position: ty is the baseline, we need to position highlight\n      // lower to align with the actual text glyphs (not the baseline)\n      const yOffset = height * 0.30; // Shift down by 30% of height\n\n      rects.push({\n        x: matchX,\n        y: y - height + yOffset,\n        width: matchWidth,\n        height: height,\n      });\n    }\n\n    currentOffset = itemEnd;\n  }\n\n  return rects;\n}\n\nexport type SearchStoreApi = ReturnType<typeof createSearchStore>;\n","import { createStore } from 'zustand/vanilla';\nimport type { AgentState, AgentActions, AgentContext, FocusedRegion } from '../types/agent-context';\n\nexport type AgentStore = AgentState & AgentActions;\n\nconst initialState: AgentState = {\n  currentContext: null,\n  focusedRegions: [],\n};\n\nlet focusRegionIdCounter = 0;\n\nfunction generateFocusRegionId(): string {\n  return `focus-region-${++focusRegionIdCounter}-${Date.now()}`;\n}\n\nexport function createAgentStore(initialOverrides: Partial<AgentState> = {}) {\n  return createStore<AgentStore>()((set, get) => ({\n    ...initialState,\n    ...initialOverrides,\n\n    setAgentContext: (context: Partial<AgentContext>) => {\n      const { currentContext } = get();\n      set({\n        currentContext: {\n          ...currentContext,\n          ...context,\n          timestamp: context.timestamp ?? new Date(),\n        } as AgentContext,\n      });\n    },\n\n    clearAgentContext: () => {\n      set({ currentContext: null });\n    },\n\n    addFocusedRegion: (region: Omit<FocusedRegion, 'id'>) => {\n      const id = generateFocusRegionId();\n      const focusedRegion: FocusedRegion = {\n        ...region,\n        id,\n        style: region.style ?? 'pulse',\n      };\n\n      set((state) => ({\n        focusedRegions: [...state.focusedRegions, focusedRegion],\n      }));\n\n      // Set up auto-clear if timeout is specified\n      if (region.autoClearTimeout && region.autoClearTimeout > 0) {\n        setTimeout(() => {\n          const { removeFocusedRegion } = get();\n          removeFocusedRegion(id);\n        }, region.autoClearTimeout);\n      }\n\n      return id;\n    },\n\n    removeFocusedRegion: (id: string) => {\n      set((state) => ({\n        focusedRegions: state.focusedRegions.filter((r) => r.id !== id),\n      }));\n    },\n\n    clearAllFocusedRegions: () => {\n      set({ focusedRegions: [] });\n    },\n\n    reset: () => {\n      set(initialState);\n    },\n  }));\n}\n\nexport type AgentStoreApi = ReturnType<typeof createAgentStore>;\n","import { createStore } from 'zustand/vanilla';\nimport type {\n  StudentState,\n  StudentActions,\n  Bookmark,\n  QuickNote,\n  Takeaway,\n} from '../types/agent-context';\n\nexport type StudentStore = StudentState & StudentActions;\n\nconst STORAGE_PREFIX = 'pdf-reader-student';\n\nlet idCounter = 0;\n\nfunction generateId(prefix: string): string {\n  return `${prefix}-${++idCounter}-${Date.now()}`;\n}\n\nfunction isStorageAvailable(): boolean {\n  if (typeof window === 'undefined') return false;\n  try {\n    const test = '__storage_test__';\n    localStorage.setItem(test, test);\n    localStorage.removeItem(test);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction getStorageKey(documentId: string, type: string): string {\n  return `${STORAGE_PREFIX}:${documentId}:${type}`;\n}\n\n// Serialization helpers for dates\ninterface StoredBookmark extends Omit<Bookmark, 'timestamp'> {\n  timestamp: string;\n}\n\ninterface StoredQuickNote extends Omit<QuickNote, 'timestamp'> {\n  timestamp: string;\n}\n\ninterface StoredTakeaway extends Omit<Takeaway, 'timestamp'> {\n  timestamp: string;\n}\n\ninterface StoredStudentData {\n  bookmarks: StoredBookmark[];\n  quickNotes: StoredQuickNote[];\n  takeaways: StoredTakeaway[];\n  visitedPages: number[];\n  progress: number;\n}\n\nconst initialState: StudentState = {\n  bookmarks: [],\n  quickNotes: [],\n  takeaways: [],\n  visitedPages: new Set<number>(),\n  progress: 0,\n};\n\nexport function createStudentStore(initialOverrides: Partial<StudentState> = {}) {\n  return createStore<StudentStore>()((set, get) => ({\n    ...initialState,\n    ...initialOverrides,\n\n    // Bookmark actions\n    addBookmark: (bookmark: Omit<Bookmark, 'id' | 'timestamp'>) => {\n      const newBookmark: Bookmark = {\n        ...bookmark,\n        id: generateId('bookmark'),\n        timestamp: new Date(),\n      };\n\n      set((state) => ({\n        bookmarks: [...state.bookmarks, newBookmark],\n      }));\n\n      return newBookmark;\n    },\n\n    updateBookmark: (id: string, updates: Partial<Omit<Bookmark, 'id'>>) => {\n      set((state) => ({\n        bookmarks: state.bookmarks.map((b) =>\n          b.id === id ? { ...b, ...updates } : b\n        ),\n      }));\n    },\n\n    removeBookmark: (id: string) => {\n      set((state) => ({\n        bookmarks: state.bookmarks.filter((b) => b.id !== id),\n      }));\n    },\n\n    // Quick note actions\n    addQuickNote: (note: Omit<QuickNote, 'id' | 'timestamp'>) => {\n      const newNote: QuickNote = {\n        ...note,\n        id: generateId('note'),\n        timestamp: new Date(),\n      };\n\n      set((state) => ({\n        quickNotes: [...state.quickNotes, newNote],\n      }));\n\n      return newNote;\n    },\n\n    updateQuickNote: (id: string, updates: Partial<Omit<QuickNote, 'id'>>) => {\n      set((state) => ({\n        quickNotes: state.quickNotes.map((n) =>\n          n.id === id ? { ...n, ...updates } : n\n        ),\n      }));\n    },\n\n    removeQuickNote: (id: string) => {\n      set((state) => ({\n        quickNotes: state.quickNotes.filter((n) => n.id !== id),\n      }));\n    },\n\n    // Takeaway actions\n    addTakeaway: (takeaway: Omit<Takeaway, 'id' | 'timestamp'>) => {\n      const newTakeaway: Takeaway = {\n        ...takeaway,\n        id: generateId('takeaway'),\n        timestamp: new Date(),\n      };\n\n      set((state) => ({\n        takeaways: [...state.takeaways, newTakeaway],\n      }));\n\n      return newTakeaway;\n    },\n\n    removeTakeaway: (id: string) => {\n      set((state) => ({\n        takeaways: state.takeaways.filter((t) => t.id !== id),\n      }));\n    },\n\n    // Progress tracking\n    markPageVisited: (pageNumber: number) => {\n      set((state) => {\n        const newVisitedPages = new Set(state.visitedPages);\n        newVisitedPages.add(pageNumber);\n        return { visitedPages: newVisitedPages };\n      });\n    },\n\n    setProgress: (progress: number) => {\n      set({ progress: Math.max(0, Math.min(1, progress)) });\n    },\n\n    // Persistence\n    persistToStorage: (documentId: string) => {\n      if (!isStorageAvailable()) {\n        console.warn('localStorage not available, student data will not persist');\n        return;\n      }\n\n      const state = get();\n\n      const data: StoredStudentData = {\n        bookmarks: state.bookmarks.map((b) => ({\n          ...b,\n          timestamp: b.timestamp.toISOString(),\n        })),\n        quickNotes: state.quickNotes.map((n) => ({\n          ...n,\n          timestamp: n.timestamp.toISOString(),\n        })),\n        takeaways: state.takeaways.map((t) => ({\n          ...t,\n          timestamp: t.timestamp.toISOString(),\n        })),\n        visitedPages: Array.from(state.visitedPages),\n        progress: state.progress,\n      };\n\n      try {\n        localStorage.setItem(getStorageKey(documentId, 'data'), JSON.stringify(data));\n      } catch (error) {\n        console.error('Failed to persist student data:', error);\n      }\n    },\n\n    loadFromStorage: (documentId: string) => {\n      if (!isStorageAvailable()) {\n        return;\n      }\n\n      try {\n        const stored = localStorage.getItem(getStorageKey(documentId, 'data'));\n        if (!stored) {\n          return;\n        }\n\n        const data: StoredStudentData = JSON.parse(stored);\n\n        set({\n          bookmarks: data.bookmarks.map((b) => ({\n            ...b,\n            timestamp: new Date(b.timestamp),\n          })),\n          quickNotes: data.quickNotes.map((n) => ({\n            ...n,\n            timestamp: new Date(n.timestamp),\n          })),\n          takeaways: data.takeaways.map((t) => ({\n            ...t,\n            timestamp: new Date(t.timestamp),\n          })),\n          visitedPages: new Set(data.visitedPages),\n          progress: data.progress,\n        });\n      } catch (error) {\n        console.error('Failed to load student data:', error);\n      }\n    },\n\n    reset: () => {\n      set(initialState);\n    },\n  }));\n}\n\nexport type StudentStoreApi = ReturnType<typeof createStudentStore>;\n","import { createStore } from 'zustand/vanilla';\nimport type {\n  CameraState,\n  ActiveOverlay,\n  Storyboard,\n  StoryboardAction,\n} from '../types/storyboard';\n\nexport interface ChunkHistoryEntry {\n  text: string;\n  pageNumber: number;\n  timestamp: number;\n}\n\nexport type EngineStatus = 'idle' | 'transitioning' | 'executing';\nexport type LlmStatus = 'idle' | 'in-flight' | 'failed';\n\nexport interface DebugEvent {\n  id: string;\n  timestamp: number;\n  kind:\n    | 'chunk'\n    | 'llm-request'\n    | 'llm-response'\n    | 'llm-error'\n    | 'storyboard-execute'\n    | 'fallback-fired'\n    | 'note';\n  /** Short headline shown in the log */\n  summary: string;\n  /** Full payload (chunk text, raw LLM response, parsed storyboard, error, etc.) */\n  payload?: unknown;\n}\n\nexport interface NarrationState {\n  currentChunk: string | null;\n  currentPage: number;\n  chunkHistory: ChunkHistoryEntry[];\n  camera: CameraState;\n  activeOverlays: ActiveOverlay[];\n  engineStatus: EngineStatus;\n  llmStatus: LlmStatus;\n  lastStoryboard: Storyboard | null;\n  lastError: string | null;\n  isPaused: boolean;\n  debugEvents: DebugEvent[];\n}\n\nexport interface NarrationActions {\n  setCurrentChunk: (chunk: string | null) => void;\n  setCurrentPage: (page: number) => void;\n  pushChunkHistory: (entry: ChunkHistoryEntry) => void;\n  setCamera: (camera: Partial<CameraState>) => void;\n  addOverlay: (overlay: ActiveOverlay) => void;\n  removeOverlay: (id: string) => void;\n  clearOverlays: (predicate?: (o: ActiveOverlay) => boolean) => void;\n  setEngineStatus: (s: EngineStatus) => void;\n  setLlmStatus: (s: LlmStatus, error?: string | null) => void;\n  setLastStoryboard: (sb: Storyboard | null) => void;\n  setPaused: (paused: boolean) => void;\n  appendDebugEvent: (event: Omit<DebugEvent, 'id' | 'timestamp'>) => void;\n  clearDebugEvents: () => void;\n  reset: () => void;\n}\n\nexport type NarrationStore = NarrationState & NarrationActions;\n\nconst MAX_HISTORY = 5;\n\nconst initialState: NarrationState = {\n  currentChunk: null,\n  currentPage: 1,\n  chunkHistory: [],\n  camera: { scale: 1, x: 0, y: 0, easing: 'ease-in-out' },\n  activeOverlays: [],\n  engineStatus: 'idle',\n  llmStatus: 'idle',\n  lastStoryboard: null,\n  lastError: null,\n  isPaused: false,\n  debugEvents: [],\n};\n\nconst MAX_DEBUG_EVENTS = 50;\nlet debugEventCounter = 0;\n\nexport function createNarrationStore(overrides: Partial<NarrationState> = {}) {\n  return createStore<NarrationStore>()((set) => ({\n    ...initialState,\n    ...overrides,\n\n    setCurrentChunk: (chunk) => set({ currentChunk: chunk }),\n    setCurrentPage: (page) => set({ currentPage: page }),\n\n    pushChunkHistory: (entry) =>\n      set((state) => ({\n        chunkHistory: [\n          ...state.chunkHistory.slice(-(MAX_HISTORY - 1)),\n          entry,\n        ],\n      })),\n\n    setCamera: (camera) =>\n      set((state) => ({ camera: { ...state.camera, ...camera } })),\n\n    addOverlay: (overlay) =>\n      set((state) => ({ activeOverlays: [...state.activeOverlays, overlay] })),\n\n    removeOverlay: (id) =>\n      set((state) => ({\n        activeOverlays: state.activeOverlays.filter((o) => o.id !== id),\n      })),\n\n    clearOverlays: (predicate) =>\n      set((state) => ({\n        activeOverlays: predicate\n          ? state.activeOverlays.filter((o) => !predicate(o))\n          : [],\n      })),\n\n    setEngineStatus: (s) => set({ engineStatus: s }),\n\n    setLlmStatus: (s, error = null) =>\n      set({ llmStatus: s, lastError: error }),\n\n    setLastStoryboard: (sb) => set({ lastStoryboard: sb }),\n\n    setPaused: (paused) => set({ isPaused: paused }),\n\n    appendDebugEvent: (event) =>\n      set((state) => {\n        debugEventCounter += 1;\n        const next: DebugEvent = {\n          ...event,\n          id: `dbg-${debugEventCounter}`,\n          timestamp: Date.now(),\n        };\n        return {\n          debugEvents: [\n            ...state.debugEvents.slice(-(MAX_DEBUG_EVENTS - 1)),\n            next,\n          ],\n        };\n      }),\n\n    clearDebugEvents: () => set({ debugEvents: [] }),\n\n    reset: () => set(initialState),\n  }));\n}\n\nexport type NarrationStoreApi = ReturnType<typeof createNarrationStore>;\n\nlet overlayIdCounter = 0;\nexport function makeOverlayId(action: StoryboardAction): string {\n  overlayIdCounter += 1;\n  return `ov-${action.type}-${overlayIdCounter}-${Date.now()}`;\n}\n","export {\n  createViewerStore,\n  type ViewerStore,\n  type ViewerStoreApi,\n} from './viewer-store';\n\nexport {\n  createAnnotationStore,\n  type AnnotationStore,\n  type AnnotationStoreApi,\n  type AnnotationState,\n  type AnnotationActions,\n  type AnnotationTool,\n  type ShapeType,\n} from './annotation-store';\n\nexport {\n  createSearchStore,\n  type SearchStore,\n  type SearchStoreApi,\n  type SearchActions,\n} from './search-store';\n\nexport {\n  createAgentStore,\n  type AgentStore,\n  type AgentStoreApi,\n} from './agent-store';\n\nexport {\n  createStudentStore,\n  type StudentStore,\n  type StudentStoreApi,\n} from './student-store';\n\nexport {\n  createNarrationStore,\n  makeOverlayId,\n  type NarrationStore,\n  type NarrationStoreApi,\n  type NarrationState,\n  type NarrationActions,\n  type EngineStatus,\n  type LlmStatus,\n  type ChunkHistoryEntry,\n  type DebugEvent,\n} from './narration-store';\n","import { createContext, useContext, useRef, useEffect, type ReactNode } from 'react';\nimport { useStore } from 'zustand';\nimport {\n  createViewerStore,\n  createAnnotationStore,\n  createSearchStore,\n  createAgentStore,\n  createStudentStore,\n  type ViewerStoreApi,\n  type AnnotationStoreApi,\n  type SearchStoreApi,\n  type AgentStoreApi,\n  type StudentStoreApi,\n  type ViewerStore,\n  type AnnotationStore,\n  type SearchStore,\n  type AgentStore,\n  type StudentStore,\n  type AnnotationState,\n} from '../store';\nimport type { ViewerState, SearchState, Theme, SidebarPanel, AgentState, StudentState } from '../types';\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface PDFViewerContextValue {\n  viewerStore: ViewerStoreApi;\n  annotationStore: AnnotationStoreApi;\n  searchStore: SearchStoreApi;\n  agentStore: AgentStoreApi;\n  studentStore: StudentStoreApi;\n}\n\nexport interface PDFViewerProviderProps {\n  children: ReactNode;\n  initialState?: {\n    viewer?: Partial<ViewerState>;\n    annotation?: Partial<AnnotationState>;\n    search?: Partial<SearchState>;\n    agent?: Partial<AgentState>;\n    student?: Partial<StudentState>;\n  };\n  theme?: Theme;\n  defaultSidebarPanel?: SidebarPanel;\n  /** Enable student learning mode features */\n  studentMode?: boolean;\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst PDFViewerContext = createContext<PDFViewerContextValue | null>(null);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport function PDFViewerProvider({\n  children,\n  initialState,\n  theme = 'light',\n  defaultSidebarPanel = 'thumbnails',\n  studentMode: _studentMode = false,\n}: PDFViewerProviderProps) {\n  const viewerStoreRef = useRef<ViewerStoreApi | null>(null);\n  const annotationStoreRef = useRef<AnnotationStoreApi | null>(null);\n  const searchStoreRef = useRef<SearchStoreApi | null>(null);\n  const agentStoreRef = useRef<AgentStoreApi | null>(null);\n  const studentStoreRef = useRef<StudentStoreApi | null>(null);\n\n  // Create stores only once\n  if (!viewerStoreRef.current) {\n    viewerStoreRef.current = createViewerStore({\n      ...initialState?.viewer,\n      theme,\n      sidebarPanel: defaultSidebarPanel,\n    });\n  }\n\n  if (!annotationStoreRef.current) {\n    annotationStoreRef.current = createAnnotationStore(initialState?.annotation);\n  }\n\n  if (!searchStoreRef.current) {\n    searchStoreRef.current = createSearchStore(initialState?.search);\n  }\n\n  // Create agent and student stores (always created for API consistency)\n  if (!agentStoreRef.current) {\n    agentStoreRef.current = createAgentStore(initialState?.agent);\n  }\n\n  if (!studentStoreRef.current) {\n    studentStoreRef.current = createStudentStore(initialState?.student);\n  }\n\n  // Cleanup on unmount\n  useEffect(() => {\n    return () => {\n      viewerStoreRef.current?.getState().reset();\n      agentStoreRef.current?.getState().reset();\n      studentStoreRef.current?.getState().reset();\n    };\n  }, []);\n\n  return (\n    <PDFViewerContext.Provider\n      value={{\n        viewerStore: viewerStoreRef.current,\n        annotationStore: annotationStoreRef.current,\n        searchStore: searchStoreRef.current,\n        agentStore: agentStoreRef.current,\n        studentStore: studentStoreRef.current,\n      }}\n    >\n      {children}\n    </PDFViewerContext.Provider>\n  );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nfunction usePDFViewerContext() {\n  const context = useContext(PDFViewerContext);\n  if (!context) {\n    throw new Error('usePDFViewerContext must be used within a PDFViewerProvider');\n  }\n  return context;\n}\n\n/**\n * Hook to access the viewer store.\n * Optionally pass a selector to subscribe to specific state.\n */\nexport function useViewerStore<T>(selector: (state: ViewerStore) => T): T {\n  const { viewerStore } = usePDFViewerContext();\n  return useStore(viewerStore, selector);\n}\n\n/**\n * Hook to access the annotation store.\n * Optionally pass a selector to subscribe to specific state.\n */\nexport function useAnnotationStore<T>(selector: (state: AnnotationStore) => T): T {\n  const { annotationStore } = usePDFViewerContext();\n  return useStore(annotationStore, selector);\n}\n\n/**\n * Hook to access the search store.\n * Optionally pass a selector to subscribe to specific state.\n */\nexport function useSearchStore<T>(selector: (state: SearchStore) => T): T {\n  const { searchStore } = usePDFViewerContext();\n  return useStore(searchStore, selector);\n}\n\n/**\n * Hook to access the agent store.\n * Optionally pass a selector to subscribe to specific state.\n */\nexport function useAgentStore<T>(selector: (state: AgentStore) => T): T {\n  const { agentStore } = usePDFViewerContext();\n  return useStore(agentStore, selector);\n}\n\n/**\n * Hook to access the student store.\n * Optionally pass a selector to subscribe to specific state.\n */\nexport function useStudentStore<T>(selector: (state: StudentStore) => T): T {\n  const { studentStore } = usePDFViewerContext();\n  return useStore(studentStore, selector);\n}\n\n/**\n * Hook to access all stores directly (for actions).\n */\nexport function usePDFViewerStores() {\n  return usePDFViewerContext();\n}\n\nexport { PDFViewerContext };\n","import { useCallback, useMemo } from 'react';\nimport {\n  useViewerStore,\n  useAnnotationStore,\n  useSearchStore,\n  useAgentStore,\n  useStudentStore,\n  usePDFViewerStores,\n} from './PDFViewerContext';\nimport type { Theme, ViewMode, SidebarPanel, HighlightColor, Highlight } from '../types';\nimport type {\n  AgentContext,\n  FocusedRegion,\n  Bookmark,\n  QuickNote,\n  Takeaway,\n  AgentAPI,\n  AgentHighlightParams,\n} from '../types/agent-context';\n\ntype AddHighlightParams = Omit<Highlight, 'id' | 'createdAt' | 'updatedAt'>;\n\n/**\n * Main unified hook for accessing PDF viewer state and actions.\n * This is the primary API for controlling the viewer.\n */\nexport function usePDFViewer() {\n  const { viewerStore, annotationStore, searchStore, agentStore, studentStore } = usePDFViewerStores();\n\n  // ============================================================================\n  // Viewer State\n  // ============================================================================\n\n  const document = useViewerStore((s) => s.document);\n  const numPages = useViewerStore((s) => s.numPages);\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const scale = useViewerStore((s) => s.scale);\n  const rotation = useViewerStore((s) => s.rotation);\n  const isLoading = useViewerStore((s) => s.isLoading);\n  const error = useViewerStore((s) => s.error);\n  const theme = useViewerStore((s) => s.theme);\n  const viewMode = useViewerStore((s) => s.viewMode);\n  const sidebarOpen = useViewerStore((s) => s.sidebarOpen);\n  const sidebarPanel = useViewerStore((s) => s.sidebarPanel);\n  const isFullscreen = useViewerStore((s) => s.isFullscreen);\n\n  // ============================================================================\n  // Annotation State\n  // ============================================================================\n\n  const highlights = useAnnotationStore((s) => s.highlights);\n  const annotations = useAnnotationStore((s) => s.annotations);\n  const selectedHighlightId = useAnnotationStore((s) => s.selectedHighlightId);\n  const activeHighlightColor = useAnnotationStore((s) => s.activeHighlightColor);\n  const isHighlightMode = useAnnotationStore((s) => s.isHighlightMode);\n\n  // ============================================================================\n  // Search State\n  // ============================================================================\n\n  const searchQuery = useSearchStore((s) => s.query);\n  const searchResults = useSearchStore((s) => s.results);\n  const currentSearchResult = useSearchStore((s) => s.currentResultIndex);\n  const isSearching = useSearchStore((s) => s.isSearching);\n\n  // ============================================================================\n  // Navigation Actions\n  // ============================================================================\n\n  const goToPage = useCallback(\n    (page: number) => viewerStore.getState().goToPage(page),\n    [viewerStore]\n  );\n\n  const nextPage = useCallback(\n    () => viewerStore.getState().nextPage(),\n    [viewerStore]\n  );\n\n  const previousPage = useCallback(\n    () => viewerStore.getState().previousPage(),\n    [viewerStore]\n  );\n\n  // ============================================================================\n  // Zoom Actions\n  // ============================================================================\n\n  const setScale = useCallback(\n    (newScale: number) => viewerStore.getState().setScale(newScale),\n    [viewerStore]\n  );\n\n  const zoomIn = useCallback(\n    () => viewerStore.getState().zoomIn(),\n    [viewerStore]\n  );\n\n  const zoomOut = useCallback(\n    () => viewerStore.getState().zoomOut(),\n    [viewerStore]\n  );\n\n  const fitToWidth = useCallback(\n    () => viewerStore.getState().fitToWidth(),\n    [viewerStore]\n  );\n\n  const fitToPage = useCallback(\n    () => viewerStore.getState().fitToPage(),\n    [viewerStore]\n  );\n\n  // ============================================================================\n  // Rotation Actions\n  // ============================================================================\n\n  const rotateClockwise = useCallback(\n    () => viewerStore.getState().rotateClockwise(),\n    [viewerStore]\n  );\n\n  const rotateCounterClockwise = useCallback(\n    () => viewerStore.getState().rotateCounterClockwise(),\n    [viewerStore]\n  );\n\n  // ============================================================================\n  // UI Actions\n  // ============================================================================\n\n  const setTheme = useCallback(\n    (newTheme: Theme) => viewerStore.getState().setTheme(newTheme),\n    [viewerStore]\n  );\n\n  const setViewMode = useCallback(\n    (mode: ViewMode) => viewerStore.getState().setViewMode(mode),\n    [viewerStore]\n  );\n\n  const toggleSidebar = useCallback(\n    () => viewerStore.getState().toggleSidebar(),\n    [viewerStore]\n  );\n\n  const setSidebarPanel = useCallback(\n    (panel: SidebarPanel) => viewerStore.getState().setSidebarPanel(panel),\n    [viewerStore]\n  );\n\n  const setFullscreen = useCallback(\n    (fullscreen: boolean) => viewerStore.getState().setFullscreen(fullscreen),\n    [viewerStore]\n  );\n\n  // ============================================================================\n  // Highlight Actions\n  // ============================================================================\n\n  const addHighlight = useCallback(\n    (highlight: AddHighlightParams) =>\n      annotationStore.getState().addHighlight(highlight),\n    [annotationStore]\n  );\n\n  const removeHighlight = useCallback(\n    (id: string) => annotationStore.getState().removeHighlight(id),\n    [annotationStore]\n  );\n\n  const setActiveHighlightColor = useCallback(\n    (color: HighlightColor) => annotationStore.getState().setActiveHighlightColor(color),\n    [annotationStore]\n  );\n\n  const setHighlightMode = useCallback(\n    (enabled: boolean) => annotationStore.getState().setHighlightMode(enabled),\n    [annotationStore]\n  );\n\n  // ============================================================================\n  // Search Actions\n  // ============================================================================\n\n  const search = useCallback(\n    async (query: string) => {\n      const doc = viewerStore.getState().document;\n      if (!doc) return;\n      searchStore.getState().setQuery(query);\n      await searchStore.getState().search(doc);\n    },\n    [viewerStore, searchStore]\n  );\n\n  const clearSearch = useCallback(\n    () => searchStore.getState().clearSearch(),\n    [searchStore]\n  );\n\n  const nextSearchResult = useCallback(\n    () => searchStore.getState().nextResult(),\n    [searchStore]\n  );\n\n  const previousSearchResult = useCallback(\n    () => searchStore.getState().previousResult(),\n    [searchStore]\n  );\n\n  // ============================================================================\n  // Agent Context State & Actions\n  // ============================================================================\n\n  const agentContext = useAgentStore((s) => s.currentContext);\n  const focusedRegions = useAgentStore((s) => s.focusedRegions);\n\n  const setAgentContext = useCallback(\n    (context: Partial<AgentContext>) => agentStore.getState().setAgentContext(context),\n    [agentStore]\n  );\n\n  const clearAgentContext = useCallback(\n    () => agentStore.getState().clearAgentContext(),\n    [agentStore]\n  );\n\n  const focusRegion = useCallback(\n    (region: Omit<FocusedRegion, 'id'>) => agentStore.getState().addFocusedRegion(region),\n    [agentStore]\n  );\n\n  const clearFocusedRegion = useCallback(\n    (id: string) => agentStore.getState().removeFocusedRegion(id),\n    [agentStore]\n  );\n\n  const clearAllFocusedRegions = useCallback(\n    () => agentStore.getState().clearAllFocusedRegions(),\n    [agentStore]\n  );\n\n  // ============================================================================\n  // Student State & Actions\n  // ============================================================================\n\n  const bookmarks = useStudentStore((s) => s.bookmarks);\n  const quickNotes = useStudentStore((s) => s.quickNotes);\n  const takeaways = useStudentStore((s) => s.takeaways);\n  const visitedPages = useStudentStore((s) => s.visitedPages);\n  const progress = useStudentStore((s) => s.progress);\n\n  const addBookmark = useCallback(\n    (data: Omit<Bookmark, 'id' | 'timestamp'>) => {\n      // Capture agent context when bookmarking\n      const context = agentStore.getState().currentContext;\n      return studentStore.getState().addBookmark({\n        ...data,\n        agentContext: data.agentContext ?? context?.lastStatement,\n      });\n    },\n    [studentStore, agentStore]\n  );\n\n  const updateBookmark = useCallback(\n    (id: string, updates: Partial<Omit<Bookmark, 'id'>>) =>\n      studentStore.getState().updateBookmark(id, updates),\n    [studentStore]\n  );\n\n  const removeBookmark = useCallback(\n    (id: string) => studentStore.getState().removeBookmark(id),\n    [studentStore]\n  );\n\n  const addQuickNote = useCallback(\n    (data: Omit<QuickNote, 'id' | 'timestamp'>) => {\n      // Capture agent context when adding note\n      const context = agentStore.getState().currentContext;\n      return studentStore.getState().addQuickNote({\n        ...data,\n        agentLastStatement: data.agentLastStatement ?? context?.lastStatement,\n      });\n    },\n    [studentStore, agentStore]\n  );\n\n  const updateQuickNote = useCallback(\n    (id: string, updates: Partial<Omit<QuickNote, 'id'>>) =>\n      studentStore.getState().updateQuickNote(id, updates),\n    [studentStore]\n  );\n\n  const removeQuickNote = useCallback(\n    (id: string) => studentStore.getState().removeQuickNote(id),\n    [studentStore]\n  );\n\n  const addTakeaway = useCallback(\n    (data: Omit<Takeaway, 'id' | 'timestamp'>) => studentStore.getState().addTakeaway(data),\n    [studentStore]\n  );\n\n  const removeTakeaway = useCallback(\n    (id: string) => studentStore.getState().removeTakeaway(id),\n    [studentStore]\n  );\n\n  const markPageVisited = useCallback(\n    (pageNumber: number) => studentStore.getState().markPageVisited(pageNumber),\n    [studentStore]\n  );\n\n  // ============================================================================\n  // Agent API Factory\n  // ============================================================================\n\n  const getAgentAPI = useCallback((): AgentAPI => {\n    return {\n      focusRegion: (region: Omit<FocusedRegion, 'id'>) => {\n        return agentStore.getState().addFocusedRegion(region);\n      },\n      clearFocusedRegion: (id?: string) => {\n        if (id) {\n          agentStore.getState().removeFocusedRegion(id);\n        } else {\n          agentStore.getState().clearAllFocusedRegions();\n        }\n      },\n      addTakeaway: (pageNumber: number, summary: string, metadata?: Record<string, unknown>) => {\n        return studentStore.getState().addTakeaway({\n          pageNumber,\n          summary,\n          source: 'agent',\n          metadata,\n        });\n      },\n      setAgentContext: (context: Partial<AgentContext>) => {\n        agentStore.getState().setAgentContext(context);\n      },\n      addAgentHighlight: (params: AgentHighlightParams) => {\n        const highlight = annotationStore.getState().addHighlight({\n          pageNumber: params.pageNumber,\n          rects: params.rects,\n          text: params.text,\n          color: params.color ?? 'blue',\n          comment: params.comment,\n          source: 'agent',\n        });\n        return highlight.id;\n      },\n      goToPage: (pageNumber: number) => {\n        viewerStore.getState().goToPage(pageNumber);\n      },\n      getCurrentPage: () => viewerStore.getState().currentPage,\n      getAgentContext: () => agentStore.getState().currentContext,\n    };\n  }, [agentStore, studentStore, annotationStore, viewerStore]);\n\n  // ============================================================================\n  // Return API\n  // ============================================================================\n\n  return useMemo(\n    () => ({\n      // Document state\n      document,\n      numPages,\n      isLoading,\n      error,\n\n      // Navigation\n      currentPage,\n      goToPage,\n      nextPage,\n      previousPage,\n\n      // Zoom\n      scale,\n      setScale,\n      zoomIn,\n      zoomOut,\n      fitToWidth,\n      fitToPage,\n\n      // Rotation\n      rotation,\n      rotateClockwise,\n      rotateCounterClockwise,\n\n      // Theme & UI\n      theme,\n      setTheme,\n      viewMode,\n      setViewMode,\n      sidebarOpen,\n      toggleSidebar,\n      sidebarPanel,\n      setSidebarPanel,\n      isFullscreen,\n      setFullscreen,\n\n      // Highlights\n      highlights,\n      selectedHighlightId,\n      activeHighlightColor,\n      isHighlightMode,\n      addHighlight,\n      removeHighlight,\n      setActiveHighlightColor,\n      setHighlightMode,\n\n      // Annotations\n      annotations,\n\n      // Search\n      searchQuery,\n      searchResults,\n      currentSearchResult,\n      isSearching,\n      search,\n      clearSearch,\n      nextSearchResult,\n      previousSearchResult,\n\n      // Agent Context (Student Mode)\n      agentContext,\n      setAgentContext,\n      clearAgentContext,\n      focusedRegions,\n      focusRegion,\n      clearFocusedRegion,\n      clearAllFocusedRegions,\n      getAgentAPI,\n\n      // Bookmarks (Student Mode)\n      bookmarks,\n      addBookmark,\n      updateBookmark,\n      removeBookmark,\n\n      // Quick Notes (Student Mode)\n      quickNotes,\n      addQuickNote,\n      updateQuickNote,\n      removeQuickNote,\n\n      // Takeaways (Student Mode)\n      takeaways,\n      addTakeaway,\n      removeTakeaway,\n\n      // Progress (Student Mode)\n      visitedPages,\n      progress,\n      markPageVisited,\n    }),\n    [\n      document,\n      numPages,\n      isLoading,\n      error,\n      currentPage,\n      goToPage,\n      nextPage,\n      previousPage,\n      scale,\n      setScale,\n      zoomIn,\n      zoomOut,\n      fitToWidth,\n      fitToPage,\n      rotation,\n      rotateClockwise,\n      rotateCounterClockwise,\n      theme,\n      setTheme,\n      viewMode,\n      setViewMode,\n      sidebarOpen,\n      toggleSidebar,\n      sidebarPanel,\n      setSidebarPanel,\n      isFullscreen,\n      setFullscreen,\n      highlights,\n      selectedHighlightId,\n      activeHighlightColor,\n      isHighlightMode,\n      addHighlight,\n      removeHighlight,\n      setActiveHighlightColor,\n      setHighlightMode,\n      annotations,\n      searchQuery,\n      searchResults,\n      currentSearchResult,\n      isSearching,\n      search,\n      clearSearch,\n      nextSearchResult,\n      previousSearchResult,\n      agentContext,\n      setAgentContext,\n      clearAgentContext,\n      focusedRegions,\n      focusRegion,\n      clearFocusedRegion,\n      clearAllFocusedRegions,\n      getAgentAPI,\n      bookmarks,\n      addBookmark,\n      updateBookmark,\n      removeBookmark,\n      quickNotes,\n      addQuickNote,\n      updateQuickNote,\n      removeQuickNote,\n      takeaways,\n      addTakeaway,\n      removeTakeaway,\n      visitedPages,\n      progress,\n      markPageVisited,\n    ]\n  );\n}\n","import { useCallback, useEffect } from 'react';\nimport { useViewerStore, usePDFViewerStores } from './PDFViewerContext';\n\nexport interface UsePageNavigationOptions {\n  enableKeyboardNavigation?: boolean;\n}\n\n/**\n * Hook for page navigation functionality.\n */\nexport function usePageNavigation(options: UsePageNavigationOptions = {}) {\n  const { enableKeyboardNavigation = true } = options;\n  const { viewerStore } = usePDFViewerStores();\n\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const numPages = useViewerStore((s) => s.numPages);\n\n  const goToPage = useCallback(\n    (page: number) => viewerStore.getState().goToPage(page),\n    [viewerStore]\n  );\n\n  const nextPage = useCallback(\n    () => viewerStore.getState().nextPage(),\n    [viewerStore]\n  );\n\n  const previousPage = useCallback(\n    () => viewerStore.getState().previousPage(),\n    [viewerStore]\n  );\n\n  const goToFirstPage = useCallback(\n    () => viewerStore.getState().goToPage(1),\n    [viewerStore]\n  );\n\n  const goToLastPage = useCallback(\n    () => {\n      const { numPages } = viewerStore.getState();\n      viewerStore.getState().goToPage(numPages);\n    },\n    [viewerStore]\n  );\n\n  // Keyboard navigation\n  useEffect(() => {\n    if (!enableKeyboardNavigation) return;\n\n    const handleKeyDown = (e: KeyboardEvent) => {\n      // Don't handle if user is typing in an input\n      if (\n        e.target instanceof HTMLInputElement ||\n        e.target instanceof HTMLTextAreaElement\n      ) {\n        return;\n      }\n\n      switch (e.key) {\n        case 'ArrowRight':\n        case 'PageDown':\n          e.preventDefault();\n          nextPage();\n          break;\n        case 'ArrowLeft':\n        case 'PageUp':\n          e.preventDefault();\n          previousPage();\n          break;\n        case 'Home':\n          e.preventDefault();\n          goToFirstPage();\n          break;\n        case 'End':\n          e.preventDefault();\n          goToLastPage();\n          break;\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [enableKeyboardNavigation, nextPage, previousPage, goToFirstPage, goToLastPage]);\n\n  return {\n    currentPage,\n    numPages,\n    goToPage,\n    nextPage,\n    previousPage,\n    goToFirstPage,\n    goToLastPage,\n    canGoNext: currentPage < numPages,\n    canGoPrevious: currentPage > 1,\n  };\n}\n","import { useCallback, useEffect, useRef } from 'react';\nimport { useViewerStore, usePDFViewerStores } from './PDFViewerContext';\n\nexport interface UseZoomOptions {\n  enableWheelZoom?: boolean;\n  minScale?: number;\n  maxScale?: number;\n}\n\n/**\n * Hook for zoom functionality.\n */\nexport function useZoom(options: UseZoomOptions = {}) {\n  const { enableWheelZoom = true, minScale = 0.1, maxScale = 10 } = options;\n  const { viewerStore } = usePDFViewerStores();\n  const containerRef = useRef<HTMLElement | null>(null);\n\n  const scale = useViewerStore((s) => s.scale);\n\n  const setScale = useCallback(\n    (newScale: number) => {\n      const clamped = Math.max(minScale, Math.min(maxScale, newScale));\n      viewerStore.getState().setScale(clamped);\n    },\n    [viewerStore, minScale, maxScale]\n  );\n\n  const zoomIn = useCallback(\n    () => viewerStore.getState().zoomIn(),\n    [viewerStore]\n  );\n\n  const zoomOut = useCallback(\n    () => viewerStore.getState().zoomOut(),\n    [viewerStore]\n  );\n\n  const fitToWidth = useCallback(\n    () => viewerStore.getState().fitToWidth(),\n    [viewerStore]\n  );\n\n  const fitToPage = useCallback(\n    () => viewerStore.getState().fitToPage(),\n    [viewerStore]\n  );\n\n  const resetZoom = useCallback(\n    () => viewerStore.getState().setScale(1),\n    [viewerStore]\n  );\n\n  // Wheel zoom handler\n  useEffect(() => {\n    if (!enableWheelZoom) return;\n\n    const handleWheel = (e: Event) => {\n      const wheelEvent = e as WheelEvent;\n      // Only zoom when Ctrl/Cmd is pressed\n      if (!wheelEvent.ctrlKey && !wheelEvent.metaKey) return;\n\n      e.preventDefault();\n\n      const delta = wheelEvent.deltaY > 0 ? -0.1 : 0.1;\n      const newScale = scale + delta;\n      setScale(newScale);\n    };\n\n    const container = containerRef.current || document;\n    container.addEventListener('wheel', handleWheel, { passive: false });\n\n    return () => {\n      container.removeEventListener('wheel', handleWheel);\n    };\n  }, [enableWheelZoom, scale, setScale]);\n\n  // Keyboard zoom\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      // Don't handle if user is typing in an input\n      if (\n        e.target instanceof HTMLInputElement ||\n        e.target instanceof HTMLTextAreaElement\n      ) {\n        return;\n      }\n\n      if (e.ctrlKey || e.metaKey) {\n        switch (e.key) {\n          case '=':\n          case '+':\n            e.preventDefault();\n            zoomIn();\n            break;\n          case '-':\n            e.preventDefault();\n            zoomOut();\n            break;\n          case '0':\n            e.preventDefault();\n            resetZoom();\n            break;\n        }\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [zoomIn, zoomOut, resetZoom]);\n\n  return {\n    scale,\n    setScale,\n    zoomIn,\n    zoomOut,\n    fitToWidth,\n    fitToPage,\n    resetZoom,\n    setContainerRef: (el: HTMLElement | null) => {\n      containerRef.current = el;\n    },\n    scalePercentage: Math.round(scale * 100),\n  };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { TextSelection } from '../types';\n\nexport interface UseTextSelectionOptions {\n  onSelect?: (selection: TextSelection) => void;\n  onCopy?: (text: string) => void;\n}\n\n/**\n * Hook for handling text selection in the PDF viewer.\n */\nexport function useTextSelection(options: UseTextSelectionOptions = {}) {\n  const { onSelect, onCopy } = options;\n  const [selection, setSelection] = useState<TextSelection | null>(null);\n  const [isSelecting, setIsSelecting] = useState(false);\n\n  const handleSelectionChange = useCallback(() => {\n    const windowSelection = window.getSelection();\n\n    if (!windowSelection || windowSelection.isCollapsed) {\n      setSelection(null);\n      return;\n    }\n\n    const text = windowSelection.toString().trim();\n    if (!text) {\n      setSelection(null);\n      return;\n    }\n\n    // Find the page number from the selection's container\n    const anchorNode = windowSelection.anchorNode;\n    let pageElement = anchorNode?.parentElement;\n\n    while (pageElement && !pageElement.dataset.pageNumber) {\n      pageElement = pageElement.parentElement;\n    }\n\n    const pageNumber = pageElement ? parseInt(pageElement.dataset.pageNumber || '1', 10) : 1;\n\n    // Get bounding rectangles\n    const range = windowSelection.getRangeAt(0);\n    const rects = Array.from(range.getClientRects());\n\n    const newSelection: TextSelection = {\n      text,\n      pageNumber,\n      rects,\n    };\n\n    setSelection(newSelection);\n    onSelect?.(newSelection);\n  }, [onSelect]);\n\n  const clearSelection = useCallback(() => {\n    window.getSelection()?.removeAllRanges();\n    setSelection(null);\n  }, []);\n\n  const copySelection = useCallback(() => {\n    if (selection?.text) {\n      navigator.clipboard.writeText(selection.text).then(() => {\n        onCopy?.(selection.text);\n      });\n    }\n  }, [selection, onCopy]);\n\n  // Listen for selection changes\n  useEffect(() => {\n    const handleMouseUp = () => {\n      setIsSelecting(false);\n      handleSelectionChange();\n    };\n\n    const handleMouseDown = () => {\n      setIsSelecting(true);\n    };\n\n    document.addEventListener('mouseup', handleMouseUp);\n    document.addEventListener('mousedown', handleMouseDown);\n    document.addEventListener('selectionchange', handleSelectionChange);\n\n    return () => {\n      document.removeEventListener('mouseup', handleMouseUp);\n      document.removeEventListener('mousedown', handleMouseDown);\n      document.removeEventListener('selectionchange', handleSelectionChange);\n    };\n  }, [handleSelectionChange]);\n\n  // Handle Ctrl+C for copy\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if ((e.ctrlKey || e.metaKey) && e.key === 'c' && selection) {\n        // Let the default copy behavior work, but also trigger our callback\n        onCopy?.(selection.text);\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [selection, onCopy]);\n\n  return {\n    selection,\n    isSelecting,\n    clearSelection,\n    copySelection,\n    hasSelection: selection !== null && selection.text.length > 0,\n  };\n}\n","import { useCallback, useRef } from 'react';\nimport { useAnnotationStore } from './PDFViewerContext';\nimport type { TextSelection, HighlightRect, HighlightColor, Highlight } from '../types';\n\nexport interface UseHighlightsOptions {\n  /** Callback when a highlight is created */\n  onHighlightCreate?: (highlight: Highlight) => void;\n  /** Callback when a highlight is updated */\n  onHighlightUpdate?: (highlight: Highlight) => void;\n  /** Callback when a highlight is deleted */\n  onHighlightDelete?: (id: string) => void;\n}\n\nexport interface UseHighlightsReturn {\n  /** Create a highlight from the current text selection */\n  createHighlightFromSelection: (\n    selection: TextSelection,\n    pageElement: HTMLElement,\n    scale: number,\n    color?: HighlightColor\n  ) => Highlight | null;\n  /**\n   * Add a highlight programmatically with coordinates.\n   * Coordinates should be in PDF points (not scaled).\n   *\n   * @example\n   * ```tsx\n   * addHighlight({\n   *   pageNumber: 1,\n   *   rects: [{ x: 100, y: 200, width: 150, height: 20 }],\n   *   text: \"Highlighted text\",\n   *   color: \"yellow\"\n   * });\n   * ```\n   */\n  addHighlight: (highlight: {\n    pageNumber: number;\n    rects: HighlightRect[];\n    text: string;\n    color?: HighlightColor;\n    comment?: string;\n  }) => Highlight;\n  /** Update an existing highlight */\n  updateHighlight: (id: string, updates: Partial<Pick<Highlight, 'color' | 'comment'>>) => void;\n  /** Delete a highlight */\n  deleteHighlight: (id: string) => void;\n  /** Get highlights for a specific page */\n  highlightsForPage: (pageNumber: number) => Highlight[];\n  /** Get all highlights */\n  allHighlights: Highlight[];\n  /** Get the currently selected highlight */\n  selectedHighlight: Highlight | null;\n  /** Select a highlight by ID */\n  selectHighlight: (id: string | null) => void;\n  /** Get the active highlight color */\n  activeColor: HighlightColor;\n  /** Set the active highlight color */\n  setActiveColor: (color: HighlightColor) => void;\n}\n\n/**\n * Convert DOMRect from browser selection to HighlightRect for storage.\n * Normalizes coordinates relative to page container and adjusts for scale.\n */\nfunction domRectToHighlightRect(\n  domRect: DOMRect,\n  pageElement: HTMLElement,\n  scale: number\n): HighlightRect {\n  const pageRect = pageElement.getBoundingClientRect();\n  return {\n    x: (domRect.left - pageRect.left) / scale,\n    y: (domRect.top - pageRect.top) / scale,\n    width: domRect.width / scale,\n    height: domRect.height / scale,\n  };\n}\n\n/**\n * Merge overlapping or adjacent rects to reduce the number of highlight rects.\n * This helps when selections span multiple lines.\n */\nfunction mergeRects(rects: HighlightRect[]): HighlightRect[] {\n  if (rects.length <= 1) return rects;\n\n  // Sort by y position, then x position\n  const sorted = [...rects].sort((a, b) => {\n    const yDiff = a.y - b.y;\n    if (Math.abs(yDiff) < 2) return a.x - b.x;\n    return yDiff;\n  });\n\n  const merged: HighlightRect[] = [];\n  let current = sorted[0];\n\n  for (let i = 1; i < sorted.length; i++) {\n    const next = sorted[i];\n    const sameRow = Math.abs(current.y - next.y) < 2 && Math.abs(current.height - next.height) < 2;\n    const overlapsOrAdjacent = current.x + current.width >= next.x - 2;\n\n    if (sameRow && overlapsOrAdjacent) {\n      // Merge the rects\n      const right = Math.max(current.x + current.width, next.x + next.width);\n      current = {\n        x: Math.min(current.x, next.x),\n        y: Math.min(current.y, next.y),\n        width: right - Math.min(current.x, next.x),\n        height: Math.max(current.height, next.height),\n      };\n    } else {\n      merged.push(current);\n      current = next;\n    }\n  }\n  merged.push(current);\n\n  return merged;\n}\n\n/**\n * Hook for creating and managing highlights from text selections.\n */\nexport function useHighlights(options: UseHighlightsOptions = {}): UseHighlightsReturn {\n  const { onHighlightCreate, onHighlightUpdate, onHighlightDelete } = options;\n\n  // Store refs for callbacks to avoid stale closures\n  const callbacksRef = useRef({ onHighlightCreate, onHighlightUpdate, onHighlightDelete });\n  callbacksRef.current = { onHighlightCreate, onHighlightUpdate, onHighlightDelete };\n\n  // Get store actions\n  const addHighlightStore = useAnnotationStore((s) => s.addHighlight);\n  const updateHighlightStore = useAnnotationStore((s) => s.updateHighlight);\n  const removeHighlight = useAnnotationStore((s) => s.removeHighlight);\n  const getHighlightsByPage = useAnnotationStore((s) => s.getHighlightsByPage);\n  const highlights = useAnnotationStore((s) => s.highlights);\n  const selectedHighlightId = useAnnotationStore((s) => s.selectedHighlightId);\n  const selectHighlightStore = useAnnotationStore((s) => s.selectHighlight);\n  const activeHighlightColor = useAnnotationStore((s) => s.activeHighlightColor);\n  const setActiveHighlightColor = useAnnotationStore((s) => s.setActiveHighlightColor);\n\n  const createHighlightFromSelection = useCallback(\n    (\n      selection: TextSelection,\n      pageElement: HTMLElement,\n      scale: number,\n      color?: HighlightColor\n    ): Highlight | null => {\n      if (!selection.text || selection.rects.length === 0) {\n        return null;\n      }\n\n      // Convert DOMRects to HighlightRects\n      const highlightRects = selection.rects.map((domRect) =>\n        domRectToHighlightRect(domRect, pageElement, scale)\n      );\n\n      // Merge adjacent rects\n      const mergedRects = mergeRects(highlightRects);\n\n      // Filter out any invalid rects\n      const validRects = mergedRects.filter(\n        (rect) => rect.width > 0 && rect.height > 0\n      );\n\n      if (validRects.length === 0) {\n        return null;\n      }\n\n      // Create the highlight\n      const highlight = addHighlightStore({\n        pageNumber: selection.pageNumber,\n        rects: validRects,\n        color: color ?? activeHighlightColor,\n        text: selection.text,\n      });\n\n      callbacksRef.current.onHighlightCreate?.(highlight);\n      return highlight;\n    },\n    [addHighlightStore, activeHighlightColor]\n  );\n\n  // Programmatic highlight creation with coordinates\n  const addHighlightWithCoords = useCallback(\n    (data: {\n      pageNumber: number;\n      rects: HighlightRect[];\n      text: string;\n      color?: HighlightColor;\n      comment?: string;\n    }): Highlight => {\n      const highlight = addHighlightStore({\n        pageNumber: data.pageNumber,\n        rects: data.rects,\n        text: data.text,\n        color: data.color ?? activeHighlightColor,\n        comment: data.comment,\n      });\n\n      callbacksRef.current.onHighlightCreate?.(highlight);\n      return highlight;\n    },\n    [addHighlightStore, activeHighlightColor]\n  );\n\n  const updateHighlight = useCallback(\n    (id: string, updates: Partial<Pick<Highlight, 'color' | 'comment'>>) => {\n      updateHighlightStore(id, updates);\n      const updated = highlights.find((h) => h.id === id);\n      if (updated) {\n        callbacksRef.current.onHighlightUpdate?.({ ...updated, ...updates });\n      }\n    },\n    [updateHighlightStore, highlights]\n  );\n\n  const deleteHighlight = useCallback(\n    (id: string) => {\n      removeHighlight(id);\n      callbacksRef.current.onHighlightDelete?.(id);\n    },\n    [removeHighlight]\n  );\n\n  const highlightsForPage = useCallback(\n    (pageNumber: number) => {\n      return getHighlightsByPage(pageNumber);\n    },\n    [getHighlightsByPage]\n  );\n\n  const selectedHighlight = selectedHighlightId\n    ? highlights.find((h) => h.id === selectedHighlightId) ?? null\n    : null;\n\n  return {\n    createHighlightFromSelection,\n    addHighlight: addHighlightWithCoords,\n    updateHighlight,\n    deleteHighlight,\n    highlightsForPage,\n    allHighlights: highlights,\n    selectedHighlight,\n    selectHighlight: selectHighlightStore,\n    activeColor: activeHighlightColor,\n    setActiveColor: setActiveHighlightColor,\n  };\n}\n","import { useCallback, useMemo } from 'react';\nimport { useAnnotationStore } from './PDFViewerContext';\nimport type { Annotation, NoteAnnotation, ShapeAnnotation } from '../types';\nimport type { AnnotationTool, ShapeType } from '../store/annotation-store';\n\nexport interface UseAnnotationsOptions {\n  onAnnotationCreate?: (annotation: Annotation) => void;\n  onAnnotationUpdate?: (annotation: Annotation) => void;\n  onAnnotationDelete?: (id: string) => void;\n}\n\nexport interface UseAnnotationsReturn {\n  // Annotations state\n  annotations: Annotation[];\n  selectedAnnotation: Annotation | undefined;\n  selectedAnnotationId: string | null;\n\n  // Tool state\n  activeTool: AnnotationTool;\n  activeShapeType: ShapeType;\n  drawingColor: string;\n  drawingStrokeWidth: number;\n  isDrawing: boolean;\n  currentDrawingPath: { points: { x: number; y: number }[] } | null;\n  currentDrawingPage: number | null;\n\n  // Tool actions\n  setActiveTool: (tool: AnnotationTool) => void;\n  setActiveShapeType: (shapeType: ShapeType) => void;\n  setDrawingColor: (color: string) => void;\n  setDrawingStrokeWidth: (width: number) => void;\n\n  // Note actions\n  createNote: (pageNumber: number, x: number, y: number, content?: string, color?: string) => NoteAnnotation;\n  updateNote: (id: string, updates: Partial<NoteAnnotation>) => void;\n\n  // Drawing actions\n  startDrawing: (pageNumber: number, point: { x: number; y: number }) => void;\n  continueDrawing: (point: { x: number; y: number }) => void;\n  finishDrawing: () => Annotation | null;\n  cancelDrawing: () => void;\n\n  // Shape actions\n  /**\n   * Create a shape annotation programmatically.\n   * Coordinates should be in PDF points (not scaled).\n   *\n   * @example\n   * ```tsx\n   * // Create a red rectangle box annotation\n   * createShape({\n   *   pageNumber: 1,\n   *   shapeType: 'rect',\n   *   x: 100,\n   *   y: 200,\n   *   width: 150,\n   *   height: 80,\n   *   color: '#ef4444',\n   *   strokeWidth: 2\n   * });\n   * ```\n   */\n  createShape: (options: {\n    pageNumber: number;\n    shapeType: ShapeType;\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n    color?: string;\n    strokeWidth?: number;\n  }) => ShapeAnnotation;\n  updateShape: (id: string, updates: Partial<ShapeAnnotation>) => void;\n\n  // General annotation actions\n  selectAnnotation: (id: string | null) => void;\n  deleteAnnotation: (id: string) => void;\n  getAnnotationsByPage: (pageNumber: number) => Annotation[];\n\n  // Export/Import\n  exportAnnotations: () => string;\n  importAnnotations: (json: string) => void;\n}\n\nexport function useAnnotations(options: UseAnnotationsOptions = {}): UseAnnotationsReturn {\n  const { onAnnotationCreate, onAnnotationUpdate, onAnnotationDelete } = options;\n\n  // Store selectors\n  const annotations = useAnnotationStore((s) => s.annotations);\n  const selectedAnnotationId = useAnnotationStore((s) => s.selectedAnnotationId);\n  const activeTool = useAnnotationStore((s) => s.activeAnnotationTool);\n  const activeShapeType = useAnnotationStore((s) => s.activeShapeType);\n  const drawingColor = useAnnotationStore((s) => s.drawingColor);\n  const drawingStrokeWidth = useAnnotationStore((s) => s.drawingStrokeWidth);\n  const currentDrawingPath = useAnnotationStore((s) => s.currentDrawingPath);\n  const currentDrawingPage = useAnnotationStore((s) => s.currentDrawingPage);\n\n  // Store actions\n  const addAnnotation = useAnnotationStore((s) => s.addAnnotation);\n  const updateAnnotation = useAnnotationStore((s) => s.updateAnnotation);\n  const removeAnnotation = useAnnotationStore((s) => s.removeAnnotation);\n  const selectAnnotationAction = useAnnotationStore((s) => s.selectAnnotation);\n  const getAnnotationsByPageAction = useAnnotationStore((s) => s.getAnnotationsByPage);\n  const setActiveAnnotationTool = useAnnotationStore((s) => s.setActiveAnnotationTool);\n  const setActiveShapeTypeAction = useAnnotationStore((s) => s.setActiveShapeType);\n  const setDrawingColorAction = useAnnotationStore((s) => s.setDrawingColor);\n  const setDrawingStrokeWidthAction = useAnnotationStore((s) => s.setDrawingStrokeWidth);\n  const startDrawingAction = useAnnotationStore((s) => s.startDrawing);\n  const addDrawingPoint = useAnnotationStore((s) => s.addDrawingPoint);\n  const finishDrawingAction = useAnnotationStore((s) => s.finishDrawing);\n  const cancelDrawingAction = useAnnotationStore((s) => s.cancelDrawing);\n  const exportAnnotationsAction = useAnnotationStore((s) => s.exportAnnotations);\n  const importAnnotationsAction = useAnnotationStore((s) => s.importAnnotations);\n\n  // Derived state\n  const selectedAnnotation = useMemo(() => {\n    return annotations.find((a) => a.id === selectedAnnotationId);\n  }, [annotations, selectedAnnotationId]);\n\n  const isDrawing = currentDrawingPath !== null;\n\n  // Tool actions\n  const setActiveTool = useCallback((tool: AnnotationTool) => {\n    setActiveAnnotationTool(tool);\n  }, [setActiveAnnotationTool]);\n\n  const setActiveShapeType = useCallback((shapeType: ShapeType) => {\n    setActiveShapeTypeAction(shapeType);\n  }, [setActiveShapeTypeAction]);\n\n  const setDrawingColor = useCallback((color: string) => {\n    setDrawingColorAction(color);\n  }, [setDrawingColorAction]);\n\n  const setDrawingStrokeWidth = useCallback((width: number) => {\n    setDrawingStrokeWidthAction(width);\n  }, [setDrawingStrokeWidthAction]);\n\n  // Note actions\n  const createNote = useCallback((\n    pageNumber: number,\n    x: number,\n    y: number,\n    content: string = '',\n    color: string = '#fef08a'\n  ): NoteAnnotation => {\n    const noteData: Omit<NoteAnnotation, 'id' | 'createdAt' | 'updatedAt'> = {\n      type: 'note',\n      pageNumber,\n      x,\n      y,\n      content,\n      color,\n    };\n    const note = addAnnotation(noteData as Omit<Annotation, 'id' | 'createdAt' | 'updatedAt'>) as NoteAnnotation;\n\n    onAnnotationCreate?.(note);\n    return note;\n  }, [addAnnotation, onAnnotationCreate]);\n\n  const updateNote = useCallback((id: string, updates: Partial<NoteAnnotation>) => {\n    updateAnnotation(id, updates);\n    const updated = annotations.find((a) => a.id === id);\n    if (updated) {\n      onAnnotationUpdate?.(updated);\n    }\n  }, [updateAnnotation, annotations, onAnnotationUpdate]);\n\n  // Drawing actions\n  const startDrawing = useCallback((pageNumber: number, point: { x: number; y: number }) => {\n    startDrawingAction(pageNumber, point);\n  }, [startDrawingAction]);\n\n  const continueDrawing = useCallback((point: { x: number; y: number }) => {\n    addDrawingPoint(point);\n  }, [addDrawingPoint]);\n\n  const finishDrawing = useCallback((): Annotation | null => {\n    const annotation = finishDrawingAction();\n    if (annotation) {\n      onAnnotationCreate?.(annotation);\n    }\n    return annotation;\n  }, [finishDrawingAction, onAnnotationCreate]);\n\n  const cancelDrawing = useCallback(() => {\n    cancelDrawingAction();\n  }, [cancelDrawingAction]);\n\n  // Shape actions\n  const createShape = useCallback((options: {\n    pageNumber: number;\n    shapeType: ShapeType;\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n    color?: string;\n    strokeWidth?: number;\n  }): ShapeAnnotation => {\n    const shapeData: Omit<ShapeAnnotation, 'id' | 'createdAt' | 'updatedAt'> = {\n      type: 'shape',\n      pageNumber: options.pageNumber,\n      shapeType: options.shapeType,\n      x: options.x,\n      y: options.y,\n      width: options.width,\n      height: options.height,\n      color: options.color ?? drawingColor,\n      strokeWidth: options.strokeWidth ?? drawingStrokeWidth,\n    };\n    const shape = addAnnotation(shapeData as Omit<Annotation, 'id' | 'createdAt' | 'updatedAt'>) as ShapeAnnotation;\n\n    onAnnotationCreate?.(shape);\n    return shape;\n  }, [addAnnotation, drawingColor, drawingStrokeWidth, onAnnotationCreate]);\n\n  const updateShape = useCallback((id: string, updates: Partial<ShapeAnnotation>) => {\n    updateAnnotation(id, updates);\n    const updated = annotations.find((a) => a.id === id);\n    if (updated) {\n      onAnnotationUpdate?.(updated);\n    }\n  }, [updateAnnotation, annotations, onAnnotationUpdate]);\n\n  // General annotation actions\n  const selectAnnotation = useCallback((id: string | null) => {\n    selectAnnotationAction(id);\n  }, [selectAnnotationAction]);\n\n  const deleteAnnotation = useCallback((id: string) => {\n    removeAnnotation(id);\n    onAnnotationDelete?.(id);\n  }, [removeAnnotation, onAnnotationDelete]);\n\n  const getAnnotationsByPage = useCallback((pageNumber: number) => {\n    return getAnnotationsByPageAction(pageNumber);\n  }, [getAnnotationsByPageAction]);\n\n  // Export/Import\n  const exportAnnotations = useCallback(() => {\n    return exportAnnotationsAction();\n  }, [exportAnnotationsAction]);\n\n  const importAnnotations = useCallback((json: string) => {\n    importAnnotationsAction(json);\n  }, [importAnnotationsAction]);\n\n  return {\n    // State\n    annotations,\n    selectedAnnotation,\n    selectedAnnotationId,\n    activeTool,\n    activeShapeType,\n    drawingColor,\n    drawingStrokeWidth,\n    isDrawing,\n    currentDrawingPath,\n    currentDrawingPage,\n\n    // Tool actions\n    setActiveTool,\n    setActiveShapeType,\n    setDrawingColor,\n    setDrawingStrokeWidth,\n\n    // Note actions\n    createNote,\n    updateNote,\n\n    // Drawing actions\n    startDrawing,\n    continueDrawing,\n    finishDrawing,\n    cancelDrawing,\n\n    // Shape actions\n    createShape,\n    updateShape,\n\n    // General actions\n    selectAnnotation,\n    deleteAnnotation,\n    getAnnotationsByPage,\n\n    // Export/Import\n    exportAnnotations,\n    importAnnotations,\n  };\n}\n","import { useRef, useCallback, useEffect } from 'react';\n\nexport interface UseTouchGesturesOptions {\n  /** Callback when pinch-to-zoom is detected */\n  onPinchZoom?: (scale: number, center: { x: number; y: number }) => void;\n  /** Callback when swipe left is detected */\n  onSwipeLeft?: () => void;\n  /** Callback when swipe right is detected */\n  onSwipeRight?: () => void;\n  /** Callback when long press is detected */\n  onLongPress?: (position: { x: number; y: number }) => void;\n  /** Callback when double tap is detected */\n  onDoubleTap?: (position: { x: number; y: number }) => void;\n  /** Minimum swipe distance in pixels */\n  swipeThreshold?: number;\n  /** Long press duration in milliseconds */\n  longPressDuration?: number;\n  /** Double tap max interval in milliseconds */\n  doubleTapInterval?: number;\n  /** Whether gestures are enabled */\n  enabled?: boolean;\n}\n\ninterface TouchState {\n  startX: number;\n  startY: number;\n  startTime: number;\n  startDistance: number;\n  currentScale: number;\n  isPinching: boolean;\n  longPressTimer: number | null;\n  lastTapTime: number;\n}\n\nfunction getDistance(touch1: Touch, touch2: Touch): number {\n  const dx = touch1.clientX - touch2.clientX;\n  const dy = touch1.clientY - touch2.clientY;\n  return Math.sqrt(dx * dx + dy * dy);\n}\n\nfunction getCenter(touch1: Touch, touch2: Touch): { x: number; y: number } {\n  return {\n    x: (touch1.clientX + touch2.clientX) / 2,\n    y: (touch1.clientY + touch2.clientY) / 2,\n  };\n}\n\nexport function useTouchGestures<T extends HTMLElement = HTMLElement>(\n  options: UseTouchGesturesOptions = {}\n) {\n  const {\n    onPinchZoom,\n    onSwipeLeft,\n    onSwipeRight,\n    onLongPress,\n    onDoubleTap,\n    swipeThreshold = 50,\n    longPressDuration = 500,\n    doubleTapInterval = 300,\n    enabled = true,\n  } = options;\n\n  const elementRef = useRef<T | null>(null);\n  const stateRef = useRef<TouchState>({\n    startX: 0,\n    startY: 0,\n    startTime: 0,\n    startDistance: 0,\n    currentScale: 1,\n    isPinching: false,\n    longPressTimer: null,\n    lastTapTime: 0,\n  });\n\n  const clearLongPressTimer = useCallback(() => {\n    if (stateRef.current.longPressTimer !== null) {\n      clearTimeout(stateRef.current.longPressTimer);\n      stateRef.current.longPressTimer = null;\n    }\n  }, []);\n\n  const handleTouchStart = useCallback(\n    (e: TouchEvent) => {\n      if (!enabled) return;\n\n      const state = stateRef.current;\n      clearLongPressTimer();\n\n      if (e.touches.length === 1) {\n        const touch = e.touches[0];\n        state.startX = touch.clientX;\n        state.startY = touch.clientY;\n        state.startTime = Date.now();\n        state.isPinching = false;\n\n        // Set up long press detection\n        if (onLongPress) {\n          state.longPressTimer = window.setTimeout(() => {\n            onLongPress({ x: touch.clientX, y: touch.clientY });\n            state.longPressTimer = null;\n          }, longPressDuration);\n        }\n      } else if (e.touches.length === 2 && onPinchZoom) {\n        // Start pinch gesture\n        const touch1 = e.touches[0];\n        const touch2 = e.touches[1];\n        state.startDistance = getDistance(touch1, touch2);\n        state.currentScale = 1;\n        state.isPinching = true;\n        clearLongPressTimer();\n      }\n    },\n    [enabled, onLongPress, onPinchZoom, longPressDuration, clearLongPressTimer]\n  );\n\n  const handleTouchMove = useCallback(\n    (e: TouchEvent) => {\n      if (!enabled) return;\n\n      const state = stateRef.current;\n      clearLongPressTimer();\n\n      if (e.touches.length === 2 && state.isPinching && onPinchZoom) {\n        // Handle pinch zoom\n        const touch1 = e.touches[0];\n        const touch2 = e.touches[1];\n        const currentDistance = getDistance(touch1, touch2);\n        const center = getCenter(touch1, touch2);\n\n        if (state.startDistance > 0) {\n          const scale = currentDistance / state.startDistance;\n          state.currentScale = scale;\n          onPinchZoom(scale, center);\n        }\n      } else if (e.touches.length === 1) {\n        // Check if we've moved enough to cancel long press\n        const touch = e.touches[0];\n        const dx = Math.abs(touch.clientX - state.startX);\n        const dy = Math.abs(touch.clientY - state.startY);\n\n        if (dx > 10 || dy > 10) {\n          clearLongPressTimer();\n        }\n      }\n    },\n    [enabled, onPinchZoom, clearLongPressTimer]\n  );\n\n  const handleTouchEnd = useCallback(\n    (e: TouchEvent) => {\n      if (!enabled) return;\n\n      const state = stateRef.current;\n      clearLongPressTimer();\n\n      // Handle pinch end\n      if (state.isPinching) {\n        state.isPinching = false;\n        state.startDistance = 0;\n        return;\n      }\n\n      // Only process single touch end\n      if (e.changedTouches.length !== 1) return;\n\n      const touch = e.changedTouches[0];\n      const endTime = Date.now();\n      const duration = endTime - state.startTime;\n\n      // Calculate movement\n      const dx = touch.clientX - state.startX;\n      const dy = touch.clientY - state.startY;\n      const absDx = Math.abs(dx);\n      const absDy = Math.abs(dy);\n\n      // Check for double tap\n      if (onDoubleTap && duration < 300 && absDx < 20 && absDy < 20) {\n        const timeSinceLastTap = endTime - state.lastTapTime;\n        if (timeSinceLastTap < doubleTapInterval) {\n          onDoubleTap({ x: touch.clientX, y: touch.clientY });\n          state.lastTapTime = 0;\n          return;\n        }\n        state.lastTapTime = endTime;\n      }\n\n      // Check for swipe (quick horizontal movement)\n      if (duration < 300 && absDx > swipeThreshold && absDx > absDy * 2) {\n        if (dx > 0 && onSwipeRight) {\n          onSwipeRight();\n        } else if (dx < 0 && onSwipeLeft) {\n          onSwipeLeft();\n        }\n      }\n    },\n    [enabled, onSwipeLeft, onSwipeRight, onDoubleTap, swipeThreshold, doubleTapInterval, clearLongPressTimer]\n  );\n\n  const handleTouchCancel = useCallback(() => {\n    clearLongPressTimer();\n    stateRef.current.isPinching = false;\n  }, [clearLongPressTimer]);\n\n  // Attach event listeners\n  useEffect(() => {\n    const element = elementRef.current;\n    if (!element || !enabled) return;\n\n    element.addEventListener('touchstart', handleTouchStart, { passive: true });\n    element.addEventListener('touchmove', handleTouchMove, { passive: true });\n    element.addEventListener('touchend', handleTouchEnd, { passive: true });\n    element.addEventListener('touchcancel', handleTouchCancel, { passive: true });\n\n    return () => {\n      element.removeEventListener('touchstart', handleTouchStart);\n      element.removeEventListener('touchmove', handleTouchMove);\n      element.removeEventListener('touchend', handleTouchEnd);\n      element.removeEventListener('touchcancel', handleTouchCancel);\n      clearLongPressTimer();\n    };\n  }, [enabled, handleTouchStart, handleTouchMove, handleTouchEnd, handleTouchCancel, clearLongPressTimer]);\n\n  // Return ref to attach to element\n  const setRef = useCallback((element: T | null) => {\n    elementRef.current = element;\n  }, []);\n\n  return {\n    ref: setRef,\n    elementRef,\n  };\n}\n\n// Utility hook for detecting if device supports touch\nexport function useIsTouchDevice(): boolean {\n  if (typeof window === 'undefined') return false;\n  return 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n}\n\n// Utility hook for detecting if device is mobile\nexport function useIsMobile(): boolean {\n  if (typeof window === 'undefined') return false;\n  return window.matchMedia('(max-width: 640px)').matches;\n}\n","import type {\n  Plugin,\n  PluginAPI,\n  ToolbarItem,\n  SidebarPanelConfig,\n  ContextMenuItem,\n  ViewerState,\n  ViewerActions,\n} from '../types';\n\nexport interface PluginManagerOptions {\n  /** Callback when a plugin is registered */\n  onPluginRegistered?: (plugin: Plugin) => void;\n  /** Callback when a plugin is unregistered */\n  onPluginUnregistered?: (name: string) => void;\n  /** Callback when toolbar items change */\n  onToolbarItemsChanged?: (items: ToolbarItem[]) => void;\n  /** Callback when sidebar panels change */\n  onSidebarPanelsChanged?: (panels: SidebarPanelConfig[]) => void;\n  /** Callback when context menu items change */\n  onContextMenuItemsChanged?: (items: ContextMenuItem[]) => void;\n}\n\nexport class PluginManager {\n  private plugins: Map<string, Plugin> = new Map();\n  private toolbarItems: Map<string, ToolbarItem[]> = new Map();\n  private sidebarPanels: Map<string, SidebarPanelConfig[]> = new Map();\n  private contextMenuItems: Map<string, ContextMenuItem[]> = new Map();\n  private viewerStateGetter: (() => ViewerState & ViewerActions) | null = null;\n  private options: PluginManagerOptions;\n\n  constructor(options: PluginManagerOptions = {}) {\n    this.options = options;\n  }\n\n  /**\n   * Set the getter function for viewer state\n   */\n  setViewerStateGetter(getter: () => ViewerState & ViewerActions): void {\n    this.viewerStateGetter = getter;\n  }\n\n  /**\n   * Create the plugin API for a specific plugin\n   */\n  private createPluginAPI(pluginName: string): PluginAPI {\n    return {\n      viewer: this.viewerStateGetter?.() || ({} as ViewerState & ViewerActions),\n\n      registerToolbarItem: (item: ToolbarItem) => {\n        const items = this.toolbarItems.get(pluginName) || [];\n        items.push(item);\n        this.toolbarItems.set(pluginName, items);\n        this.notifyToolbarItemsChanged();\n      },\n\n      registerSidebarPanel: (panel: SidebarPanelConfig) => {\n        const panels = this.sidebarPanels.get(pluginName) || [];\n        panels.push(panel);\n        this.sidebarPanels.set(pluginName, panels);\n        this.notifySidebarPanelsChanged();\n      },\n\n      registerContextMenuItem: (item: ContextMenuItem) => {\n        const items = this.contextMenuItems.get(pluginName) || [];\n        items.push(item);\n        this.contextMenuItems.set(pluginName, items);\n        this.notifyContextMenuItemsChanged();\n      },\n    };\n  }\n\n  /**\n   * Register a plugin\n   */\n  async register(plugin: Plugin): Promise<void> {\n    if (this.plugins.has(plugin.name)) {\n      console.warn(`Plugin \"${plugin.name}\" is already registered. Unregister it first.`);\n      return;\n    }\n\n    this.plugins.set(plugin.name, plugin);\n\n    // Initialize the plugin if it has an initialize function\n    if (plugin.initialize) {\n      const api = this.createPluginAPI(plugin.name);\n      await plugin.initialize(api);\n    }\n\n    this.options.onPluginRegistered?.(plugin);\n  }\n\n  /**\n   * Unregister a plugin\n   */\n  async unregister(name: string): Promise<void> {\n    const plugin = this.plugins.get(name);\n    if (!plugin) {\n      console.warn(`Plugin \"${name}\" is not registered.`);\n      return;\n    }\n\n    // Destroy the plugin if it has a destroy function\n    if (plugin.destroy) {\n      await plugin.destroy();\n    }\n\n    // Remove all registered items from this plugin\n    this.toolbarItems.delete(name);\n    this.sidebarPanels.delete(name);\n    this.contextMenuItems.delete(name);\n\n    this.plugins.delete(name);\n\n    this.notifyToolbarItemsChanged();\n    this.notifySidebarPanelsChanged();\n    this.notifyContextMenuItemsChanged();\n\n    this.options.onPluginUnregistered?.(name);\n  }\n\n  /**\n   * Get a registered plugin by name\n   */\n  getPlugin(name: string): Plugin | undefined {\n    return this.plugins.get(name);\n  }\n\n  /**\n   * Get all registered plugins\n   */\n  getAllPlugins(): Plugin[] {\n    return Array.from(this.plugins.values());\n  }\n\n  /**\n   * Check if a plugin is registered\n   */\n  hasPlugin(name: string): boolean {\n    return this.plugins.has(name);\n  }\n\n  /**\n   * Get all toolbar items from all plugins\n   */\n  getToolbarItems(): ToolbarItem[] {\n    const allItems: ToolbarItem[] = [];\n    for (const items of this.toolbarItems.values()) {\n      allItems.push(...items);\n    }\n    // Sort by order if specified\n    return allItems.sort((a, b) => (a.order || 0) - (b.order || 0));\n  }\n\n  /**\n   * Get toolbar items by position\n   */\n  getToolbarItemsByPosition(position: 'left' | 'center' | 'right'): ToolbarItem[] {\n    return this.getToolbarItems().filter((item) => item.position === position);\n  }\n\n  /**\n   * Get all sidebar panels from all plugins\n   */\n  getSidebarPanels(): SidebarPanelConfig[] {\n    const allPanels: SidebarPanelConfig[] = [];\n    for (const panels of this.sidebarPanels.values()) {\n      allPanels.push(...panels);\n    }\n    return allPanels;\n  }\n\n  /**\n   * Get all context menu items from all plugins\n   */\n  getContextMenuItems(): ContextMenuItem[] {\n    const allItems: ContextMenuItem[] = [];\n    for (const items of this.contextMenuItems.values()) {\n      allItems.push(...items);\n    }\n    // Filter by condition if specified\n    return allItems.filter((item) => !item.condition || item.condition());\n  }\n\n  /**\n   * Destroy all plugins and clean up\n   */\n  async destroy(): Promise<void> {\n    const pluginNames = Array.from(this.plugins.keys());\n    for (const name of pluginNames) {\n      await this.unregister(name);\n    }\n  }\n\n  private notifyToolbarItemsChanged(): void {\n    this.options.onToolbarItemsChanged?.(this.getToolbarItems());\n  }\n\n  private notifySidebarPanelsChanged(): void {\n    this.options.onSidebarPanelsChanged?.(this.getSidebarPanels());\n  }\n\n  private notifyContextMenuItemsChanged(): void {\n    this.options.onContextMenuItemsChanged?.(this.getContextMenuItems());\n  }\n}\n\n// Create a default plugin manager instance\nlet defaultPluginManager: PluginManager | null = null;\n\nexport function getPluginManager(): PluginManager {\n  if (!defaultPluginManager) {\n    defaultPluginManager = new PluginManager();\n  }\n  return defaultPluginManager;\n}\n\nexport function createPluginManager(options?: PluginManagerOptions): PluginManager {\n  return new PluginManager(options);\n}\n","import { useRef, useEffect, useState, useCallback, useMemo } from 'react';\nimport {\n  PluginManager,\n  createPluginManager,\n  type PluginManagerOptions,\n} from '../plugins/PluginManager';\nimport type { Plugin, ToolbarItem, SidebarPanelConfig, ContextMenuItem } from '../types';\nimport { usePDFViewer } from './usePDFViewer';\n\nexport interface UsePluginsOptions extends PluginManagerOptions {\n  /** Initial plugins to register */\n  initialPlugins?: Plugin[];\n}\n\nexport interface UsePluginsReturn {\n  /** The plugin manager instance */\n  pluginManager: PluginManager;\n\n  /** All registered plugins */\n  plugins: Plugin[];\n\n  /** Toolbar items from plugins */\n  toolbarItems: ToolbarItem[];\n\n  /** Sidebar panels from plugins */\n  sidebarPanels: SidebarPanelConfig[];\n\n  /** Context menu items from plugins */\n  contextMenuItems: ContextMenuItem[];\n\n  /** Register a plugin */\n  registerPlugin: (plugin: Plugin) => Promise<void>;\n\n  /** Unregister a plugin by name */\n  unregisterPlugin: (name: string) => Promise<void>;\n\n  /** Check if a plugin is registered */\n  hasPlugin: (name: string) => boolean;\n}\n\nexport function usePlugins(options: UsePluginsOptions = {}): UsePluginsReturn {\n  const { initialPlugins, ...managerOptions } = options;\n\n  // Get viewer state/actions for the plugin API\n  const viewerState = usePDFViewer();\n\n  // State for plugin-registered items\n  const [plugins, setPlugins] = useState<Plugin[]>([]);\n  const [toolbarItems, setToolbarItems] = useState<ToolbarItem[]>([]);\n  const [sidebarPanels, setSidebarPanels] = useState<SidebarPanelConfig[]>([]);\n  const [contextMenuItems, setContextMenuItems] = useState<ContextMenuItem[]>([]);\n\n  // Create the plugin manager\n  const pluginManagerRef = useRef<PluginManager | null>(null);\n\n  const getPluginManager = useCallback(() => {\n    if (!pluginManagerRef.current) {\n      pluginManagerRef.current = createPluginManager({\n        ...managerOptions,\n        onPluginRegistered: (plugin) => {\n          setPlugins((prev) => [...prev, plugin]);\n          managerOptions.onPluginRegistered?.(plugin);\n        },\n        onPluginUnregistered: (name) => {\n          setPlugins((prev) => prev.filter((p) => p.name !== name));\n          managerOptions.onPluginUnregistered?.(name);\n        },\n        onToolbarItemsChanged: (items) => {\n          setToolbarItems(items);\n          managerOptions.onToolbarItemsChanged?.(items);\n        },\n        onSidebarPanelsChanged: (panels) => {\n          setSidebarPanels(panels);\n          managerOptions.onSidebarPanelsChanged?.(panels);\n        },\n        onContextMenuItemsChanged: (items) => {\n          setContextMenuItems(items);\n          managerOptions.onContextMenuItemsChanged?.(items);\n        },\n      });\n    }\n    return pluginManagerRef.current;\n  }, [managerOptions]);\n\n  // Update viewer state getter when state changes\n  useEffect(() => {\n    const manager = getPluginManager();\n    manager.setViewerStateGetter(() => viewerState as any);\n  }, [viewerState, getPluginManager]);\n\n  // Register initial plugins\n  useEffect(() => {\n    if (initialPlugins && initialPlugins.length > 0) {\n      const manager = getPluginManager();\n      initialPlugins.forEach((plugin) => {\n        manager.register(plugin);\n      });\n    }\n  }, [initialPlugins, getPluginManager]);\n\n  // Cleanup on unmount\n  useEffect(() => {\n    return () => {\n      pluginManagerRef.current?.destroy();\n    };\n  }, []);\n\n  // Memoized return value\n  const registerPlugin = useCallback(async (plugin: Plugin) => {\n    const manager = getPluginManager();\n    await manager.register(plugin);\n  }, [getPluginManager]);\n\n  const unregisterPlugin = useCallback(async (name: string) => {\n    const manager = getPluginManager();\n    await manager.unregister(name);\n  }, [getPluginManager]);\n\n  const hasPlugin = useCallback((name: string) => {\n    const manager = getPluginManager();\n    return manager.hasPlugin(name);\n  }, [getPluginManager]);\n\n  return useMemo(\n    () => ({\n      pluginManager: getPluginManager(),\n      plugins,\n      toolbarItems,\n      sidebarPanels,\n      contextMenuItems,\n      registerPlugin,\n      unregisterPlugin,\n      hasPlugin,\n    }),\n    [\n      getPluginManager,\n      plugins,\n      toolbarItems,\n      sidebarPanels,\n      contextMenuItems,\n      registerPlugin,\n      unregisterPlugin,\n      hasPlugin,\n    ]\n  );\n}\n","import { useCallback, useMemo } from 'react';\nimport { useAgentStore, useStudentStore, useAnnotationStore, useViewerStore } from './PDFViewerContext';\nimport type {\n  AgentContext,\n  FocusedRegion,\n  Takeaway,\n  AgentAPI,\n  AgentHighlightParams,\n} from '../types/agent-context';\nimport type { HighlightColor } from '../types';\n\nexport interface UseAgentContextOptions {\n  /** Default focus region style */\n  defaultFocusStyle?: 'pulse' | 'glow' | 'border';\n  /** Default focus region color */\n  defaultFocusColor?: string;\n  /** Default auto-clear timeout for focus regions (ms) */\n  defaultAutoClearTimeout?: number;\n}\n\nexport interface UseAgentContextReturn {\n  /** Current agent context */\n  agentContext: AgentContext | null;\n  /** Set or update agent context */\n  setAgentContext: (context: Partial<AgentContext>) => void;\n  /** Clear agent context */\n  clearAgentContext: () => void;\n  /** Currently focused regions */\n  focusedRegions: FocusedRegion[];\n  /** Add a focus region and return its ID */\n  focusRegion: (region: Omit<FocusedRegion, 'id'>) => string;\n  /** Remove a focus region by ID */\n  clearFocusedRegion: (id: string) => void;\n  /** Clear all focus regions */\n  clearAllFocusedRegions: () => void;\n  /** Add a takeaway for a page */\n  addTakeaway: (pageNumber: number, summary: string, metadata?: Record<string, unknown>) => Takeaway;\n  /** Add a highlight from the agent */\n  addAgentHighlight: (params: AgentHighlightParams) => string;\n  /** Get the agent API for external integration */\n  getAgentAPI: () => AgentAPI;\n}\n\n/**\n * Hook for agent context management and AI agent integration.\n * Provides methods for agents to interact with the PDF viewer.\n */\nexport function useAgentContext(options: UseAgentContextOptions = {}): UseAgentContextReturn {\n  const {\n    defaultFocusStyle = 'pulse',\n    defaultFocusColor,\n    defaultAutoClearTimeout = 0,\n  } = options;\n\n  // Agent store state and actions\n  const agentContext = useAgentStore((s) => s.currentContext);\n  const focusedRegions = useAgentStore((s) => s.focusedRegions);\n  const setAgentContextAction = useAgentStore((s) => s.setAgentContext);\n  const clearAgentContextAction = useAgentStore((s) => s.clearAgentContext);\n  const addFocusedRegionAction = useAgentStore((s) => s.addFocusedRegion);\n  const removeFocusedRegionAction = useAgentStore((s) => s.removeFocusedRegion);\n  const clearAllFocusedRegionsAction = useAgentStore((s) => s.clearAllFocusedRegions);\n\n  // Student store actions for takeaways\n  const addTakeawayAction = useStudentStore((s) => s.addTakeaway);\n\n  // Annotation store for agent highlights\n  const addHighlightAction = useAnnotationStore((s) => s.addHighlight);\n\n  // Viewer store for navigation\n  const goToPageAction = useViewerStore((s) => s.goToPage);\n  const currentPage = useViewerStore((s) => s.currentPage);\n\n  const setAgentContext = useCallback(\n    (context: Partial<AgentContext>) => {\n      setAgentContextAction(context);\n    },\n    [setAgentContextAction]\n  );\n\n  const clearAgentContext = useCallback(() => {\n    clearAgentContextAction();\n  }, [clearAgentContextAction]);\n\n  const focusRegion = useCallback(\n    (region: Omit<FocusedRegion, 'id'>) => {\n      const regionWithDefaults: Omit<FocusedRegion, 'id'> = {\n        ...region,\n        style: region.style ?? defaultFocusStyle,\n        color: region.color ?? defaultFocusColor,\n        autoClearTimeout: region.autoClearTimeout ?? defaultAutoClearTimeout,\n      };\n      return addFocusedRegionAction(regionWithDefaults);\n    },\n    [addFocusedRegionAction, defaultFocusStyle, defaultFocusColor, defaultAutoClearTimeout]\n  );\n\n  const clearFocusedRegion = useCallback(\n    (id: string) => {\n      removeFocusedRegionAction(id);\n    },\n    [removeFocusedRegionAction]\n  );\n\n  const clearAllFocusedRegions = useCallback(() => {\n    clearAllFocusedRegionsAction();\n  }, [clearAllFocusedRegionsAction]);\n\n  const addTakeaway = useCallback(\n    (pageNumber: number, summary: string, metadata?: Record<string, unknown>) => {\n      return addTakeawayAction({\n        pageNumber,\n        summary,\n        source: 'agent',\n        metadata,\n      });\n    },\n    [addTakeawayAction]\n  );\n\n  const addAgentHighlight = useCallback(\n    (params: AgentHighlightParams) => {\n      const highlight = addHighlightAction({\n        pageNumber: params.pageNumber,\n        rects: params.rects,\n        text: params.text,\n        color: params.color ?? ('blue' as HighlightColor),\n        comment: params.comment,\n        source: 'agent',\n      });\n      return highlight.id;\n    },\n    [addHighlightAction]\n  );\n\n  const getAgentAPI = useCallback((): AgentAPI => {\n    return {\n      focusRegion,\n      clearFocusedRegion: (id?: string) => {\n        if (id) {\n          clearFocusedRegion(id);\n        } else {\n          clearAllFocusedRegions();\n        }\n      },\n      addTakeaway,\n      setAgentContext,\n      addAgentHighlight,\n      goToPage: goToPageAction,\n      getCurrentPage: () => currentPage,\n      getAgentContext: () => agentContext,\n    };\n  }, [\n    focusRegion,\n    clearFocusedRegion,\n    clearAllFocusedRegions,\n    addTakeaway,\n    setAgentContext,\n    addAgentHighlight,\n    goToPageAction,\n    currentPage,\n    agentContext,\n  ]);\n\n  return useMemo(\n    () => ({\n      agentContext,\n      setAgentContext,\n      clearAgentContext,\n      focusedRegions,\n      focusRegion,\n      clearFocusedRegion,\n      clearAllFocusedRegions,\n      addTakeaway,\n      addAgentHighlight,\n      getAgentAPI,\n    }),\n    [\n      agentContext,\n      setAgentContext,\n      clearAgentContext,\n      focusedRegions,\n      focusRegion,\n      clearFocusedRegion,\n      clearAllFocusedRegions,\n      addTakeaway,\n      addAgentHighlight,\n      getAgentAPI,\n    ]\n  );\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { useAgentStore } from './PDFViewerContext';\nimport type { AskAboutContext, PDFRegion } from '../types/agent-context';\n\nexport interface UseAskAboutOptions {\n  /** Whether the feature is enabled */\n  enabled?: boolean;\n  /** Long press duration to trigger ask about (ms) */\n  longPressDuration?: number;\n  /** Callback when ask about is triggered */\n  onAskAbout?: (context: AskAboutContext) => void;\n  /** Minimum selection length to enable ask about for text */\n  minSelectionLength?: number;\n}\n\nexport interface UseAskAboutReturn {\n  /** Whether ask about is currently in progress (long press active) */\n  isLongPressing: boolean;\n  /** Progress of the long press (0-1) */\n  longPressProgress: number;\n  /** Position of the long press */\n  longPressPosition: { x: number; y: number } | null;\n  /** Trigger ask about for selected text */\n  askAboutSelection: (text: string, pageNumber: number) => void;\n  /** Trigger ask about for a region (diagram, image) */\n  askAboutRegion: (region: PDFRegion, pageNumber: number) => void;\n  /** Start long press tracking (for custom implementations) */\n  startLongPress: (x: number, y: number) => void;\n  /** Cancel long press */\n  cancelLongPress: () => void;\n  /** Complete long press and trigger callback */\n  completeLongPress: (type: 'text' | 'region', pageNumber: number, text?: string, region?: PDFRegion) => void;\n  /** Handlers for attaching to elements */\n  handlers: {\n    onMouseDown: (e: React.MouseEvent) => void;\n    onMouseUp: () => void;\n    onMouseLeave: () => void;\n    onTouchStart: (e: React.TouchEvent) => void;\n    onTouchEnd: () => void;\n    onTouchCancel: () => void;\n  };\n}\n\n/**\n * Hook for implementing the \"Ask About This\" feature.\n * Provides long-press detection and callbacks for asking about text or regions.\n */\nexport function useAskAbout(options: UseAskAboutOptions = {}): UseAskAboutReturn {\n  const {\n    enabled = true,\n    longPressDuration = 800,\n    onAskAbout,\n    minSelectionLength = 3,\n  } = options;\n\n  const [isLongPressing, setIsLongPressing] = useState(false);\n  const [longPressProgress, setLongPressProgress] = useState(0);\n  const [longPressPosition, setLongPressPosition] = useState<{ x: number; y: number } | null>(null);\n\n  const timerRef = useRef<number | null>(null);\n  const progressIntervalRef = useRef<number | null>(null);\n  const startTimeRef = useRef<number>(0);\n\n  // Get agent context for including in ask about\n  const agentContext = useAgentStore((s) => s.currentContext);\n\n  const clearTimers = useCallback(() => {\n    if (timerRef.current !== null) {\n      clearTimeout(timerRef.current);\n      timerRef.current = null;\n    }\n    if (progressIntervalRef.current !== null) {\n      clearInterval(progressIntervalRef.current);\n      progressIntervalRef.current = null;\n    }\n  }, []);\n\n  const cancelLongPress = useCallback(() => {\n    clearTimers();\n    setIsLongPressing(false);\n    setLongPressProgress(0);\n    setLongPressPosition(null);\n  }, [clearTimers]);\n\n  const triggerAskAbout = useCallback(\n    (context: AskAboutContext) => {\n      // Include agent context if available\n      const fullContext: AskAboutContext = {\n        ...context,\n        agentContext: agentContext ?? undefined,\n      };\n      onAskAbout?.(fullContext);\n    },\n    [onAskAbout, agentContext]\n  );\n\n  const startLongPress = useCallback(\n    (x: number, y: number) => {\n      if (!enabled) return;\n\n      clearTimers();\n      setIsLongPressing(true);\n      setLongPressProgress(0);\n      setLongPressPosition({ x, y });\n      startTimeRef.current = Date.now();\n\n      // Update progress every 50ms\n      progressIntervalRef.current = window.setInterval(() => {\n        const elapsed = Date.now() - startTimeRef.current;\n        const progress = Math.min(elapsed / longPressDuration, 1);\n        setLongPressProgress(progress);\n      }, 50);\n\n      // Complete after duration\n      timerRef.current = window.setTimeout(() => {\n        setLongPressProgress(1);\n        clearTimers();\n      }, longPressDuration);\n    },\n    [enabled, longPressDuration, clearTimers]\n  );\n\n  const completeLongPress = useCallback(\n    (type: 'text' | 'region', pageNumber: number, text?: string, region?: PDFRegion) => {\n      if (longPressProgress >= 1) {\n        triggerAskAbout({\n          type,\n          pageNumber,\n          selectedText: text,\n          region,\n        });\n      }\n      cancelLongPress();\n    },\n    [longPressProgress, triggerAskAbout, cancelLongPress]\n  );\n\n  const askAboutSelection = useCallback(\n    (text: string, pageNumber: number) => {\n      if (!enabled || text.length < minSelectionLength) return;\n\n      triggerAskAbout({\n        type: 'text',\n        pageNumber,\n        selectedText: text,\n      });\n    },\n    [enabled, minSelectionLength, triggerAskAbout]\n  );\n\n  const askAboutRegion = useCallback(\n    (region: PDFRegion, pageNumber: number) => {\n      if (!enabled) return;\n\n      triggerAskAbout({\n        type: 'region',\n        pageNumber,\n        region,\n      });\n    },\n    [enabled, triggerAskAbout]\n  );\n\n  // Mouse handlers\n  const handleMouseDown = useCallback(\n    (e: React.MouseEvent) => {\n      if (!enabled) return;\n      startLongPress(e.clientX, e.clientY);\n    },\n    [enabled, startLongPress]\n  );\n\n  const handleMouseUp = useCallback(() => {\n    if (isLongPressing && longPressProgress < 1) {\n      cancelLongPress();\n    }\n  }, [isLongPressing, longPressProgress, cancelLongPress]);\n\n  const handleMouseLeave = useCallback(() => {\n    if (isLongPressing) {\n      cancelLongPress();\n    }\n  }, [isLongPressing, cancelLongPress]);\n\n  // Touch handlers\n  const handleTouchStart = useCallback(\n    (e: React.TouchEvent) => {\n      if (!enabled || e.touches.length !== 1) return;\n      const touch = e.touches[0];\n      startLongPress(touch.clientX, touch.clientY);\n    },\n    [enabled, startLongPress]\n  );\n\n  const handleTouchEnd = useCallback(() => {\n    if (isLongPressing && longPressProgress < 1) {\n      cancelLongPress();\n    }\n  }, [isLongPressing, longPressProgress, cancelLongPress]);\n\n  const handleTouchCancel = useCallback(() => {\n    cancelLongPress();\n  }, [cancelLongPress]);\n\n  // Cleanup on unmount\n  useEffect(() => {\n    return () => {\n      clearTimers();\n    };\n  }, [clearTimers]);\n\n  return {\n    isLongPressing,\n    longPressProgress,\n    longPressPosition,\n    askAboutSelection,\n    askAboutRegion,\n    startLongPress,\n    cancelLongPress,\n    completeLongPress,\n    handlers: {\n      onMouseDown: handleMouseDown,\n      onMouseUp: handleMouseUp,\n      onMouseLeave: handleMouseLeave,\n      onTouchStart: handleTouchStart,\n      onTouchEnd: handleTouchEnd,\n      onTouchCancel: handleTouchCancel,\n    },\n  };\n}\n","import { useCallback, useMemo } from 'react';\nimport { useStudentStore, useAgentStore, useViewerStore } from './PDFViewerContext';\nimport type { Bookmark } from '../types/agent-context';\n\nexport interface UseBookmarksOptions {\n  /** Callback when bookmark is added */\n  onBookmarkAdd?: (bookmark: Bookmark) => void;\n  /** Callback when bookmark is removed */\n  onBookmarkRemove?: (id: string) => void;\n  /** Automatically capture agent context when bookmarking */\n  captureAgentContext?: boolean;\n}\n\nexport interface UseBookmarksReturn {\n  /** All bookmarks */\n  bookmarks: Bookmark[];\n  /** Bookmarks for the current page */\n  currentPageBookmarks: Bookmark[];\n  /** Check if current page is bookmarked */\n  isCurrentPageBookmarked: boolean;\n  /** Add a bookmark */\n  addBookmark: (data?: Partial<Omit<Bookmark, 'id' | 'timestamp'>>) => Bookmark;\n  /** Update a bookmark */\n  updateBookmark: (id: string, updates: Partial<Omit<Bookmark, 'id'>>) => void;\n  /** Remove a bookmark */\n  removeBookmark: (id: string) => void;\n  /** Toggle bookmark on current page */\n  toggleBookmark: () => void;\n  /** Navigate to a bookmarked page */\n  goToBookmark: (bookmark: Bookmark) => void;\n  /** Get bookmarks for a specific page */\n  getBookmarksForPage: (pageNumber: number) => Bookmark[];\n  /** Get bookmarks grouped by page */\n  bookmarksByPage: Map<number, Bookmark[]>;\n}\n\n/**\n * Hook for managing bookmarks with agent context capture.\n */\nexport function useBookmarks(options: UseBookmarksOptions = {}): UseBookmarksReturn {\n  const { onBookmarkAdd, onBookmarkRemove, captureAgentContext = true } = options;\n\n  // Student store state and actions\n  const bookmarks = useStudentStore((s) => s.bookmarks);\n  const addBookmarkAction = useStudentStore((s) => s.addBookmark);\n  const updateBookmarkAction = useStudentStore((s) => s.updateBookmark);\n  const removeBookmarkAction = useStudentStore((s) => s.removeBookmark);\n\n  // Agent context for capturing\n  const agentContext = useAgentStore((s) => s.currentContext);\n\n  // Viewer store for navigation\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const goToPage = useViewerStore((s) => s.goToPage);\n\n  const currentPageBookmarks = useMemo(\n    () => bookmarks.filter((b) => b.pageNumber === currentPage),\n    [bookmarks, currentPage]\n  );\n\n  const isCurrentPageBookmarked = currentPageBookmarks.length > 0;\n\n  const bookmarksByPage = useMemo(() => {\n    const map = new Map<number, Bookmark[]>();\n    bookmarks.forEach((bookmark) => {\n      const existing = map.get(bookmark.pageNumber) || [];\n      map.set(bookmark.pageNumber, [...existing, bookmark]);\n    });\n    return map;\n  }, [bookmarks]);\n\n  const addBookmark = useCallback(\n    (data?: Partial<Omit<Bookmark, 'id' | 'timestamp'>>) => {\n      const bookmarkData = {\n        pageNumber: data?.pageNumber ?? currentPage,\n        userNote: data?.userNote,\n        label: data?.label,\n        agentContext: captureAgentContext && agentContext?.lastStatement\n          ? agentContext.lastStatement\n          : data?.agentContext,\n      };\n\n      const bookmark = addBookmarkAction(bookmarkData);\n      onBookmarkAdd?.(bookmark);\n      return bookmark;\n    },\n    [currentPage, captureAgentContext, agentContext, addBookmarkAction, onBookmarkAdd]\n  );\n\n  const updateBookmark = useCallback(\n    (id: string, updates: Partial<Omit<Bookmark, 'id'>>) => {\n      updateBookmarkAction(id, updates);\n    },\n    [updateBookmarkAction]\n  );\n\n  const removeBookmark = useCallback(\n    (id: string) => {\n      removeBookmarkAction(id);\n      onBookmarkRemove?.(id);\n    },\n    [removeBookmarkAction, onBookmarkRemove]\n  );\n\n  const toggleBookmark = useCallback(() => {\n    if (isCurrentPageBookmarked) {\n      // Remove the first bookmark on the current page\n      const bookmarkToRemove = currentPageBookmarks[0];\n      if (bookmarkToRemove) {\n        removeBookmark(bookmarkToRemove.id);\n      }\n    } else {\n      addBookmark();\n    }\n  }, [isCurrentPageBookmarked, currentPageBookmarks, removeBookmark, addBookmark]);\n\n  const goToBookmark = useCallback(\n    (bookmark: Bookmark) => {\n      goToPage(bookmark.pageNumber);\n    },\n    [goToPage]\n  );\n\n  const getBookmarksForPage = useCallback(\n    (pageNumber: number) => {\n      return bookmarks.filter((b) => b.pageNumber === pageNumber);\n    },\n    [bookmarks]\n  );\n\n  return useMemo(\n    () => ({\n      bookmarks,\n      currentPageBookmarks,\n      isCurrentPageBookmarked,\n      addBookmark,\n      updateBookmark,\n      removeBookmark,\n      toggleBookmark,\n      goToBookmark,\n      getBookmarksForPage,\n      bookmarksByPage,\n    }),\n    [\n      bookmarks,\n      currentPageBookmarks,\n      isCurrentPageBookmarked,\n      addBookmark,\n      updateBookmark,\n      removeBookmark,\n      toggleBookmark,\n      goToBookmark,\n      getBookmarksForPage,\n      bookmarksByPage,\n    ]\n  );\n}\n","import { useCallback, useMemo } from 'react';\nimport { useStudentStore, useAgentStore, useViewerStore } from './PDFViewerContext';\nimport type { QuickNote } from '../types/agent-context';\n\nexport interface UseQuickNotesOptions {\n  /** Callback when note is added */\n  onNoteAdd?: (note: QuickNote) => void;\n  /** Callback when note is removed */\n  onNoteRemove?: (id: string) => void;\n  /** Automatically capture agent's last statement when creating notes */\n  captureAgentContext?: boolean;\n}\n\nexport interface UseQuickNotesReturn {\n  /** All quick notes */\n  quickNotes: QuickNote[];\n  /** Quick notes for the current page */\n  currentPageNotes: QuickNote[];\n  /** Add a quick note */\n  addQuickNote: (data: { content: string; x: number; y: number; pageNumber?: number }) => QuickNote;\n  /** Update a quick note */\n  updateQuickNote: (id: string, updates: Partial<Omit<QuickNote, 'id'>>) => void;\n  /** Remove a quick note */\n  removeQuickNote: (id: string) => void;\n  /** Get notes for a specific page */\n  getNotesForPage: (pageNumber: number) => QuickNote[];\n  /** Notes grouped by page */\n  notesByPage: Map<number, QuickNote[]>;\n}\n\n/**\n * Hook for managing quick notes with agent context capture.\n */\nexport function useQuickNotes(options: UseQuickNotesOptions = {}): UseQuickNotesReturn {\n  const { onNoteAdd, onNoteRemove, captureAgentContext = true } = options;\n\n  // Student store state and actions\n  const quickNotes = useStudentStore((s) => s.quickNotes);\n  const addQuickNoteAction = useStudentStore((s) => s.addQuickNote);\n  const updateQuickNoteAction = useStudentStore((s) => s.updateQuickNote);\n  const removeQuickNoteAction = useStudentStore((s) => s.removeQuickNote);\n\n  // Agent context for capturing\n  const agentContext = useAgentStore((s) => s.currentContext);\n\n  // Viewer store for current page\n  const currentPage = useViewerStore((s) => s.currentPage);\n\n  const currentPageNotes = useMemo(\n    () => quickNotes.filter((n) => n.pageNumber === currentPage),\n    [quickNotes, currentPage]\n  );\n\n  const notesByPage = useMemo(() => {\n    const map = new Map<number, QuickNote[]>();\n    quickNotes.forEach((note) => {\n      const existing = map.get(note.pageNumber) || [];\n      map.set(note.pageNumber, [...existing, note]);\n    });\n    return map;\n  }, [quickNotes]);\n\n  const addQuickNote = useCallback(\n    (data: { content: string; x: number; y: number; pageNumber?: number }) => {\n      const noteData = {\n        content: data.content,\n        x: data.x,\n        y: data.y,\n        pageNumber: data.pageNumber ?? currentPage,\n        agentLastStatement: captureAgentContext && agentContext?.lastStatement\n          ? agentContext.lastStatement\n          : undefined,\n      };\n\n      const note = addQuickNoteAction(noteData);\n      onNoteAdd?.(note);\n      return note;\n    },\n    [currentPage, captureAgentContext, agentContext, addQuickNoteAction, onNoteAdd]\n  );\n\n  const updateQuickNote = useCallback(\n    (id: string, updates: Partial<Omit<QuickNote, 'id'>>) => {\n      updateQuickNoteAction(id, updates);\n    },\n    [updateQuickNoteAction]\n  );\n\n  const removeQuickNote = useCallback(\n    (id: string) => {\n      removeQuickNoteAction(id);\n      onNoteRemove?.(id);\n    },\n    [removeQuickNoteAction, onNoteRemove]\n  );\n\n  const getNotesForPage = useCallback(\n    (pageNumber: number) => {\n      return quickNotes.filter((n) => n.pageNumber === pageNumber);\n    },\n    [quickNotes]\n  );\n\n  return useMemo(\n    () => ({\n      quickNotes,\n      currentPageNotes,\n      addQuickNote,\n      updateQuickNote,\n      removeQuickNote,\n      getNotesForPage,\n      notesByPage,\n    }),\n    [\n      quickNotes,\n      currentPageNotes,\n      addQuickNote,\n      updateQuickNote,\n      removeQuickNote,\n      getNotesForPage,\n      notesByPage,\n    ]\n  );\n}\n","import { useCallback, useMemo, useEffect } from 'react';\nimport { useStudentStore, useViewerStore } from './PDFViewerContext';\n\nexport interface UseStudentProgressOptions {\n  /** Automatically track page visits */\n  autoTrack?: boolean;\n  /** Debounce time for page tracking (ms) */\n  trackDebounce?: number;\n}\n\nexport interface UseStudentProgressReturn {\n  /** Set of visited page numbers */\n  visitedPages: Set<number>;\n  /** Array of visited page numbers (for easier iteration) */\n  visitedPagesArray: number[];\n  /** Current reading progress (0-1) */\n  progress: number;\n  /** Percentage of pages visited */\n  visitedPercentage: number;\n  /** Number of pages visited */\n  visitedCount: number;\n  /** Total number of pages */\n  totalPages: number;\n  /** Current page number */\n  currentPage: number;\n  /** Mark a page as visited */\n  markPageVisited: (pageNumber: number) => void;\n  /** Check if a page has been visited */\n  isPageVisited: (pageNumber: number) => boolean;\n  /** Get page visit status for minimap rendering */\n  getPageStatus: (pageNumber: number) => 'current' | 'visited' | 'unvisited';\n}\n\n/**\n * Hook for tracking student reading progress.\n */\nexport function useStudentProgress(options: UseStudentProgressOptions = {}): UseStudentProgressReturn {\n  const { autoTrack = true, trackDebounce = 1000 } = options;\n\n  // Student store state and actions\n  const visitedPages = useStudentStore((s) => s.visitedPages);\n  const progress = useStudentStore((s) => s.progress);\n  const markPageVisitedAction = useStudentStore((s) => s.markPageVisited);\n  const setProgressAction = useStudentStore((s) => s.setProgress);\n\n  // Viewer store for page info\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const numPages = useViewerStore((s) => s.numPages);\n\n  const visitedPagesArray = useMemo(\n    () => Array.from(visitedPages).sort((a, b) => a - b),\n    [visitedPages]\n  );\n\n  const visitedCount = visitedPages.size;\n  const totalPages = numPages;\n\n  const visitedPercentage = useMemo(() => {\n    if (totalPages === 0) return 0;\n    return (visitedCount / totalPages) * 100;\n  }, [visitedCount, totalPages]);\n\n  const markPageVisited = useCallback(\n    (pageNumber: number) => {\n      markPageVisitedAction(pageNumber);\n      // Update progress based on visited pages\n      if (totalPages > 0) {\n        const newProgress = (visitedPages.size + 1) / totalPages;\n        setProgressAction(Math.min(newProgress, 1));\n      }\n    },\n    [markPageVisitedAction, setProgressAction, totalPages, visitedPages.size]\n  );\n\n  const isPageVisited = useCallback(\n    (pageNumber: number) => {\n      return visitedPages.has(pageNumber);\n    },\n    [visitedPages]\n  );\n\n  const getPageStatus = useCallback(\n    (pageNumber: number): 'current' | 'visited' | 'unvisited' => {\n      if (pageNumber === currentPage) return 'current';\n      if (visitedPages.has(pageNumber)) return 'visited';\n      return 'unvisited';\n    },\n    [currentPage, visitedPages]\n  );\n\n  // Auto-track current page visits\n  useEffect(() => {\n    if (!autoTrack || currentPage <= 0) return;\n\n    const timer = setTimeout(() => {\n      if (!visitedPages.has(currentPage)) {\n        markPageVisited(currentPage);\n      }\n    }, trackDebounce);\n\n    return () => clearTimeout(timer);\n  }, [autoTrack, currentPage, trackDebounce, visitedPages, markPageVisited]);\n\n  return useMemo(\n    () => ({\n      visitedPages,\n      visitedPagesArray,\n      progress,\n      visitedPercentage,\n      visitedCount,\n      totalPages,\n      currentPage,\n      markPageVisited,\n      isPageVisited,\n      getPageStatus,\n    }),\n    [\n      visitedPages,\n      visitedPagesArray,\n      progress,\n      visitedPercentage,\n      visitedCount,\n      totalPages,\n      currentPage,\n      markPageVisited,\n      isPageVisited,\n      getPageStatus,\n    ]\n  );\n}\n","export {\n  PDFViewerProvider,\n  PDFViewerContext,\n  useViewerStore,\n  useAnnotationStore,\n  useSearchStore,\n  useAgentStore,\n  useStudentStore,\n  usePDFViewerStores,\n  type PDFViewerProviderProps,\n  type PDFViewerContextValue,\n} from './PDFViewerContext';\n\nexport { usePDFViewer } from './usePDFViewer';\nexport { usePageNavigation, type UsePageNavigationOptions } from './usePageNavigation';\nexport { useZoom, type UseZoomOptions } from './useZoom';\nexport { useTextSelection, type UseTextSelectionOptions } from './useTextSelection';\nexport { useHighlights, type UseHighlightsOptions, type UseHighlightsReturn } from './useHighlights';\nexport { useAnnotations, type UseAnnotationsOptions, type UseAnnotationsReturn } from './useAnnotations';\nexport { useTouchGestures, useIsTouchDevice, useIsMobile, type UseTouchGesturesOptions } from './useTouchGestures';\nexport { usePlugins, type UsePluginsOptions, type UsePluginsReturn } from './usePlugins';\n\n// Student Learning Feature Hooks\nexport { useAgentContext, type UseAgentContextOptions, type UseAgentContextReturn } from './useAgentContext';\nexport { useAskAbout, type UseAskAboutOptions, type UseAskAboutReturn } from './useAskAbout';\nexport { useBookmarks, type UseBookmarksOptions, type UseBookmarksReturn } from './useBookmarks';\nexport { useQuickNotes, type UseQuickNotesOptions, type UseQuickNotesReturn } from './useQuickNotes';\nexport { useStudentProgress, type UseStudentProgressOptions, type UseStudentProgressReturn } from './useStudentProgress';\n","import { memo, useCallback, useState } from 'react';\nimport { usePDFViewer } from '../../hooks';\nimport { cn } from '../../utils';\n\nexport interface ToolbarProps {\n  className?: string;\n  showNavigation?: boolean;\n  showZoom?: boolean;\n  showRotation?: boolean;\n  showTheme?: boolean;\n  showSidebar?: boolean;\n  showFullscreen?: boolean;\n}\n\nexport const Toolbar = memo(function Toolbar({\n  className,\n  showNavigation = true,\n  showZoom = true,\n  showRotation = true,\n  showTheme = true,\n  showSidebar = true,\n  showFullscreen = true,\n}: ToolbarProps) {\n  const {\n    currentPage,\n    numPages,\n    scale,\n    theme,\n    sidebarOpen,\n    goToPage,\n    previousPage,\n    nextPage,\n    zoomIn,\n    zoomOut,\n    setScale,\n    rotateClockwise,\n    setTheme,\n    toggleSidebar,\n    setFullscreen,\n  } = usePDFViewer();\n\n  const [pageInput, setPageInput] = useState(String(currentPage));\n\n  const handlePageInputChange = useCallback(\n    (e: React.ChangeEvent<HTMLInputElement>) => {\n      setPageInput(e.target.value);\n    },\n    []\n  );\n\n  const handlePageInputBlur = useCallback(() => {\n    const page = parseInt(pageInput, 10);\n    if (!isNaN(page) && page >= 1 && page <= numPages) {\n      goToPage(page);\n    } else {\n      setPageInput(String(currentPage));\n    }\n  }, [pageInput, numPages, goToPage, currentPage]);\n\n  const handlePageInputKeyDown = useCallback(\n    (e: React.KeyboardEvent) => {\n      if (e.key === 'Enter') {\n        handlePageInputBlur();\n      }\n    },\n    [handlePageInputBlur]\n  );\n\n  const handleZoomChange = useCallback(\n    (e: React.ChangeEvent<HTMLSelectElement>) => {\n      const value = e.target.value;\n      if (value === 'fit-width') {\n        setScale(1);\n      } else if (value === 'fit-page') {\n        setScale(1);\n      } else {\n        setScale(parseFloat(value));\n      }\n    },\n    [setScale]\n  );\n\n  const zoomOptions = [\n    { value: '0.5', label: '50%' },\n    { value: '0.75', label: '75%' },\n    { value: '1', label: '100%' },\n    { value: '1.25', label: '125%' },\n    { value: '1.5', label: '150%' },\n    { value: '2', label: '200%' },\n    { value: '3', label: '300%' },\n  ];\n\n  // Update page input when currentPage changes\n  if (pageInput !== String(currentPage) && document.activeElement?.tagName !== 'INPUT') {\n    setPageInput(String(currentPage));\n  }\n\n  return (\n    <div\n      className={cn(\n        'pdf-toolbar',\n        'flex items-center justify-between',\n        'px-4 py-2',\n        'bg-white border-b border-gray-200',\n        'dark:bg-gray-800 dark:border-gray-700',\n        className\n      )}\n    >\n      {/* Left section */}\n      <div className=\"flex items-center gap-2\">\n        {showSidebar && (\n          <button\n            onClick={toggleSidebar}\n            className={cn(\n              'p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700',\n              sidebarOpen && 'bg-gray-100 dark:bg-gray-700'\n            )}\n            title=\"Toggle Sidebar\"\n            aria-label=\"Toggle Sidebar\"\n          >\n            <svg\n              className=\"w-5 h-5\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              viewBox=\"0 0 24 24\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M4 6h16M4 12h16M4 18h7\"\n              />\n            </svg>\n          </button>\n        )}\n      </div>\n\n      {/* Center section - Navigation */}\n      <div className=\"flex items-center gap-4\">\n        {showNavigation && (\n          <div className=\"flex items-center gap-2\">\n            <button\n              onClick={previousPage}\n              disabled={currentPage <= 1}\n              className=\"p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed\"\n              title=\"Previous Page\"\n              aria-label=\"Previous Page\"\n            >\n              <svg\n                className=\"w-5 h-5\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                viewBox=\"0 0 24 24\"\n              >\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M15 19l-7-7 7-7\"\n                />\n              </svg>\n            </button>\n\n            <div className=\"flex items-center gap-1 text-sm\">\n              <input\n                type=\"text\"\n                value={pageInput}\n                onChange={handlePageInputChange}\n                onBlur={handlePageInputBlur}\n                onKeyDown={handlePageInputKeyDown}\n                className=\"w-12 px-2 py-1 text-center border rounded dark:bg-gray-700 dark:border-gray-600\"\n                aria-label=\"Current Page\"\n              />\n              <span className=\"text-gray-500\">/ {numPages}</span>\n            </div>\n\n            <button\n              onClick={nextPage}\n              disabled={currentPage >= numPages}\n              className=\"p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed\"\n              title=\"Next Page\"\n              aria-label=\"Next Page\"\n            >\n              <svg\n                className=\"w-5 h-5\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                viewBox=\"0 0 24 24\"\n              >\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M9 5l7 7-7 7\"\n                />\n              </svg>\n            </button>\n          </div>\n        )}\n\n        {showZoom && (\n          <div className=\"flex items-center gap-2 border-l pl-4 border-gray-200 dark:border-gray-700\">\n            <button\n              onClick={zoomOut}\n              className=\"p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700\"\n              title=\"Zoom Out\"\n              aria-label=\"Zoom Out\"\n            >\n              <svg\n                className=\"w-5 h-5\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                viewBox=\"0 0 24 24\"\n              >\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7\"\n                />\n              </svg>\n            </button>\n\n            <select\n              value={scale.toString()}\n              onChange={handleZoomChange}\n              className=\"px-2 py-1 border rounded text-sm dark:bg-gray-700 dark:border-gray-600\"\n              aria-label=\"Zoom Level\"\n            >\n              {zoomOptions.map((option) => (\n                <option key={option.value} value={option.value}>\n                  {option.label}\n                </option>\n              ))}\n            </select>\n\n            <button\n              onClick={zoomIn}\n              className=\"p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700\"\n              title=\"Zoom In\"\n              aria-label=\"Zoom In\"\n            >\n              <svg\n                className=\"w-5 h-5\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                viewBox=\"0 0 24 24\"\n              >\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v6m3-3H7\"\n                />\n              </svg>\n            </button>\n          </div>\n        )}\n      </div>\n\n      {/* Right section */}\n      <div className=\"flex items-center gap-2\">\n        {showRotation && (\n          <button\n            onClick={rotateClockwise}\n            className=\"p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700\"\n            title=\"Rotate Clockwise\"\n            aria-label=\"Rotate Clockwise\"\n          >\n            <svg\n              className=\"w-5 h-5\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              viewBox=\"0 0 24 24\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n              />\n            </svg>\n          </button>\n        )}\n\n        {showTheme && (\n          <select\n            value={theme}\n            onChange={(e) => setTheme(e.target.value as 'light' | 'dark' | 'sepia')}\n            className=\"px-2 py-1 border rounded text-sm dark:bg-gray-700 dark:border-gray-600\"\n            aria-label=\"Theme\"\n          >\n            <option value=\"light\">Light</option>\n            <option value=\"dark\">Dark</option>\n            <option value=\"sepia\">Sepia</option>\n          </select>\n        )}\n\n        {showFullscreen && (\n          <button\n            onClick={() => setFullscreen(true)}\n            className=\"p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700\"\n            title=\"Fullscreen\"\n            aria-label=\"Fullscreen\"\n          >\n            <svg\n              className=\"w-5 h-5\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              viewBox=\"0 0 24 24\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4\"\n              />\n            </svg>\n          </button>\n        )}\n      </div>\n    </div>\n  );\n});\n","import { memo, useState, useCallback } from 'react';\nimport { cn } from '../../utils';\n\nexport interface MobileToolbarProps {\n  // Navigation\n  currentPage: number;\n  totalPages: number;\n  onPreviousPage: () => void;\n  onNextPage: () => void;\n  onGoToPage: (page: number) => void;\n\n  // Zoom\n  scale: number;\n  onZoomIn: () => void;\n  onZoomOut: () => void;\n\n  // Sidebar\n  onToggleSidebar: () => void;\n  sidebarOpen: boolean;\n\n  // Theme\n  theme: 'light' | 'dark' | 'sepia';\n  onThemeChange: (theme: 'light' | 'dark' | 'sepia') => void;\n\n  // Position\n  position?: 'top' | 'bottom';\n\n  className?: string;\n}\n\nexport const MobileToolbar = memo(function MobileToolbar({\n  currentPage,\n  totalPages,\n  onPreviousPage,\n  onNextPage,\n  onGoToPage,\n  scale,\n  onZoomIn,\n  onZoomOut,\n  onToggleSidebar,\n  sidebarOpen,\n  theme,\n  onThemeChange,\n  position = 'bottom',\n  className,\n}: MobileToolbarProps) {\n  const [showMoreMenu, setShowMoreMenu] = useState(false);\n  const [showPageInput, setShowPageInput] = useState(false);\n  const [pageInputValue, setPageInputValue] = useState(String(currentPage));\n\n  const handlePageSubmit = useCallback(() => {\n    const page = parseInt(pageInputValue, 10);\n    if (!isNaN(page) && page >= 1 && page <= totalPages) {\n      onGoToPage(page);\n    }\n    setShowPageInput(false);\n  }, [pageInputValue, totalPages, onGoToPage]);\n\n  const toggleMoreMenu = useCallback(() => {\n    setShowMoreMenu((prev) => !prev);\n  }, []);\n\n  const buttonClasses = cn(\n    'min-w-[44px] min-h-[44px]',\n    'flex items-center justify-center',\n    'rounded-lg transition-colors',\n    'text-gray-700 dark:text-gray-300',\n    'hover:bg-gray-100 dark:hover:bg-gray-700',\n    'active:bg-gray-200 dark:active:bg-gray-600',\n    'disabled:opacity-40 disabled:pointer-events-none'\n  );\n\n  return (\n    <div\n      className={cn(\n        'mobile-toolbar',\n        'fixed left-0 right-0 z-50',\n        'bg-white dark:bg-gray-800',\n        'border-gray-200 dark:border-gray-700',\n        'px-2 py-1 safe-area-inset',\n        position === 'top' && 'top-0 border-b',\n        position === 'bottom' && 'bottom-0 border-t',\n        className\n      )}\n    >\n      <div className=\"flex items-center justify-between gap-1\">\n        {/* Sidebar toggle */}\n        <button\n          className={cn(buttonClasses, sidebarOpen && 'bg-blue-100 dark:bg-blue-900')}\n          onClick={onToggleSidebar}\n          aria-label=\"Toggle sidebar\"\n        >\n          <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n            <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6h16M4 12h16M4 18h16\" />\n          </svg>\n        </button>\n\n        {/* Navigation group */}\n        <div className=\"flex items-center\">\n          <button\n            className={buttonClasses}\n            onClick={onPreviousPage}\n            disabled={currentPage <= 1}\n            aria-label=\"Previous page\"\n          >\n            <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n            </svg>\n          </button>\n\n          {/* Page indicator */}\n          {showPageInput ? (\n            <input\n              type=\"number\"\n              className={cn(\n                'w-16 h-10 text-center text-sm',\n                'bg-gray-100 dark:bg-gray-700',\n                'border border-gray-300 dark:border-gray-600',\n                'rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500'\n              )}\n              value={pageInputValue}\n              onChange={(e) => setPageInputValue(e.target.value)}\n              onBlur={handlePageSubmit}\n              onKeyDown={(e) => {\n                if (e.key === 'Enter') handlePageSubmit();\n                if (e.key === 'Escape') setShowPageInput(false);\n              }}\n              min={1}\n              max={totalPages}\n              autoFocus\n            />\n          ) : (\n            <button\n              className={cn(\n                'min-w-[60px] h-10 px-2',\n                'text-sm font-medium',\n                'text-gray-700 dark:text-gray-300'\n              )}\n              onClick={() => {\n                setPageInputValue(String(currentPage));\n                setShowPageInput(true);\n              }}\n            >\n              {currentPage} / {totalPages}\n            </button>\n          )}\n\n          <button\n            className={buttonClasses}\n            onClick={onNextPage}\n            disabled={currentPage >= totalPages}\n            aria-label=\"Next page\"\n          >\n            <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n            </svg>\n          </button>\n        </div>\n\n        {/* Zoom group */}\n        <div className=\"flex items-center\">\n          <button\n            className={buttonClasses}\n            onClick={onZoomOut}\n            aria-label=\"Zoom out\"\n          >\n            <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M20 12H4\" />\n            </svg>\n          </button>\n\n          <span className=\"text-xs text-gray-500 dark:text-gray-400 min-w-[40px] text-center\">\n            {Math.round(scale * 100)}%\n          </span>\n\n          <button\n            className={buttonClasses}\n            onClick={onZoomIn}\n            aria-label=\"Zoom in\"\n          >\n            <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n            </svg>\n          </button>\n        </div>\n\n        {/* More menu */}\n        <div className=\"relative\">\n          <button\n            className={cn(buttonClasses, showMoreMenu && 'bg-gray-100 dark:bg-gray-700')}\n            onClick={toggleMoreMenu}\n            aria-label=\"More options\"\n          >\n            <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z\" />\n            </svg>\n          </button>\n\n          {/* More menu dropdown */}\n          {showMoreMenu && (\n            <>\n              <div\n                className=\"fixed inset-0 z-40\"\n                onClick={() => setShowMoreMenu(false)}\n              />\n              <div\n                className={cn(\n                  'absolute right-0 z-50',\n                  'w-48 p-2',\n                  'bg-white dark:bg-gray-800',\n                  'rounded-lg shadow-lg',\n                  'border border-gray-200 dark:border-gray-700',\n                  position === 'bottom' ? 'bottom-full mb-2' : 'top-full mt-2'\n                )}\n              >\n                {/* Theme options */}\n                <div className=\"px-2 py-1 text-xs text-gray-500 dark:text-gray-400 font-medium\">\n                  Theme\n                </div>\n                {(['light', 'dark', 'sepia'] as const).map((t) => (\n                  <button\n                    key={t}\n                    className={cn(\n                      'w-full px-3 py-2 text-left text-sm rounded-lg',\n                      'flex items-center gap-2',\n                      theme === t\n                        ? 'bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300'\n                        : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300'\n                    )}\n                    onClick={() => {\n                      onThemeChange(t);\n                      setShowMoreMenu(false);\n                    }}\n                  >\n                    <span className=\"capitalize\">{t}</span>\n                    {theme === t && (\n                      <svg className=\"w-4 h-4 ml-auto\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                        <path fillRule=\"evenodd\" d=\"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z\" clipRule=\"evenodd\" />\n                      </svg>\n                    )}\n                  </button>\n                ))}\n              </div>\n            </>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n});\n","export { Toolbar, type ToolbarProps } from './Toolbar';\nexport { MobileToolbar, type MobileToolbarProps } from './MobileToolbar';\n","import { useEffect, useRef, useState, memo, useCallback } from 'react';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport { usePDFViewer } from '../../hooks';\nimport { cn } from '../../utils';\n\nexport interface ThumbnailPanelProps {\n  className?: string;\n  thumbnailScale?: number;\n}\n\ninterface ThumbnailProps {\n  document: PDFDocumentProxy;\n  pageNumber: number;\n  isActive: boolean;\n  onClick: () => void;\n  scale: number;\n}\n\nconst Thumbnail = memo(function Thumbnail({\n  document,\n  pageNumber,\n  isActive,\n  onClick,\n  scale,\n}: ThumbnailProps) {\n  const buttonRef = useRef<HTMLButtonElement>(null);\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const [isRendered, setIsRendered] = useState(false);\n  // Don't fetch the PDF page until the thumbnail scrolls into the panel's\n  // viewport. Without this gate, mounting the panel for a 1000-page PDF\n  // immediately fires `getPage(n)` for every page — the same kind of\n  // pre-fetch that makes a 400 MB book load entirely just to show the\n  // sidebar.\n  const [shouldRender, setShouldRender] = useState(false);\n\n  useEffect(() => {\n    if (shouldRender) return;\n    const el = buttonRef.current;\n    if (!el) return;\n\n    if (typeof IntersectionObserver === 'undefined') {\n      // Fallback for very old browsers — render immediately. Functionally\n      // equivalent to the old behaviour.\n      setShouldRender(true);\n      return;\n    }\n\n    const observer = new IntersectionObserver(\n      (entries) => {\n        for (const entry of entries) {\n          if (entry.isIntersecting) {\n            setShouldRender(true);\n            observer.disconnect();\n            break;\n          }\n        }\n      },\n      // 200px root margin so the page is fetched just before it scrolls\n      // into view, hiding the render latency.\n      { rootMargin: '200px' }\n    );\n    observer.observe(el);\n    return () => observer.disconnect();\n  }, [shouldRender]);\n\n  useEffect(() => {\n    if (!shouldRender) return;\n    let cancelled = false;\n\n    const renderThumbnail = async () => {\n      const canvas = canvasRef.current;\n      if (!canvas) return;\n\n      try {\n        const page = await document.getPage(pageNumber);\n        if (cancelled) return;\n\n        const viewport = page.getViewport({ scale });\n        const context = canvas.getContext('2d');\n\n        if (!context) return;\n\n        canvas.width = viewport.width;\n        canvas.height = viewport.height;\n\n        await page.render({\n          canvasContext: context,\n          viewport,\n        }).promise;\n\n        if (!cancelled) {\n          setIsRendered(true);\n        }\n      } catch (error) {\n        if (!cancelled) {\n          // Silently ignore errors from document switching/destruction\n          const errorMessage = error instanceof Error ? error.message : String(error);\n          const isDocumentDestroyed =\n            errorMessage.includes('destroyed') ||\n            errorMessage.includes('sendWithStream') ||\n            errorMessage.includes('sendWithPromise') ||\n            errorMessage.includes('Cannot read properties of null');\n          if (!isDocumentDestroyed) {\n            console.error(`Error rendering thumbnail for page ${pageNumber}:`, error);\n          }\n        }\n      }\n    };\n\n    renderThumbnail();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [document, pageNumber, scale, shouldRender]);\n\n  return (\n    <button\n      ref={buttonRef}\n      onClick={onClick}\n      className={cn(\n        'thumbnail-item',\n        'flex flex-col items-center p-2 rounded',\n        'hover:bg-gray-100 dark:hover:bg-gray-700',\n        'focus:outline-none focus:ring-2 focus:ring-blue-500',\n        isActive && 'bg-blue-50 dark:bg-blue-900/30 ring-2 ring-blue-500'\n      )}\n    >\n      <div\n        className={cn(\n          'relative bg-white shadow-md',\n          !isRendered && 'animate-pulse bg-gray-200'\n        )}\n      >\n        <canvas ref={canvasRef} className=\"block\" />\n      </div>\n      <span className=\"mt-1 text-xs text-gray-600 dark:text-gray-400\">\n        {pageNumber}\n      </span>\n    </button>\n  );\n});\n\nexport const ThumbnailPanel = memo(function ThumbnailPanel({\n  className,\n  thumbnailScale = 0.2,\n}: ThumbnailPanelProps) {\n  const { document, currentPage, numPages, goToPage } = usePDFViewer();\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  // Scroll to active thumbnail when page changes\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    const activeThumb = container.querySelector(`[data-page=\"${currentPage}\"]`);\n    if (activeThumb) {\n      activeThumb.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n    }\n  }, [currentPage]);\n\n  const handleThumbnailClick = useCallback(\n    (pageNumber: number) => {\n      goToPage(pageNumber);\n    },\n    [goToPage]\n  );\n\n  if (!document) {\n    return null; // Loading screen in main container handles this\n  }\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        'thumbnail-panel',\n        'overflow-y-auto p-2',\n        'grid grid-cols-1 gap-2',\n        className\n      )}\n    >\n      {Array.from({ length: numPages }, (_, i) => i + 1).map((pageNumber) => (\n        <div key={pageNumber} data-page={pageNumber}>\n          <Thumbnail\n            document={document}\n            pageNumber={pageNumber}\n            isActive={pageNumber === currentPage}\n            onClick={() => handleThumbnailClick(pageNumber)}\n            scale={thumbnailScale}\n          />\n        </div>\n      ))}\n    </div>\n  );\n});\n","import { memo, useCallback, useState, useEffect, useRef } from 'react';\nimport { usePDFViewer, useSearchStore, usePDFViewerStores } from '../../hooks';\nimport { cn } from '../../utils';\n\nexport interface SearchPanelProps {\n  className?: string;\n}\n\nexport const SearchPanel = memo(function SearchPanel({ className }: SearchPanelProps) {\n  const { searchStore } = usePDFViewerStores();\n  const {\n    searchQuery,\n    searchResults,\n    currentSearchResult,\n    isSearching,\n    search,\n    clearSearch,\n    nextSearchResult,\n    previousSearchResult,\n    goToPage,\n  } = usePDFViewer();\n\n  const caseSensitive = useSearchStore((s) => s.caseSensitive);\n  const wholeWord = useSearchStore((s) => s.wholeWord);\n  const toggleCaseSensitive = useSearchStore((s) => s.toggleCaseSensitive);\n  const toggleWholeWord = useSearchStore((s) => s.toggleWholeWord);\n\n  const [inputValue, setInputValue] = useState(searchQuery);\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  // Focus input on mount\n  useEffect(() => {\n    inputRef.current?.focus();\n  }, []);\n\n  const handleSearch = useCallback(() => {\n    if (inputValue.trim()) {\n      search(inputValue.trim());\n    }\n  }, [inputValue, search]);\n\n  const handleKeyDown = useCallback(\n    (e: React.KeyboardEvent) => {\n      if (e.key === 'Enter') {\n        if (e.shiftKey) {\n          previousSearchResult();\n        } else if (searchResults.length > 0) {\n          nextSearchResult();\n        } else {\n          handleSearch();\n        }\n      } else if (e.key === 'Escape') {\n        clearSearch();\n        setInputValue('');\n      }\n    },\n    [handleSearch, searchResults, nextSearchResult, previousSearchResult, clearSearch]\n  );\n\n  const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n    setInputValue(e.target.value);\n  }, []);\n\n  const handleClear = useCallback(() => {\n    clearSearch();\n    setInputValue('');\n    inputRef.current?.focus();\n  }, [clearSearch]);\n\n  const handleResultClick = useCallback(\n    (pageNumber: number, resultIndex: number) => {\n      goToPage(pageNumber);\n      // Navigate to specific result\n      searchStore.getState().goToResult(resultIndex);\n    },\n    [goToPage, searchStore]\n  );\n\n  return (\n    <div className={cn('search-panel', 'flex flex-col h-full', className)}>\n      {/* Search input */}\n      <div className=\"p-3 border-b border-gray-200 dark:border-gray-700\">\n        <div className=\"relative\">\n          <input\n            ref={inputRef}\n            type=\"text\"\n            value={inputValue}\n            onChange={handleInputChange}\n            onKeyDown={handleKeyDown}\n            placeholder=\"Search in document...\"\n            className={cn(\n              'w-full px-3 py-2 pr-8',\n              'border rounded-md',\n              'text-sm',\n              'focus:outline-none focus:ring-2 focus:ring-blue-500',\n              'dark:bg-gray-700 dark:border-gray-600 dark:text-white'\n            )}\n          />\n          {inputValue && (\n            <button\n              onClick={handleClear}\n              className=\"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600\"\n              aria-label=\"Clear search\"\n            >\n              <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M6 18L18 6M6 6l12 12\"\n                />\n              </svg>\n            </button>\n          )}\n        </div>\n\n        {/* Search options */}\n        <div className=\"flex items-center gap-4 mt-2\">\n          <label className=\"flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400 cursor-pointer\">\n            <input\n              type=\"checkbox\"\n              checked={caseSensitive}\n              onChange={toggleCaseSensitive}\n              className=\"rounded\"\n            />\n            Match case\n          </label>\n          <label className=\"flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400 cursor-pointer\">\n            <input\n              type=\"checkbox\"\n              checked={wholeWord}\n              onChange={toggleWholeWord}\n              className=\"rounded\"\n            />\n            Whole word\n          </label>\n        </div>\n\n        {/* Results navigation */}\n        {searchResults.length > 0 && (\n          <div className=\"flex items-center justify-between mt-2\">\n            <span className=\"text-xs text-gray-600 dark:text-gray-400\">\n              {currentSearchResult + 1} of {searchResults.length} results\n            </span>\n            <div className=\"flex gap-1\">\n              <button\n                onClick={previousSearchResult}\n                className=\"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700\"\n                title=\"Previous result\"\n              >\n                <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n                  <path\n                    strokeLinecap=\"round\"\n                    strokeLinejoin=\"round\"\n                    strokeWidth={2}\n                    d=\"M5 15l7-7 7 7\"\n                  />\n                </svg>\n              </button>\n              <button\n                onClick={nextSearchResult}\n                className=\"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700\"\n                title=\"Next result\"\n              >\n                <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n                  <path\n                    strokeLinecap=\"round\"\n                    strokeLinejoin=\"round\"\n                    strokeWidth={2}\n                    d=\"M19 9l-7 7-7-7\"\n                  />\n                </svg>\n              </button>\n            </div>\n          </div>\n        )}\n\n        {isSearching && (\n          <div className=\"mt-2 text-xs text-gray-500\">Searching...</div>\n        )}\n      </div>\n\n      {/* Results list */}\n      <div className=\"flex-1 overflow-y-auto\">\n        {searchResults.length === 0 && searchQuery && !isSearching && (\n          <div className=\"p-4 text-sm text-gray-500 text-center\">\n            No results found for \"{searchQuery}\"\n          </div>\n        )}\n\n        {searchResults.length > 0 && (\n          <ul className=\"divide-y divide-gray-100 dark:divide-gray-700\">\n            {searchResults.map((result, index) => (\n              <li key={`${result.pageNumber}-${result.matchIndex}`}>\n                <button\n                  onClick={() => handleResultClick(result.pageNumber, index)}\n                  className={cn(\n                    'w-full px-3 py-2 text-left',\n                    'hover:bg-gray-50 dark:hover:bg-gray-700',\n                    'focus:outline-none focus:bg-gray-50 dark:focus:bg-gray-700',\n                    index === currentSearchResult && 'bg-blue-50 dark:bg-blue-900/30'\n                  )}\n                >\n                  <div className=\"text-xs text-gray-500 dark:text-gray-400\">\n                    Page {result.pageNumber}\n                  </div>\n                  <div className=\"text-sm truncate\">{result.text}</div>\n                </button>\n              </li>\n            ))}\n          </ul>\n        )}\n      </div>\n    </div>\n  );\n});\n","import { memo, useCallback, useEffect, useState } from 'react';\nimport { usePDFViewer } from '../../hooks';\nimport { cn } from '../../utils';\nimport type { OutlineItem } from '../../types';\n\nexport interface OutlinePanelProps {\n  className?: string;\n}\n\ninterface OutlineNodeProps {\n  item: OutlineItem;\n  level: number;\n  onNavigate: (pageNumber: number) => void;\n}\n\nconst OutlineNode = memo(function OutlineNode({\n  item,\n  level,\n  onNavigate,\n}: OutlineNodeProps) {\n  const [isExpanded, setIsExpanded] = useState(item.expanded ?? level < 2);\n  const hasChildren = item.children && item.children.length > 0;\n\n  const handleClick = useCallback(() => {\n    if (item.pageNumber > 0) {\n      onNavigate(item.pageNumber);\n    }\n  }, [item.pageNumber, onNavigate]);\n\n  const handleToggle = useCallback((e: React.MouseEvent) => {\n    e.stopPropagation();\n    setIsExpanded(!isExpanded);\n  }, [isExpanded]);\n\n  return (\n    <div className=\"outline-node\">\n      <div\n        className={cn(\n          'flex items-center gap-1 py-1.5 px-2 rounded cursor-pointer',\n          'hover:bg-gray-100 dark:hover:bg-gray-700',\n          'text-sm text-gray-700 dark:text-gray-300',\n          'transition-colors'\n        )}\n        style={{ paddingLeft: `${level * 12 + 8}px` }}\n        onClick={handleClick}\n        role=\"button\"\n        tabIndex={0}\n        onKeyDown={(e) => {\n          if (e.key === 'Enter' || e.key === ' ') {\n            handleClick();\n          }\n        }}\n      >\n        {/* Expand/collapse toggle */}\n        {hasChildren ? (\n          <button\n            onClick={handleToggle}\n            className=\"p-0.5 hover:bg-gray-200 dark:hover:bg-gray-600 rounded\"\n            aria-label={isExpanded ? 'Collapse' : 'Expand'}\n          >\n            <svg\n              className={cn(\n                'w-3 h-3 transition-transform',\n                isExpanded && 'rotate-90'\n              )}\n              fill=\"none\"\n              stroke=\"currentColor\"\n              viewBox=\"0 0 24 24\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M9 5l7 7-7 7\"\n              />\n            </svg>\n          </button>\n        ) : (\n          <span className=\"w-4\" /> // Spacer for alignment\n        )}\n\n        {/* Title */}\n        <span className=\"flex-1 truncate\" title={item.title}>\n          {item.title}\n        </span>\n\n        {/* Page number */}\n        {item.pageNumber > 0 && (\n          <span className=\"text-xs text-gray-400 dark:text-gray-500 ml-2\">\n            {item.pageNumber}\n          </span>\n        )}\n      </div>\n\n      {/* Children */}\n      {hasChildren && isExpanded && (\n        <div className=\"outline-children\">\n          {item.children.map((child, index) => (\n            <OutlineNode\n              key={`${child.title}-${index}`}\n              item={child}\n              level={level + 1}\n              onNavigate={onNavigate}\n            />\n          ))}\n        </div>\n      )}\n    </div>\n  );\n});\n\nexport const OutlinePanel = memo(function OutlinePanel({\n  className,\n}: OutlinePanelProps) {\n  const { document, goToPage } = usePDFViewer();\n  const [outline, setOutline] = useState<OutlineItem[] | null>(null);\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n\n  // Load outline when document changes\n  useEffect(() => {\n    if (!document) {\n      setOutline(null);\n      return;\n    }\n\n    let cancelled = false;\n    setIsLoading(true);\n    setError(null);\n\n    const loadOutline = async () => {\n      try {\n        const rawOutline = await document.getOutline();\n\n        if (cancelled) return;\n\n        if (!rawOutline || rawOutline.length === 0) {\n          setOutline([]);\n          return;\n        }\n\n        // Convert PDF.js outline format to our OutlineItem format\n        const convertOutlineItem = async (item: {\n          title: string;\n          dest: string | unknown[] | null;\n          items: unknown[];\n        }): Promise<OutlineItem> => {\n          let pageNumber = 0;\n\n          // Try to resolve the destination to a page number\n          if (item.dest) {\n            try {\n              let destRef: unknown;\n              if (typeof item.dest === 'string') {\n                destRef = await document.getDestination(item.dest);\n              } else {\n                destRef = item.dest;\n              }\n\n              if (Array.isArray(destRef) && destRef[0]) {\n                const pageIndex = await document.getPageIndex(destRef[0]);\n                pageNumber = pageIndex + 1; // Convert to 1-indexed\n              }\n            } catch {\n              // Destination resolution failed, leave pageNumber as 0\n            }\n          }\n\n          const children: OutlineItem[] = [];\n          if (item.items && item.items.length > 0) {\n            for (const child of item.items) {\n              children.push(await convertOutlineItem(child as typeof item));\n            }\n          }\n\n          return {\n            title: item.title || 'Untitled',\n            pageNumber,\n            children,\n          };\n        };\n\n        const convertedOutline: OutlineItem[] = [];\n        for (const item of rawOutline) {\n          convertedOutline.push(await convertOutlineItem(item));\n        }\n\n        if (!cancelled) {\n          setOutline(convertedOutline);\n        }\n      } catch (err) {\n        if (!cancelled) {\n          console.error('Failed to load outline:', err);\n          setError('Failed to load document outline');\n        }\n      } finally {\n        if (!cancelled) {\n          setIsLoading(false);\n        }\n      }\n    };\n\n    loadOutline();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [document]);\n\n  const handleNavigate = useCallback(\n    (pageNumber: number) => {\n      goToPage(pageNumber);\n    },\n    [goToPage]\n  );\n\n  if (!document) {\n    return null; // Loading screen in main container handles this\n  }\n\n  if (isLoading) {\n    return (\n      <div className={cn('flex items-center justify-center p-4', className)}>\n        <div className=\"flex items-center gap-2\">\n          <div className=\"w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin\" />\n          <span className=\"text-sm text-gray-500 dark:text-gray-400\">\n            Loading outline...\n          </span>\n        </div>\n      </div>\n    );\n  }\n\n  if (error) {\n    return (\n      <div className={cn('flex items-center justify-center p-4', className)}>\n        <p className=\"text-sm text-red-500\">{error}</p>\n      </div>\n    );\n  }\n\n  if (!outline || outline.length === 0) {\n    return (\n      <div className={cn('flex flex-col items-center justify-center p-4 gap-2', className)}>\n        <svg\n          className=\"w-12 h-12 text-gray-300 dark:text-gray-600\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          viewBox=\"0 0 24 24\"\n        >\n          <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth={1.5}\n            d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n          />\n        </svg>\n        <p className=\"text-sm text-gray-500 dark:text-gray-400 text-center\">\n          This document doesn&apos;t have an outline\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <div className={cn('outline-panel overflow-auto p-2', className)}>\n      {outline.map((item, index) => (\n        <OutlineNode\n          key={`${item.title}-${index}`}\n          item={item}\n          level={0}\n          onNavigate={handleNavigate}\n        />\n      ))}\n    </div>\n  );\n});\n","import { memo, useMemo, useCallback, useState } from 'react';\nimport { useAnnotationStore } from '../../hooks';\nimport { usePDFViewer } from '../../hooks';\nimport type { Highlight, HighlightColor } from '../../types';\nimport { cn } from '../../utils';\nimport { exportHighlightsAsJSON, exportHighlightsAsMarkdown } from '../../utils/highlight-storage';\n\nexport interface HighlightsPanelProps {\n  className?: string;\n  /** Callback when a highlight item is clicked */\n  onHighlightClick?: (highlight: Highlight) => void;\n}\n\nconst HIGHLIGHT_COLOR_DOT: Record<HighlightColor, string> = {\n  yellow: 'bg-yellow-400',\n  green: 'bg-green-400',\n  blue: 'bg-blue-400',\n  pink: 'bg-pink-400',\n  orange: 'bg-orange-400',\n};\n\ninterface HighlightItemProps {\n  highlight: Highlight;\n  isSelected: boolean;\n  onClick: () => void;\n  onDelete: () => void;\n}\n\nconst HighlightItem = memo(function HighlightItem({\n  highlight,\n  isSelected,\n  onClick,\n  onDelete,\n}: HighlightItemProps) {\n  return (\n    <div\n      className={cn(\n        'group p-3 rounded-lg cursor-pointer',\n        'border border-transparent',\n        'hover:bg-gray-50 dark:hover:bg-gray-700/50',\n        isSelected && 'bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800'\n      )}\n      onClick={onClick}\n    >\n      <div className=\"flex items-start gap-3\">\n        {/* Color dot */}\n        <div\n          className={cn(\n            'w-3 h-3 rounded-full mt-1 flex-shrink-0',\n            HIGHLIGHT_COLOR_DOT[highlight.color]\n          )}\n        />\n\n        <div className=\"flex-1 min-w-0\">\n          {/* Text preview */}\n          <p className=\"text-sm text-gray-700 dark:text-gray-200 line-clamp-2\">\n            &ldquo;{highlight.text}&rdquo;\n          </p>\n\n          {/* Comment if exists */}\n          {highlight.comment && (\n            <p className=\"mt-1 text-xs text-gray-500 dark:text-gray-400 line-clamp-1\">\n              {highlight.comment}\n            </p>\n          )}\n\n          {/* Page number and date */}\n          <p className=\"mt-1 text-xs text-gray-400 dark:text-gray-500\">\n            Page {highlight.pageNumber}\n          </p>\n        </div>\n\n        {/* Delete button */}\n        <button\n          onClick={(e) => {\n            e.stopPropagation();\n            onDelete();\n          }}\n          className={cn(\n            'p-1 rounded opacity-0 group-hover:opacity-100',\n            'text-gray-400 hover:text-red-500',\n            'hover:bg-red-50 dark:hover:bg-red-900/20',\n            'transition-opacity duration-150',\n            'focus:outline-none focus:opacity-100'\n          )}\n          title=\"Delete highlight\"\n          aria-label=\"Delete highlight\"\n        >\n          <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n            <path\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth={2}\n              d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n            />\n          </svg>\n        </button>\n      </div>\n    </div>\n  );\n});\n\ninterface PageGroupProps {\n  pageNumber: number;\n  highlights: Highlight[];\n  selectedId: string | null;\n  onHighlightClick: (highlight: Highlight) => void;\n  onDeleteHighlight: (id: string) => void;\n}\n\nconst PageGroup = memo(function PageGroup({\n  pageNumber,\n  highlights,\n  selectedId,\n  onHighlightClick,\n  onDeleteHighlight,\n}: PageGroupProps) {\n  return (\n    <div className=\"mb-4\">\n      <h3 className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2 px-3\">\n        Page {pageNumber}\n      </h3>\n      <div className=\"space-y-1\">\n        {highlights.map((highlight) => (\n          <HighlightItem\n            key={highlight.id}\n            highlight={highlight}\n            isSelected={highlight.id === selectedId}\n            onClick={() => onHighlightClick(highlight)}\n            onDelete={() => onDeleteHighlight(highlight.id)}\n          />\n        ))}\n      </div>\n    </div>\n  );\n});\n\ntype ExportFormat = 'json' | 'markdown';\n\nexport const HighlightsPanel = memo(function HighlightsPanel({\n  className,\n  onHighlightClick,\n}: HighlightsPanelProps) {\n  const highlights = useAnnotationStore((s) => s.highlights);\n  const selectedHighlightId = useAnnotationStore((s) => s.selectedHighlightId);\n  const removeHighlight = useAnnotationStore((s) => s.removeHighlight);\n  const selectHighlight = useAnnotationStore((s) => s.selectHighlight);\n  const { goToPage } = usePDFViewer();\n  const [showExportMenu, setShowExportMenu] = useState(false);\n\n  // Group highlights by page\n  const groupedHighlights = useMemo(() => {\n    const groups = new Map<number, Highlight[]>();\n\n    // Sort highlights by page number, then by position (y coordinate)\n    const sorted = [...highlights].sort((a, b) => {\n      if (a.pageNumber !== b.pageNumber) return a.pageNumber - b.pageNumber;\n      const aY = a.rects[0]?.y ?? 0;\n      const bY = b.rects[0]?.y ?? 0;\n      return aY - bY;\n    });\n\n    sorted.forEach((highlight) => {\n      const page = highlight.pageNumber;\n      if (!groups.has(page)) {\n        groups.set(page, []);\n      }\n      groups.get(page)!.push(highlight);\n    });\n\n    return Array.from(groups.entries()).sort(([a], [b]) => a - b);\n  }, [highlights]);\n\n  const handleHighlightClick = useCallback(\n    (highlight: Highlight) => {\n      selectHighlight(highlight.id);\n      goToPage(highlight.pageNumber);\n      onHighlightClick?.(highlight);\n    },\n    [selectHighlight, goToPage, onHighlightClick]\n  );\n\n  const handleDeleteHighlight = useCallback(\n    (id: string) => {\n      removeHighlight(id);\n    },\n    [removeHighlight]\n  );\n\n  const handleExport = useCallback(\n    (format: ExportFormat) => {\n      let content: string;\n      let filename: string;\n      let mimeType: string;\n\n      if (format === 'json') {\n        content = exportHighlightsAsJSON(highlights);\n        filename = 'highlights.json';\n        mimeType = 'application/json';\n      } else {\n        content = exportHighlightsAsMarkdown(highlights);\n        filename = 'highlights.md';\n        mimeType = 'text/markdown';\n      }\n\n      // Create download link\n      const blob = new Blob([content], { type: mimeType });\n      const url = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = url;\n      a.download = filename;\n      document.body.appendChild(a);\n      a.click();\n      document.body.removeChild(a);\n      URL.revokeObjectURL(url);\n\n      setShowExportMenu(false);\n    },\n    [highlights]\n  );\n\n  return (\n    <div className={cn('flex flex-col h-full', className)}>\n      {/* Header */}\n      <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n        <h2 className=\"text-sm font-semibold text-gray-700 dark:text-gray-200\">\n          Highlights ({highlights.length})\n        </h2>\n\n        {/* Export button */}\n        {highlights.length > 0 && (\n          <div className=\"relative\">\n            <button\n              onClick={() => setShowExportMenu(!showExportMenu)}\n              className={cn(\n                'p-1.5 rounded-md',\n                'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200',\n                'hover:bg-gray-100 dark:hover:bg-gray-700',\n                'focus:outline-none focus:ring-2 focus:ring-blue-500'\n              )}\n              title=\"Export highlights\"\n              aria-label=\"Export highlights\"\n            >\n              <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12\"\n                />\n              </svg>\n            </button>\n\n            {/* Export dropdown menu */}\n            {showExportMenu && (\n              <div\n                className={cn(\n                  'absolute right-0 mt-1 py-1 w-40',\n                  'bg-white dark:bg-gray-800',\n                  'rounded-lg shadow-lg',\n                  'border border-gray-200 dark:border-gray-700',\n                  'z-10'\n                )}\n              >\n                <button\n                  onClick={() => handleExport('json')}\n                  className={cn(\n                    'w-full px-4 py-2 text-left text-sm',\n                    'text-gray-700 dark:text-gray-200',\n                    'hover:bg-gray-100 dark:hover:bg-gray-700'\n                  )}\n                >\n                  Export as JSON\n                </button>\n                <button\n                  onClick={() => handleExport('markdown')}\n                  className={cn(\n                    'w-full px-4 py-2 text-left text-sm',\n                    'text-gray-700 dark:text-gray-200',\n                    'hover:bg-gray-100 dark:hover:bg-gray-700'\n                  )}\n                >\n                  Export as Markdown\n                </button>\n              </div>\n            )}\n          </div>\n        )}\n      </div>\n\n      {/* Highlight list */}\n      <div className=\"flex-1 overflow-y-auto p-2\">\n        {highlights.length === 0 ? (\n          <div className=\"flex flex-col items-center justify-center h-full text-center p-4\">\n            <svg\n              className=\"w-12 h-12 text-gray-300 dark:text-gray-600 mb-3\"\n              fill=\"none\"\n              viewBox=\"0 0 24 24\"\n              stroke=\"currentColor\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={1.5}\n                d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\"\n              />\n            </svg>\n            <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n              No highlights yet\n            </p>\n            <p className=\"text-xs text-gray-400 dark:text-gray-500 mt-1\">\n              Select text in the PDF and click a color to create a highlight\n            </p>\n          </div>\n        ) : (\n          groupedHighlights.map(([pageNumber, pageHighlights]) => (\n            <PageGroup\n              key={pageNumber}\n              pageNumber={pageNumber}\n              highlights={pageHighlights}\n              selectedId={selectedHighlightId}\n              onHighlightClick={handleHighlightClick}\n              onDeleteHighlight={handleDeleteHighlight}\n            />\n          ))\n        )}\n      </div>\n    </div>\n  );\n});\n\nexport default HighlightsPanel;\n","import { memo } from 'react';\nimport { usePDFViewer } from '../../hooks';\nimport { ThumbnailPanel } from './ThumbnailPanel';\nimport { SearchPanel } from './SearchPanel';\nimport { OutlinePanel } from './OutlinePanel';\nimport { HighlightsPanel } from './HighlightsPanel';\nimport { cn } from '../../utils';\nimport type { SidebarPanel as SidebarPanelType } from '../../types';\n\nexport interface SidebarProps {\n  className?: string;\n  width?: number;\n}\n\ninterface SidebarTabProps {\n  id: SidebarPanelType;\n  icon: React.ReactNode;\n  title: string;\n  isActive: boolean;\n  onClick: () => void;\n}\n\nconst SidebarTab = memo(function SidebarTab({\n  icon,\n  title,\n  isActive,\n  onClick,\n}: SidebarTabProps) {\n  return (\n    <button\n      onClick={onClick}\n      className={cn(\n        'p-3 flex items-center justify-center',\n        'hover:bg-gray-100 dark:hover:bg-gray-700',\n        'focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500',\n        isActive && 'bg-gray-100 dark:bg-gray-700 border-l-2 border-blue-500'\n      )}\n      title={title}\n      aria-label={title}\n      aria-selected={isActive}\n      role=\"tab\"\n    >\n      {icon}\n    </button>\n  );\n});\n\nexport const Sidebar = memo(function Sidebar({\n  className,\n  width = 280,\n}: SidebarProps) {\n  const { sidebarOpen, sidebarPanel, setSidebarPanel } = usePDFViewer();\n\n  if (!sidebarOpen) {\n    return null;\n  }\n\n  const tabs: Array<{\n    id: SidebarPanelType;\n    icon: React.ReactNode;\n    title: string;\n  }> = [\n    {\n      id: 'thumbnails',\n      title: 'Thumbnails',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n          <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth={2}\n            d=\"M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\"\n          />\n        </svg>\n      ),\n    },\n    {\n      id: 'search',\n      title: 'Search',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n          <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth={2}\n            d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n          />\n        </svg>\n      ),\n    },\n    {\n      id: 'outline',\n      title: 'Outline',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n          <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth={2}\n            d=\"M4 6h16M4 10h16M4 14h16M4 18h16\"\n          />\n        </svg>\n      ),\n    },\n    {\n      id: 'annotations',\n      title: 'Annotations',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n          <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth={2}\n            d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\"\n          />\n        </svg>\n      ),\n    },\n  ];\n\n  const renderPanel = () => {\n    switch (sidebarPanel) {\n      case 'thumbnails':\n        return <ThumbnailPanel className=\"flex-1\" />;\n      case 'search':\n        return <SearchPanel className=\"flex-1\" />;\n      case 'outline':\n        return <OutlinePanel className=\"flex-1\" />;\n      case 'annotations':\n        return <HighlightsPanel className=\"flex-1\" />;\n      default:\n        return null;\n    }\n  };\n\n  return (\n    <div\n      className={cn(\n        'pdf-sidebar',\n        'flex h-full',\n        'bg-white dark:bg-gray-800',\n        'border-r border-gray-200 dark:border-gray-700',\n        className\n      )}\n      style={{ width }}\n    >\n      {/* Tab bar */}\n      <div\n        className={cn(\n          'flex flex-col',\n          'border-r border-gray-200 dark:border-gray-700',\n          'bg-gray-50 dark:bg-gray-900'\n        )}\n        role=\"tablist\"\n        aria-orientation=\"vertical\"\n      >\n        {tabs.map((tab) => (\n          <SidebarTab\n            key={tab.id}\n            id={tab.id}\n            icon={tab.icon}\n            title={tab.title}\n            isActive={sidebarPanel === tab.id}\n            onClick={() => setSidebarPanel(tab.id)}\n          />\n        ))}\n      </div>\n\n      {/* Panel content */}\n      <div className=\"flex-1 flex flex-col overflow-hidden\">{renderPanel()}</div>\n    </div>\n  );\n});\n","import { memo, useCallback, useRef, useEffect, useState } from 'react';\nimport { cn } from '../../utils';\nimport type { SidebarPanel } from '../../types';\n\nexport interface MobileSidebarProps {\n  isOpen: boolean;\n  onClose: () => void;\n  activePanel: SidebarPanel;\n  onPanelChange: (panel: SidebarPanel) => void;\n  children: React.ReactNode;\n  className?: string;\n}\n\nconst SWIPE_THRESHOLD = 50;\n\nexport const MobileSidebar = memo(function MobileSidebar({\n  isOpen,\n  onClose,\n  activePanel,\n  onPanelChange,\n  children,\n  className,\n}: MobileSidebarProps) {\n  const sidebarRef = useRef<HTMLDivElement>(null);\n  const startXRef = useRef(0);\n  const [translateX, setTranslateX] = useState(0);\n  const [isDragging, setIsDragging] = useState(false);\n\n  // Handle touch start\n  const handleTouchStart = useCallback((e: React.TouchEvent) => {\n    startXRef.current = e.touches[0].clientX;\n    setIsDragging(true);\n  }, []);\n\n  // Handle touch move\n  const handleTouchMove = useCallback((e: React.TouchEvent) => {\n    if (!isDragging) return;\n\n    const currentX = e.touches[0].clientX;\n    const diff = currentX - startXRef.current;\n\n    // Only allow dragging to the left (to close)\n    if (diff < 0) {\n      setTranslateX(diff);\n    }\n  }, [isDragging]);\n\n  // Handle touch end\n  const handleTouchEnd = useCallback(() => {\n    setIsDragging(false);\n\n    // If dragged past threshold, close the sidebar\n    if (translateX < -SWIPE_THRESHOLD) {\n      onClose();\n    }\n\n    setTranslateX(0);\n  }, [translateX, onClose]);\n\n  // Close on escape key\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.key === 'Escape' && isOpen) {\n        onClose();\n      }\n    };\n\n    document.addEventListener('keydown', handleKeyDown);\n    return () => document.removeEventListener('keydown', handleKeyDown);\n  }, [isOpen, onClose]);\n\n  // Prevent body scroll when open\n  useEffect(() => {\n    if (isOpen) {\n      document.body.style.overflow = 'hidden';\n    } else {\n      document.body.style.overflow = '';\n    }\n\n    return () => {\n      document.body.style.overflow = '';\n    };\n  }, [isOpen]);\n\n  const panels: { id: SidebarPanel; label: string; icon: React.ReactNode }[] = [\n    {\n      id: 'thumbnails',\n      label: 'Pages',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\" />\n        </svg>\n      ),\n    },\n    {\n      id: 'search',\n      label: 'Search',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n        </svg>\n      ),\n    },\n    {\n      id: 'outline',\n      label: 'Outline',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 6h16M4 10h16M4 14h16M4 18h16\" />\n        </svg>\n      ),\n    },\n    {\n      id: 'annotations',\n      label: 'Notes',\n      icon: (\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\" />\n        </svg>\n      ),\n    },\n  ];\n\n  return (\n    <>\n      {/* Backdrop */}\n      <div\n        className={cn(\n          'fixed inset-0 z-40 bg-black/50 transition-opacity duration-300',\n          isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'\n        )}\n        onClick={onClose}\n        aria-hidden=\"true\"\n      />\n\n      {/* Sidebar drawer */}\n      <div\n        ref={sidebarRef}\n        className={cn(\n          'mobile-sidebar',\n          'fixed inset-y-0 left-0 z-50',\n          'w-[85vw] max-w-[320px]',\n          'bg-white dark:bg-gray-800',\n          'shadow-2xl',\n          'transform transition-transform duration-300 ease-out',\n          isOpen ? 'translate-x-0' : '-translate-x-full',\n          className\n        )}\n        style={{\n          transform: isOpen\n            ? `translateX(${translateX}px)`\n            : 'translateX(-100%)',\n        }}\n        onTouchStart={handleTouchStart}\n        onTouchMove={handleTouchMove}\n        onTouchEnd={handleTouchEnd}\n      >\n        {/* Header */}\n        <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n          <h2 className=\"text-lg font-semibold text-gray-900 dark:text-gray-100\">\n            {panels.find((p) => p.id === activePanel)?.label || 'Menu'}\n          </h2>\n          <button\n            className={cn(\n              'p-2 -mr-2 rounded-lg',\n              'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200',\n              'hover:bg-gray-100 dark:hover:bg-gray-700',\n              'min-w-[44px] min-h-[44px] flex items-center justify-center'\n            )}\n            onClick={onClose}\n            aria-label=\"Close sidebar\"\n          >\n            <svg className=\"w-6 h-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n            </svg>\n          </button>\n        </div>\n\n        {/* Panel tabs */}\n        <div className=\"flex border-b border-gray-200 dark:border-gray-700\">\n          {panels.map((panel) => (\n            <button\n              key={panel.id}\n              className={cn(\n                'flex-1 py-3 flex flex-col items-center gap-1',\n                'text-xs font-medium transition-colors',\n                'min-h-[60px]',\n                activePanel === panel.id\n                  ? 'text-blue-600 dark:text-blue-400 border-b-2 border-blue-600 dark:border-blue-400 -mb-[2px]'\n                  : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'\n              )}\n              onClick={() => onPanelChange(panel.id)}\n            >\n              {panel.icon}\n              <span>{panel.label}</span>\n            </button>\n          ))}\n        </div>\n\n        {/* Panel content */}\n        <div className=\"flex-1 overflow-auto\">\n          {children}\n        </div>\n\n        {/* Swipe indicator */}\n        <div className=\"absolute top-1/2 -translate-y-1/2 right-0 w-1 h-16 bg-gray-300 dark:bg-gray-600 rounded-l-full opacity-50\" />\n      </div>\n    </>\n  );\n});\n","import { memo, useMemo, useCallback, useState } from 'react';\nimport { useStudentStore, useViewerStore } from '../../hooks';\nimport type { Bookmark } from '../../types/agent-context';\nimport { cn } from '../../utils';\n\nexport interface BookmarksPanelProps {\n  className?: string;\n  /** Callback when a bookmark item is clicked */\n  onBookmarkClick?: (bookmark: Bookmark) => void;\n}\n\ninterface BookmarkItemProps {\n  bookmark: Bookmark;\n  isSelected: boolean;\n  onClick: () => void;\n  onDelete: () => void;\n  onEdit: () => void;\n}\n\nconst BookmarkItem = memo(function BookmarkItem({\n  bookmark,\n  isSelected,\n  onClick,\n  onDelete,\n  onEdit,\n}: BookmarkItemProps) {\n  return (\n    <div\n      className={cn(\n        'group p-3 rounded-lg cursor-pointer',\n        'border border-transparent',\n        'hover:bg-gray-50 dark:hover:bg-gray-700/50',\n        isSelected && 'bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800'\n      )}\n      onClick={onClick}\n    >\n      <div className=\"flex items-start gap-3\">\n        {/* Bookmark icon */}\n        <div className=\"mt-0.5 flex-shrink-0\">\n          <svg\n            className=\"w-4 h-4 text-blue-500\"\n            fill=\"currentColor\"\n            viewBox=\"0 0 24 24\"\n          >\n            <path d=\"M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z\" />\n          </svg>\n        </div>\n\n        <div className=\"flex-1 min-w-0\">\n          {/* Label or page number */}\n          <p className=\"text-sm font-medium text-gray-700 dark:text-gray-200\">\n            {bookmark.label || `Page ${bookmark.pageNumber}`}\n          </p>\n\n          {/* User note if exists */}\n          {bookmark.userNote && (\n            <p className=\"mt-1 text-xs text-gray-600 dark:text-gray-300 line-clamp-2\">\n              {bookmark.userNote}\n            </p>\n          )}\n\n          {/* Agent context if exists */}\n          {bookmark.agentContext && (\n            <p className=\"mt-1 text-xs text-blue-500 dark:text-blue-400 line-clamp-1 italic\">\n              AI: &ldquo;{bookmark.agentContext}&rdquo;\n            </p>\n          )}\n\n          {/* Timestamp */}\n          <p className=\"mt-1 text-xs text-gray-400 dark:text-gray-500\">\n            {bookmark.timestamp.toLocaleDateString()} at{' '}\n            {bookmark.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}\n          </p>\n        </div>\n\n        {/* Action buttons */}\n        <div className=\"flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n          <button\n            onClick={(e) => {\n              e.stopPropagation();\n              onEdit();\n            }}\n            className={cn(\n              'p-1 rounded',\n              'text-gray-400 hover:text-blue-500',\n              'hover:bg-blue-50 dark:hover:bg-blue-900/20',\n              'focus:outline-none focus:opacity-100'\n            )}\n            title=\"Edit bookmark\"\n            aria-label=\"Edit bookmark\"\n          >\n            <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n              />\n            </svg>\n          </button>\n          <button\n            onClick={(e) => {\n              e.stopPropagation();\n              onDelete();\n            }}\n            className={cn(\n              'p-1 rounded',\n              'text-gray-400 hover:text-red-500',\n              'hover:bg-red-50 dark:hover:bg-red-900/20',\n              'focus:outline-none focus:opacity-100'\n            )}\n            title=\"Delete bookmark\"\n            aria-label=\"Delete bookmark\"\n          >\n            <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n              />\n            </svg>\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n});\n\ninterface PageGroupProps {\n  pageNumber: number;\n  bookmarks: Bookmark[];\n  currentPage: number;\n  onBookmarkClick: (bookmark: Bookmark) => void;\n  onDeleteBookmark: (id: string) => void;\n  onEditBookmark: (bookmark: Bookmark) => void;\n}\n\nconst PageGroup = memo(function PageGroup({\n  pageNumber,\n  bookmarks,\n  currentPage,\n  onBookmarkClick,\n  onDeleteBookmark,\n  onEditBookmark,\n}: PageGroupProps) {\n  return (\n    <div className=\"mb-4\">\n      <h3 className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2 px-3\">\n        Page {pageNumber}\n      </h3>\n      <div className=\"space-y-1\">\n        {bookmarks.map((bookmark) => (\n          <BookmarkItem\n            key={bookmark.id}\n            bookmark={bookmark}\n            isSelected={bookmark.pageNumber === currentPage}\n            onClick={() => onBookmarkClick(bookmark)}\n            onDelete={() => onDeleteBookmark(bookmark.id)}\n            onEdit={() => onEditBookmark(bookmark)}\n          />\n        ))}\n      </div>\n    </div>\n  );\n});\n\ninterface EditModalProps {\n  bookmark: Bookmark;\n  onSave: (updates: { label?: string; userNote?: string }) => void;\n  onClose: () => void;\n}\n\nconst EditModal = memo(function EditModal({ bookmark, onSave, onClose }: EditModalProps) {\n  const [label, setLabel] = useState(bookmark.label || '');\n  const [userNote, setUserNote] = useState(bookmark.userNote || '');\n\n  const handleSave = useCallback(() => {\n    onSave({ label: label || undefined, userNote: userNote || undefined });\n  }, [label, userNote, onSave]);\n\n  return (\n    <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\n      <div className=\"bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md mx-4 p-4\">\n        <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white mb-4\">\n          Edit Bookmark\n        </h3>\n\n        <div className=\"space-y-4\">\n          <div>\n            <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n              Label\n            </label>\n            <input\n              type=\"text\"\n              value={label}\n              onChange={(e) => setLabel(e.target.value)}\n              placeholder={`Page ${bookmark.pageNumber}`}\n              className={cn(\n                'w-full px-3 py-2 rounded-md',\n                'border border-gray-300 dark:border-gray-600',\n                'bg-white dark:bg-gray-700',\n                'text-gray-900 dark:text-white',\n                'focus:outline-none focus:ring-2 focus:ring-blue-500'\n              )}\n            />\n          </div>\n\n          <div>\n            <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n              Note\n            </label>\n            <textarea\n              value={userNote}\n              onChange={(e) => setUserNote(e.target.value)}\n              placeholder=\"Add a note...\"\n              rows={3}\n              className={cn(\n                'w-full px-3 py-2 rounded-md',\n                'border border-gray-300 dark:border-gray-600',\n                'bg-white dark:bg-gray-700',\n                'text-gray-900 dark:text-white',\n                'focus:outline-none focus:ring-2 focus:ring-blue-500',\n                'resize-none'\n              )}\n            />\n          </div>\n        </div>\n\n        <div className=\"flex justify-end gap-2 mt-6\">\n          <button\n            onClick={onClose}\n            className={cn(\n              'px-4 py-2 rounded-md text-sm font-medium',\n              'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300',\n              'hover:bg-gray-200 dark:hover:bg-gray-600',\n              'focus:outline-none focus:ring-2 focus:ring-gray-500'\n            )}\n          >\n            Cancel\n          </button>\n          <button\n            onClick={handleSave}\n            className={cn(\n              'px-4 py-2 rounded-md text-sm font-medium',\n              'bg-blue-500 text-white',\n              'hover:bg-blue-600',\n              'focus:outline-none focus:ring-2 focus:ring-blue-500'\n            )}\n          >\n            Save\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n});\n\nexport const BookmarksPanel = memo(function BookmarksPanel({\n  className,\n  onBookmarkClick,\n}: BookmarksPanelProps) {\n  const bookmarks = useStudentStore((s) => s.bookmarks);\n  const removeBookmark = useStudentStore((s) => s.removeBookmark);\n  const updateBookmark = useStudentStore((s) => s.updateBookmark);\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const goToPage = useViewerStore((s) => s.goToPage);\n\n  const [editingBookmark, setEditingBookmark] = useState<Bookmark | null>(null);\n\n  // Group bookmarks by page\n  const groupedBookmarks = useMemo(() => {\n    const groups = new Map<number, Bookmark[]>();\n\n    // Sort bookmarks by page number, then by timestamp\n    const sorted = [...bookmarks].sort((a, b) => {\n      if (a.pageNumber !== b.pageNumber) return a.pageNumber - b.pageNumber;\n      return a.timestamp.getTime() - b.timestamp.getTime();\n    });\n\n    sorted.forEach((bookmark) => {\n      const page = bookmark.pageNumber;\n      if (!groups.has(page)) {\n        groups.set(page, []);\n      }\n      groups.get(page)!.push(bookmark);\n    });\n\n    return Array.from(groups.entries()).sort(([a], [b]) => a - b);\n  }, [bookmarks]);\n\n  const handleBookmarkClick = useCallback(\n    (bookmark: Bookmark) => {\n      goToPage(bookmark.pageNumber);\n      onBookmarkClick?.(bookmark);\n    },\n    [goToPage, onBookmarkClick]\n  );\n\n  const handleDeleteBookmark = useCallback(\n    (id: string) => {\n      removeBookmark(id);\n    },\n    [removeBookmark]\n  );\n\n  const handleEditBookmark = useCallback((bookmark: Bookmark) => {\n    setEditingBookmark(bookmark);\n  }, []);\n\n  const handleSaveEdit = useCallback(\n    (updates: { label?: string; userNote?: string }) => {\n      if (editingBookmark) {\n        updateBookmark(editingBookmark.id, updates);\n        setEditingBookmark(null);\n      }\n    },\n    [editingBookmark, updateBookmark]\n  );\n\n  return (\n    <div className={cn('flex flex-col h-full', className)}>\n      {/* Header */}\n      <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n        <h2 className=\"text-sm font-semibold text-gray-700 dark:text-gray-200\">\n          Bookmarks ({bookmarks.length})\n        </h2>\n      </div>\n\n      {/* Bookmark list */}\n      <div className=\"flex-1 overflow-y-auto p-2\">\n        {bookmarks.length === 0 ? (\n          <div className=\"flex flex-col items-center justify-center h-full text-center p-4\">\n            <svg\n              className=\"w-12 h-12 text-gray-300 dark:text-gray-600 mb-3\"\n              fill=\"none\"\n              viewBox=\"0 0 24 24\"\n              stroke=\"currentColor\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={1.5}\n                d=\"M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z\"\n              />\n            </svg>\n            <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n              No bookmarks yet\n            </p>\n            <p className=\"text-xs text-gray-400 dark:text-gray-500 mt-1\">\n              Click the bookmark button in the toolbar to save your place\n            </p>\n          </div>\n        ) : (\n          groupedBookmarks.map(([pageNumber, pageBookmarks]) => (\n            <PageGroup\n              key={pageNumber}\n              pageNumber={pageNumber}\n              bookmarks={pageBookmarks}\n              currentPage={currentPage}\n              onBookmarkClick={handleBookmarkClick}\n              onDeleteBookmark={handleDeleteBookmark}\n              onEditBookmark={handleEditBookmark}\n            />\n          ))\n        )}\n      </div>\n\n      {/* Edit modal */}\n      {editingBookmark && (\n        <EditModal\n          bookmark={editingBookmark}\n          onSave={handleSaveEdit}\n          onClose={() => setEditingBookmark(null)}\n        />\n      )}\n    </div>\n  );\n});\n\nexport default BookmarksPanel;\n","import { memo, useMemo, useCallback, useState } from 'react';\nimport { useStudentStore, useViewerStore } from '../../hooks';\nimport type { Takeaway } from '../../types/agent-context';\nimport { cn } from '../../utils';\n\nexport interface TakeawaysPanelProps {\n  className?: string;\n  /** Callback when a takeaway item is clicked */\n  onTakeawayClick?: (takeaway: Takeaway) => void;\n  /** Filter by source */\n  sourceFilter?: 'all' | 'agent' | 'user';\n}\n\ninterface TakeawayItemProps {\n  takeaway: Takeaway;\n  onClick: () => void;\n  onDelete: () => void;\n}\n\nconst TakeawayItem = memo(function TakeawayItem({\n  takeaway,\n  onClick,\n  onDelete,\n}: TakeawayItemProps) {\n  const isAgent = takeaway.source === 'agent';\n\n  return (\n    <div\n      className={cn(\n        'group p-3 rounded-lg cursor-pointer',\n        'border border-transparent',\n        'hover:bg-gray-50 dark:hover:bg-gray-700/50'\n      )}\n      onClick={onClick}\n    >\n      <div className=\"flex items-start gap-3\">\n        {/* Source icon */}\n        <div\n          className={cn(\n            'mt-0.5 flex-shrink-0 w-5 h-5 rounded-full flex items-center justify-center',\n            isAgent ? 'bg-blue-100 dark:bg-blue-900/50' : 'bg-green-100 dark:bg-green-900/50'\n          )}\n        >\n          {isAgent ? (\n            <svg className=\"w-3 h-3 text-blue-600 dark:text-blue-400\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n              <path d=\"M12 2a2 2 0 012 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 017 7h1a1 1 0 011 1v3a1 1 0 01-1 1h-1v1a2 2 0 01-2 2H5a2 2 0 01-2-2v-1H2a1 1 0 01-1-1v-3a1 1 0 011-1h1a7 7 0 017-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 012-2z\" />\n            </svg>\n          ) : (\n            <svg className=\"w-3 h-3 text-green-600 dark:text-green-400\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n              <path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" />\n            </svg>\n          )}\n        </div>\n\n        <div className=\"flex-1 min-w-0\">\n          {/* Summary text */}\n          <p className=\"text-sm text-gray-700 dark:text-gray-200\">\n            {takeaway.summary}\n          </p>\n\n          {/* Metadata */}\n          <div className=\"mt-1 flex items-center gap-2 text-xs text-gray-400 dark:text-gray-500\">\n            <span>Page {takeaway.pageNumber}</span>\n            <span>&middot;</span>\n            <span>{isAgent ? 'AI Summary' : 'Your Note'}</span>\n          </div>\n        </div>\n\n        {/* Delete button (only for user takeaways) */}\n        {!isAgent && (\n          <button\n            onClick={(e) => {\n              e.stopPropagation();\n              onDelete();\n            }}\n            className={cn(\n              'p-1 rounded opacity-0 group-hover:opacity-100',\n              'text-gray-400 hover:text-red-500',\n              'hover:bg-red-50 dark:hover:bg-red-900/20',\n              'transition-opacity duration-150',\n              'focus:outline-none focus:opacity-100'\n            )}\n            title=\"Delete takeaway\"\n            aria-label=\"Delete takeaway\"\n          >\n            <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={2}\n                d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n              />\n            </svg>\n          </button>\n        )}\n      </div>\n    </div>\n  );\n});\n\ninterface PageGroupProps {\n  pageNumber: number;\n  takeaways: Takeaway[];\n  onTakeawayClick: (takeaway: Takeaway) => void;\n  onDeleteTakeaway: (id: string) => void;\n}\n\nconst PageGroup = memo(function PageGroup({\n  pageNumber,\n  takeaways,\n  onTakeawayClick,\n  onDeleteTakeaway,\n}: PageGroupProps) {\n  return (\n    <div className=\"mb-4\">\n      <h3 className=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2 px-3\">\n        Page {pageNumber}\n      </h3>\n      <div className=\"space-y-1\">\n        {takeaways.map((takeaway) => (\n          <TakeawayItem\n            key={takeaway.id}\n            takeaway={takeaway}\n            onClick={() => onTakeawayClick(takeaway)}\n            onDelete={() => onDeleteTakeaway(takeaway.id)}\n          />\n        ))}\n      </div>\n    </div>\n  );\n});\n\nexport const TakeawaysPanel = memo(function TakeawaysPanel({\n  className,\n  onTakeawayClick,\n  sourceFilter = 'all',\n}: TakeawaysPanelProps) {\n  const takeaways = useStudentStore((s) => s.takeaways);\n  const removeTakeaway = useStudentStore((s) => s.removeTakeaway);\n  const goToPage = useViewerStore((s) => s.goToPage);\n  const [activeFilter, setActiveFilter] = useState<'all' | 'agent' | 'user'>(sourceFilter);\n\n  // Filter takeaways by source\n  const filteredTakeaways = useMemo(() => {\n    if (activeFilter === 'all') return takeaways;\n    return takeaways.filter((t) => t.source === activeFilter);\n  }, [takeaways, activeFilter]);\n\n  // Group takeaways by page\n  const groupedTakeaways = useMemo(() => {\n    const groups = new Map<number, Takeaway[]>();\n\n    const sorted = [...filteredTakeaways].sort((a, b) => {\n      if (a.pageNumber !== b.pageNumber) return a.pageNumber - b.pageNumber;\n      return a.timestamp.getTime() - b.timestamp.getTime();\n    });\n\n    sorted.forEach((takeaway) => {\n      const page = takeaway.pageNumber;\n      if (!groups.has(page)) {\n        groups.set(page, []);\n      }\n      groups.get(page)!.push(takeaway);\n    });\n\n    return Array.from(groups.entries()).sort(([a], [b]) => a - b);\n  }, [filteredTakeaways]);\n\n  const handleTakeawayClick = useCallback(\n    (takeaway: Takeaway) => {\n      goToPage(takeaway.pageNumber);\n      onTakeawayClick?.(takeaway);\n    },\n    [goToPage, onTakeawayClick]\n  );\n\n  const handleDeleteTakeaway = useCallback(\n    (id: string) => {\n      removeTakeaway(id);\n    },\n    [removeTakeaway]\n  );\n\n  const agentCount = takeaways.filter((t) => t.source === 'agent').length;\n  const userCount = takeaways.filter((t) => t.source === 'user').length;\n\n  return (\n    <div className={cn('flex flex-col h-full', className)}>\n      {/* Header */}\n      <div className=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n        <h2 className=\"text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2\">\n          Key Takeaways ({filteredTakeaways.length})\n        </h2>\n\n        {/* Filter tabs */}\n        <div className=\"flex gap-1\">\n          <button\n            onClick={() => setActiveFilter('all')}\n            className={cn(\n              'px-2 py-1 text-xs rounded-md transition-colors',\n              activeFilter === 'all'\n                ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white'\n                : 'text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800'\n            )}\n          >\n            All ({takeaways.length})\n          </button>\n          <button\n            onClick={() => setActiveFilter('agent')}\n            className={cn(\n              'px-2 py-1 text-xs rounded-md transition-colors',\n              activeFilter === 'agent'\n                ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300'\n                : 'text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800'\n            )}\n          >\n            AI ({agentCount})\n          </button>\n          <button\n            onClick={() => setActiveFilter('user')}\n            className={cn(\n              'px-2 py-1 text-xs rounded-md transition-colors',\n              activeFilter === 'user'\n                ? 'bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300'\n                : 'text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800'\n            )}\n          >\n            Mine ({userCount})\n          </button>\n        </div>\n      </div>\n\n      {/* Takeaway list */}\n      <div className=\"flex-1 overflow-y-auto p-2\">\n        {filteredTakeaways.length === 0 ? (\n          <div className=\"flex flex-col items-center justify-center h-full text-center p-4\">\n            <svg\n              className=\"w-12 h-12 text-gray-300 dark:text-gray-600 mb-3\"\n              fill=\"none\"\n              viewBox=\"0 0 24 24\"\n              stroke=\"currentColor\"\n            >\n              <path\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n                strokeWidth={1.5}\n                d=\"M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z\"\n              />\n            </svg>\n            <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n              No takeaways yet\n            </p>\n            <p className=\"text-xs text-gray-400 dark:text-gray-500 mt-1\">\n              {activeFilter === 'agent'\n                ? 'AI summaries will appear here as you read'\n                : activeFilter === 'user'\n                  ? 'Add your own key points while studying'\n                  : 'Key points and summaries will appear here'}\n            </p>\n          </div>\n        ) : (\n          groupedTakeaways.map(([pageNumber, pageTakeaways]) => (\n            <PageGroup\n              key={pageNumber}\n              pageNumber={pageNumber}\n              takeaways={pageTakeaways}\n              onTakeawayClick={handleTakeawayClick}\n              onDeleteTakeaway={handleDeleteTakeaway}\n            />\n          ))\n        )}\n      </div>\n    </div>\n  );\n});\n\nexport default TakeawaysPanel;\n","export { Sidebar, type SidebarProps } from './Sidebar';\nexport { MobileSidebar, type MobileSidebarProps } from './MobileSidebar';\nexport { ThumbnailPanel, type ThumbnailPanelProps } from './ThumbnailPanel';\nexport { SearchPanel, type SearchPanelProps } from './SearchPanel';\nexport { OutlinePanel, type OutlinePanelProps } from './OutlinePanel';\nexport { HighlightsPanel, type HighlightsPanelProps } from './HighlightsPanel';\nexport { BookmarksPanel, type BookmarksPanelProps } from './BookmarksPanel';\nexport { TakeawaysPanel, type TakeawaysPanelProps } from './TakeawaysPanel';\n","import { memo, useCallback, useState, useRef, useEffect } from 'react';\nimport { cn } from '../../utils';\nimport { useAnnotationStore } from '../../hooks';\nimport type { AnnotationTool, ShapeType } from '../../store/annotation-store';\n\nexport interface AnnotationToolbarProps {\n  /** Override the active tool from store */\n  activeTool?: AnnotationTool;\n  /** Override the active shape type from store */\n  activeShapeType?: ShapeType;\n  /** Override the drawing color from store */\n  drawingColor?: string;\n  /** Override the stroke width from store */\n  strokeWidth?: number;\n  /** Custom tool change handler */\n  onToolChange?: (tool: AnnotationTool) => void;\n  /** Custom shape type change handler */\n  onShapeTypeChange?: (shapeType: ShapeType) => void;\n  /** Custom color change handler */\n  onColorChange?: (color: string) => void;\n  /** Custom stroke width change handler */\n  onStrokeWidthChange?: (width: number) => void;\n  /** Position of the toolbar */\n  position?: 'top' | 'bottom' | 'floating';\n  /** Additional class name */\n  className?: string;\n}\n\nconst COLORS = [\n  '#ef4444', // red\n  '#f97316', // orange\n  '#eab308', // yellow\n  '#22c55e', // green\n  '#3b82f6', // blue\n  '#8b5cf6', // purple\n  '#ec4899', // pink\n  '#000000', // black\n];\n\nconst STROKE_WIDTHS = [1, 2, 3, 5, 8];\n\nconst SHAPE_TYPES: { type: ShapeType; icon: React.ReactNode; label: string }[] = [\n  {\n    type: 'rect',\n    label: 'Rectangle',\n    icon: (\n      <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <rect x=\"4\" y=\"6\" width=\"16\" height=\"12\" strokeWidth={2} />\n      </svg>\n    ),\n  },\n  {\n    type: 'circle',\n    label: 'Circle/Ellipse',\n    icon: (\n      <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <ellipse cx=\"12\" cy=\"12\" rx=\"8\" ry=\"6\" strokeWidth={2} />\n      </svg>\n    ),\n  },\n  {\n    type: 'arrow',\n    label: 'Arrow',\n    icon: (\n      <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M14 5l7 7m0 0l-7 7m7-7H3\" />\n      </svg>\n    ),\n  },\n  {\n    type: 'line',\n    label: 'Line',\n    icon: (\n      <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 20L20 4\" />\n      </svg>\n    ),\n  },\n];\n\nexport const AnnotationToolbar = memo(function AnnotationToolbar({\n  activeTool: activeToolProp,\n  activeShapeType: activeShapeTypeProp,\n  drawingColor: drawingColorProp,\n  strokeWidth: strokeWidthProp,\n  onToolChange: onToolChangeProp,\n  onShapeTypeChange: onShapeTypeChangeProp,\n  onColorChange: onColorChangeProp,\n  onStrokeWidthChange: onStrokeWidthChangeProp,\n  position = 'top',\n  className,\n}: AnnotationToolbarProps) {\n  // Get state from store\n  const storeActiveTool = useAnnotationStore((s) => s.activeAnnotationTool);\n  const storeActiveShapeType = useAnnotationStore((s) => s.activeShapeType);\n  const storeDrawingColor = useAnnotationStore((s) => s.drawingColor);\n  const storeStrokeWidth = useAnnotationStore((s) => s.drawingStrokeWidth);\n  const setActiveAnnotationTool = useAnnotationStore((s) => s.setActiveAnnotationTool);\n  const setActiveShapeType = useAnnotationStore((s) => s.setActiveShapeType);\n  const setDrawingColor = useAnnotationStore((s) => s.setDrawingColor);\n  const setDrawingStrokeWidth = useAnnotationStore((s) => s.setDrawingStrokeWidth);\n\n  // Use props if provided, otherwise use store values\n  const activeTool = activeToolProp !== undefined ? activeToolProp : storeActiveTool;\n  const activeShapeType = activeShapeTypeProp !== undefined ? activeShapeTypeProp : storeActiveShapeType;\n  const drawingColor = drawingColorProp !== undefined ? drawingColorProp : storeDrawingColor;\n  const strokeWidth = strokeWidthProp !== undefined ? strokeWidthProp : storeStrokeWidth;\n\n  // Use custom handlers if provided, otherwise use store actions\n  const onToolChange = onToolChangeProp || setActiveAnnotationTool;\n  const onShapeTypeChange = onShapeTypeChangeProp || setActiveShapeType;\n  const onColorChange = onColorChangeProp || setDrawingColor;\n  const onStrokeWidthChange = onStrokeWidthChangeProp || setDrawingStrokeWidth;\n\n  const [showColorPicker, setShowColorPicker] = useState(false);\n  const [showShapePicker, setShowShapePicker] = useState(false);\n  const [showStrokeWidth, setShowStrokeWidth] = useState(false);\n  const colorPickerRef = useRef<HTMLDivElement>(null);\n  const shapePickerRef = useRef<HTMLDivElement>(null);\n  const strokePickerRef = useRef<HTMLDivElement>(null);\n\n  // Close dropdowns when clicking outside\n  useEffect(() => {\n    const handleClickOutside = (e: MouseEvent) => {\n      const target = e.target as Node;\n      if (colorPickerRef.current && !colorPickerRef.current.contains(target)) {\n        setShowColorPicker(false);\n      }\n      if (shapePickerRef.current && !shapePickerRef.current.contains(target)) {\n        setShowShapePicker(false);\n      }\n      if (strokePickerRef.current && !strokePickerRef.current.contains(target)) {\n        setShowStrokeWidth(false);\n      }\n    };\n\n    document.addEventListener('mousedown', handleClickOutside);\n    return () => document.removeEventListener('mousedown', handleClickOutside);\n  }, []);\n\n  const handleToolClick = useCallback((tool: AnnotationTool) => {\n    onToolChange(activeTool === tool ? null : tool);\n  }, [activeTool, onToolChange]);\n\n  const isActive = activeTool !== null;\n\n  return (\n    <div\n      className={cn(\n        'annotation-toolbar flex items-center gap-1 p-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700',\n        position === 'floating' && 'fixed bottom-20 left-1/2 -translate-x-1/2 z-50',\n        position === 'top' && 'sticky top-0 z-40',\n        position === 'bottom' && 'sticky bottom-0 z-40',\n        !isActive && 'opacity-90',\n        className\n      )}\n    >\n      {/* Note tool */}\n      <button\n        className={cn(\n          'p-2 rounded transition-colors',\n          activeTool === 'note'\n            ? 'bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400'\n            : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300'\n        )}\n        onClick={() => handleToolClick('note')}\n        title=\"Sticky Note\"\n      >\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z\" />\n        </svg>\n      </button>\n\n      {/* Draw tool */}\n      <button\n        className={cn(\n          'p-2 rounded transition-colors',\n          activeTool === 'draw'\n            ? 'bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400'\n            : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300'\n        )}\n        onClick={() => handleToolClick('draw')}\n        title=\"Freehand Draw\"\n      >\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\" />\n        </svg>\n      </button>\n\n      {/* Shape tool with dropdown */}\n      <div className=\"relative\" ref={shapePickerRef}>\n        <button\n          className={cn(\n            'p-2 rounded transition-colors flex items-center gap-1',\n            activeTool === 'shape'\n              ? 'bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400'\n              : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300'\n          )}\n          onClick={() => {\n            if (activeTool !== 'shape') {\n              handleToolClick('shape');\n            }\n            setShowShapePicker(!showShapePicker);\n          }}\n          title=\"Shapes\"\n        >\n          {SHAPE_TYPES.find(s => s.type === activeShapeType)?.icon || SHAPE_TYPES[0].icon}\n          <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n            <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n          </svg>\n        </button>\n\n        {showShapePicker && (\n          <div className=\"absolute bottom-full left-0 mb-2 p-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700\">\n            <div className=\"flex gap-1\">\n              {SHAPE_TYPES.map((shape) => (\n                <button\n                  key={shape.type}\n                  className={cn(\n                    'p-2 rounded transition-colors',\n                    activeShapeType === shape.type\n                      ? 'bg-blue-100 dark:bg-blue-900 text-blue-600 dark:text-blue-400'\n                      : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300'\n                  )}\n                  onClick={() => {\n                    onShapeTypeChange(shape.type);\n                    onToolChange('shape');\n                    setShowShapePicker(false);\n                  }}\n                  title={shape.label}\n                >\n                  {shape.icon}\n                </button>\n              ))}\n            </div>\n          </div>\n        )}\n      </div>\n\n      {/* Divider */}\n      <div className=\"w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1\" />\n\n      {/* Color picker */}\n      <div className=\"relative\" ref={colorPickerRef}>\n        <button\n          className={cn(\n            'p-2 rounded transition-colors hover:bg-gray-100 dark:hover:bg-gray-700',\n            showColorPicker && 'bg-gray-100 dark:bg-gray-700'\n          )}\n          onClick={() => setShowColorPicker(!showColorPicker)}\n          title=\"Color\"\n        >\n          <div\n            className=\"w-5 h-5 rounded border-2 border-gray-300 dark:border-gray-500\"\n            style={{ backgroundColor: drawingColor }}\n          />\n        </button>\n\n        {showColorPicker && (\n          <div className=\"absolute bottom-full left-0 mb-2 p-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700\">\n            <div className=\"grid grid-cols-4 gap-1\">\n              {COLORS.map((color) => (\n                <button\n                  key={color}\n                  className={cn(\n                    'w-6 h-6 rounded border-2 transition-transform hover:scale-110',\n                    drawingColor === color\n                      ? 'border-blue-500 ring-2 ring-blue-200'\n                      : 'border-gray-300 dark:border-gray-500'\n                  )}\n                  style={{ backgroundColor: color }}\n                  onClick={() => {\n                    onColorChange(color);\n                    setShowColorPicker(false);\n                  }}\n                  title={color}\n                />\n              ))}\n            </div>\n          </div>\n        )}\n      </div>\n\n      {/* Stroke width */}\n      <div className=\"relative\" ref={strokePickerRef}>\n        <button\n          className={cn(\n            'p-2 rounded transition-colors hover:bg-gray-100 dark:hover:bg-gray-700',\n            showStrokeWidth && 'bg-gray-100 dark:bg-gray-700'\n          )}\n          onClick={() => setShowStrokeWidth(!showStrokeWidth)}\n          title=\"Stroke Width\"\n        >\n          <div className=\"w-5 h-5 flex items-center justify-center\">\n            <div\n              className=\"rounded-full bg-gray-700 dark:bg-gray-300\"\n              style={{ width: Math.min(strokeWidth * 2, 16), height: Math.min(strokeWidth * 2, 16) }}\n            />\n          </div>\n        </button>\n\n        {showStrokeWidth && (\n          <div className=\"absolute bottom-full left-0 mb-2 p-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700\">\n            <div className=\"flex flex-col gap-1\">\n              {STROKE_WIDTHS.map((width) => (\n                <button\n                  key={width}\n                  className={cn(\n                    'flex items-center gap-2 px-3 py-1 rounded transition-colors',\n                    strokeWidth === width\n                      ? 'bg-blue-100 dark:bg-blue-900'\n                      : 'hover:bg-gray-100 dark:hover:bg-gray-700'\n                  )}\n                  onClick={() => {\n                    onStrokeWidthChange(width);\n                    setShowStrokeWidth(false);\n                  }}\n                >\n                  <div\n                    className=\"rounded-full bg-gray-700 dark:bg-gray-300\"\n                    style={{ width: width * 2, height: width * 2 }}\n                  />\n                  <span className=\"text-sm text-gray-700 dark:text-gray-300\">{width}px</span>\n                </button>\n              ))}\n            </div>\n          </div>\n        )}\n      </div>\n\n      {/* Divider */}\n      <div className=\"w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1\" />\n\n      {/* Clear/Cancel button */}\n      {activeTool && (\n        <button\n          className=\"p-2 rounded transition-colors hover:bg-red-100 dark:hover:bg-red-900/30 text-red-600 dark:text-red-400\"\n          onClick={() => onToolChange(null)}\n          title=\"Exit annotation mode\"\n        >\n          <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n            <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n          </svg>\n        </button>\n      )}\n    </div>\n  );\n});\n","export { AnnotationToolbar, type AnnotationToolbarProps } from './AnnotationToolbar';\n","import { useEffect, useRef, useCallback, useState, memo } from 'react';\nimport type { PDFPageProxy, RenderTask } from 'pdfjs-dist';\nimport {\n  calculateOptimalCanvasDimensions,\n  cn,\n  getDeviceCapabilities,\n  getRenderConfig,\n} from '../../utils';\n\nexport interface CanvasLayerProps {\n  page: PDFPageProxy;\n  scale: number;\n  rotation: number;\n  className?: string;\n  onRenderStart?: () => void;\n  onRenderComplete?: () => void;\n  onRenderError?: (error: Error) => void;\n  /** Priority for rendering (lower = higher priority) - used for render ordering */\n  priority?: number;\n}\n\n/**\n * CanvasLayer renders a PDF page at full quality.\n *\n * Optimizations for mobile:\n * - Uses requestAnimationFrame for render timing\n * - Cancels pending renders on unmount/update\n * - Uses 'display' intent for faster rendering\n * - Disables alpha channel for better performance\n */\nexport const CanvasLayer = memo(function CanvasLayer({\n  page,\n  scale,\n  rotation,\n  className,\n  onRenderStart,\n  onRenderComplete,\n  onRenderError,\n  priority: _priority,\n}: CanvasLayerProps) {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const renderTaskRef = useRef<RenderTask | null>(null);\n  const [isRendering, setIsRendering] = useState(false);\n  const mountedRef = useRef(true);\n  const rafIdRef = useRef<number | null>(null);\n\n  const cancelRender = useCallback(() => {\n    // Cancel any pending animation frame\n    if (rafIdRef.current !== null) {\n      cancelAnimationFrame(rafIdRef.current);\n      rafIdRef.current = null;\n    }\n    // Cancel any ongoing render task\n    if (renderTaskRef.current) {\n      renderTaskRef.current.cancel();\n      renderTaskRef.current = null;\n    }\n  }, []);\n\n  const render = useCallback(async () => {\n    const canvas = canvasRef.current;\n    if (!canvas || !page) return;\n\n    // Cancel any ongoing render\n    cancelRender();\n\n    const viewport = page.getViewport({ scale, rotation });\n\n    // Use 2d context without alpha for better performance\n    const context = canvas.getContext('2d', {\n      alpha: false,\n      // Hint for better performance on mobile\n      desynchronized: true,\n    });\n\n    if (!context) {\n      onRenderError?.(new Error('Failed to get canvas context'));\n      return;\n    }\n\n    // Render at full devicePixelRatio so canvas backing pixels match physical\n    // pixels — anything less makes Safari upscale and look blurry. Memory\n    // safety is enforced by `maxCanvasDimension` inside\n    // `calculateOptimalCanvasDimensions`, which only forces a downscale when\n    // the resulting backing store would exceed the per-canvas pixel budget\n    // (e.g. deep zoom on iOS Safari).\n    const capabilities = getDeviceCapabilities();\n    const renderConfig = getRenderConfig('auto', capabilities);\n    const optimal = calculateOptimalCanvasDimensions(\n      viewport.width,\n      viewport.height,\n      renderConfig.canvasScaleFactor,\n      renderConfig.maxCanvasDimension,\n    );\n    const outputScale = optimal.actualScale;\n\n    canvas.width = optimal.width;\n    canvas.height = optimal.height;\n    // CSS size stays at viewport points so overlays align; only the\n    // backing-store resolution is reduced on mobile.\n    canvas.style.width = `${Math.floor(viewport.width)}px`;\n    canvas.style.height = `${Math.floor(viewport.height)}px`;\n\n    // Scale the drawing context so pdf.js rasterizes into the\n    // (possibly-reduced) backing store at the right density.\n    context.scale(outputScale, outputScale);\n\n    if (mountedRef.current) {\n      setIsRendering(true);\n    }\n    onRenderStart?.();\n\n    try {\n      renderTaskRef.current = page.render({\n        canvasContext: context,\n        viewport,\n        // 'display' intent is faster than 'print' and sufficient for screen viewing\n        intent: 'display',\n      });\n\n      await renderTaskRef.current.promise;\n\n      if (mountedRef.current) {\n        setIsRendering(false);\n      }\n      onRenderComplete?.();\n    } catch (error) {\n      if ((error as Error).name !== 'RenderingCancelledException') {\n        if (mountedRef.current) {\n          setIsRendering(false);\n        }\n        onRenderError?.(error as Error);\n      }\n    }\n  }, [page, scale, rotation, cancelRender, onRenderStart, onRenderComplete, onRenderError]);\n\n  // Render when page, scale, or rotation changes\n  // Use requestAnimationFrame to avoid blocking the main thread\n  useEffect(() => {\n    rafIdRef.current = requestAnimationFrame(() => {\n      render();\n    });\n\n    return () => {\n      cancelRender();\n    };\n  }, [render, cancelRender]);\n\n  // Cleanup on unmount\n  useEffect(() => {\n    mountedRef.current = true;\n    return () => {\n      mountedRef.current = false;\n      cancelRender();\n    };\n  }, [cancelRender]);\n\n  return (\n    <canvas\n      ref={canvasRef}\n      className={cn(\n        'pdf-canvas-layer',\n        'absolute inset-0',\n        isRendering && 'opacity-50',\n        className\n      )}\n      style={{ zIndex: 10 }}\n    />\n  );\n});\n","import { useEffect, useRef, memo } from 'react';\nimport type { PDFPageProxy } from 'pdfjs-dist';\nimport { cn } from '../../utils';\n\nexport interface TextLayerProps {\n  page: PDFPageProxy;\n  scale: number;\n  rotation: number;\n  className?: string;\n}\n\n// Local type for text content to avoid pdfjs-dist version issues\ninterface TextContentItem {\n  str?: string;\n  dir?: string;\n  transform?: number[];\n  width?: number;\n  height?: number;\n  fontName?: string;\n}\n\ninterface LocalTextContent {\n  items: TextContentItem[];\n}\n\nfunction isTextItem(item: TextContentItem): item is Required<TextContentItem> {\n  return typeof item.str === 'string' && Array.isArray(item.transform);\n}\n\nexport const TextLayer = memo(function TextLayer({\n  page,\n  scale,\n  rotation,\n  className,\n}: TextLayerProps) {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const pageNumberRef = useRef<number | null>(null);\n\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container || !page) return;\n\n    let cancelled = false;\n\n    const renderTextLayer = async () => {\n      // Clear existing text\n      container.innerHTML = '';\n\n      // Check if page number changed - if so, we need fresh text content\n      const currentPageNumber = page.pageNumber;\n\n      try {\n        // Get text content - don't cache as the page object may change\n        const textContent = (await page.getTextContent()) as unknown as LocalTextContent;\n\n        // Check if cancelled or page changed during async operation\n        if (cancelled || pageNumberRef.current !== currentPageNumber) {\n          return;\n        }\n\n        const viewport = page.getViewport({ scale, rotation });\n\n        // Set container dimensions\n        container.style.width = `${viewport.width}px`;\n        container.style.height = `${viewport.height}px`;\n\n        // Render each text item\n        for (const item of textContent.items) {\n          if (cancelled) return;\n          if (!isTextItem(item) || !item.str.trim()) continue;\n\n          const [scaleX, rotY, rotX, scaleY, tx, ty] = item.transform;\n\n          // Calculate position and font size\n          const fontSize = Math.sqrt(rotX * rotX + scaleY * scaleY) * scale;\n          const angle = Math.atan2(rotY, scaleX) * (180 / Math.PI) + rotation;\n\n          // Create text span\n          const span = document.createElement('span');\n          span.textContent = item.str;\n          span.style.cssText = `\n            position: absolute;\n            left: ${tx * scale}px;\n            top: ${viewport.height - ty * scale - fontSize}px;\n            font-size: ${fontSize}px;\n            font-family: sans-serif;\n            transform-origin: 0 0;\n            transform: rotate(${angle}deg) scaleX(${(item.width * scale) / (fontSize * item.str.length) || 1});\n            white-space: pre;\n            color: transparent;\n            pointer-events: all;\n            user-select: text;\n          `;\n\n          container.appendChild(span);\n        }\n      } catch (error) {\n        // Silently ignore errors from destroyed pages\n        if (!cancelled) {\n          // Only log if not a page destruction error\n          const errorMessage = error instanceof Error ? error.message : String(error);\n          if (!errorMessage.includes('sendWithStream') && !errorMessage.includes('destroyed')) {\n            console.error('Error rendering text layer:', error);\n          }\n        }\n      }\n    };\n\n    pageNumberRef.current = page.pageNumber;\n    renderTextLayer();\n\n    return () => {\n      cancelled = true;\n      if (container) {\n        container.innerHTML = '';\n      }\n    };\n  }, [page, scale, rotation]);\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        'pdf-text-layer',\n        'absolute inset-0 overflow-hidden',\n        'select-text',\n        className\n      )}\n      style={{ zIndex: 20 }}\n    />\n  );\n});\n","import { memo, useMemo } from 'react';\nimport type { Highlight, HighlightColor } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface HighlightLayerProps {\n  highlights: Highlight[];\n  scale: number;\n  selectedId?: string | null;\n  onHighlightClick?: (highlight: Highlight) => void;\n  className?: string;\n  /** Filter by source type */\n  sourceFilter?: 'all' | 'user' | 'agent';\n}\n\n// User highlight colors (warmer tones)\nconst HIGHLIGHT_COLORS: Record<HighlightColor, string> = {\n  yellow: 'rgba(254, 240, 138, 0.5)',\n  green: 'rgba(134, 239, 172, 0.5)',\n  blue: 'rgba(147, 197, 253, 0.5)',\n  pink: 'rgba(249, 168, 212, 0.5)',\n  orange: 'rgba(253, 186, 116, 0.5)',\n};\n\nconst HIGHLIGHT_COLORS_SELECTED: Record<HighlightColor, string> = {\n  yellow: 'rgba(254, 240, 138, 0.8)',\n  green: 'rgba(134, 239, 172, 0.8)',\n  blue: 'rgba(147, 197, 253, 0.8)',\n  pink: 'rgba(249, 168, 212, 0.8)',\n  orange: 'rgba(253, 186, 116, 0.8)',\n};\n\n// Agent highlight colors (cooler tones with slight transparency difference)\nconst AGENT_HIGHLIGHT_COLORS: Record<HighlightColor, string> = {\n  yellow: 'rgba(250, 204, 21, 0.4)', // amber-400\n  green: 'rgba(74, 222, 128, 0.4)', // green-400\n  blue: 'rgba(96, 165, 250, 0.45)', // blue-400\n  pink: 'rgba(244, 114, 182, 0.4)', // pink-400\n  orange: 'rgba(251, 146, 60, 0.4)', // orange-400\n};\n\nconst AGENT_HIGHLIGHT_COLORS_SELECTED: Record<HighlightColor, string> = {\n  yellow: 'rgba(250, 204, 21, 0.7)',\n  green: 'rgba(74, 222, 128, 0.7)',\n  blue: 'rgba(96, 165, 250, 0.75)',\n  pink: 'rgba(244, 114, 182, 0.7)',\n  orange: 'rgba(251, 146, 60, 0.7)',\n};\n\nexport const HighlightLayer = memo(function HighlightLayer({\n  highlights,\n  scale,\n  selectedId,\n  onHighlightClick,\n  className,\n  sourceFilter = 'all',\n}: HighlightLayerProps) {\n  const filteredHighlights = useMemo(() => {\n    if (sourceFilter === 'all') return highlights;\n    return highlights.filter((h) => {\n      const source = h.source ?? 'user';\n      return source === sourceFilter;\n    });\n  }, [highlights, sourceFilter]);\n\n  const renderedHighlights = useMemo(() => {\n    return filteredHighlights.map((highlight) => {\n      const isSelected = highlight.id === selectedId;\n      const isAgentHighlight = highlight.source === 'agent';\n\n      // Choose color palette based on source\n      const colorPalette = isAgentHighlight\n        ? (isSelected ? AGENT_HIGHLIGHT_COLORS_SELECTED : AGENT_HIGHLIGHT_COLORS)\n        : (isSelected ? HIGHLIGHT_COLORS_SELECTED : HIGHLIGHT_COLORS);\n\n      return (\n        <div\n          key={highlight.id}\n          className={cn(\n            'highlight-group',\n            'cursor-pointer',\n            isSelected && 'ring-2 ring-blue-500',\n            isAgentHighlight && 'highlight-agent'\n          )}\n          onClick={() => onHighlightClick?.(highlight)}\n          data-source={highlight.source ?? 'user'}\n        >\n          {highlight.rects.map((rect, index) => (\n            <div\n              key={`${highlight.id}-${index}`}\n              className={cn(\n                'absolute transition-colors duration-150',\n                isAgentHighlight && 'border-b-2 border-dashed border-blue-400/50'\n              )}\n              style={{\n                left: rect.x * scale,\n                top: rect.y * scale,\n                width: rect.width * scale,\n                height: rect.height * scale,\n                backgroundColor: colorPalette[highlight.color],\n                mixBlendMode: 'multiply',\n              }}\n            />\n          ))}\n          {/* Agent highlight indicator */}\n          {isAgentHighlight && highlight.rects[0] && (\n            <div\n              className=\"absolute -left-1 flex items-center justify-center w-3 h-3 bg-blue-500 rounded-full text-white\"\n              style={{\n                top: highlight.rects[0].y * scale,\n              }}\n              title=\"AI highlighted\"\n            >\n              <svg className=\"w-2 h-2\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n                <path d=\"M12 2a2 2 0 012 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 017 7h1a1 1 0 011 1v3a1 1 0 01-1 1h-1v1a2 2 0 01-2 2H5a2 2 0 01-2-2v-1H2a1 1 0 01-1-1v-3a1 1 0 011-1h1a7 7 0 017-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 012-2z\" />\n              </svg>\n            </div>\n          )}\n        </div>\n      );\n    });\n  }, [filteredHighlights, scale, selectedId, onHighlightClick]);\n\n  return (\n    <div\n      className={cn(\n        'pdf-highlight-layer',\n        'absolute inset-0 pointer-events-none',\n        className\n      )}\n      style={{ zIndex: 40 }}\n    >\n      <div className=\"pointer-events-auto\">{renderedHighlights}</div>\n    </div>\n  );\n});\n","import { memo, useCallback, useRef, MouseEvent, TouchEvent } from 'react';\nimport type { Annotation, DrawingPath } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface AnnotationLayerProps {\n  pageNumber: number;\n  annotations: Annotation[];\n  scale: number;\n  selectedId?: string | null;\n  isDrawing?: boolean;\n  currentDrawingPath?: DrawingPath | null;\n  drawingColor?: string;\n  drawingStrokeWidth?: number;\n  activeAnnotationTool?: 'note' | 'draw' | 'shape' | null;\n  onAnnotationClick?: (annotation: Annotation) => void;\n  onNoteClick?: (annotation: Annotation, event: { x: number; y: number }) => void;\n  onDrawStart?: (point: { x: number; y: number }) => void;\n  onDrawMove?: (point: { x: number; y: number }) => void;\n  onDrawEnd?: () => void;\n  onPageClick?: (point: { x: number; y: number }) => void;\n  className?: string;\n}\n\n// Convert points to SVG path data\nfunction pointsToPath(points: { x: number; y: number }[], scale: number): string {\n  if (points.length === 0) return '';\n  if (points.length === 1) {\n    const p = points[0];\n    return `M ${p.x * scale} ${p.y * scale} L ${p.x * scale} ${p.y * scale}`;\n  }\n\n  const path = points.reduce((acc, point, index) => {\n    const scaledX = point.x * scale;\n    const scaledY = point.y * scale;\n    if (index === 0) {\n      return `M ${scaledX} ${scaledY}`;\n    }\n    return `${acc} L ${scaledX} ${scaledY}`;\n  }, '');\n\n  return path;\n}\n\n// Render a shape annotation\nfunction renderShape(\n  annotation: Annotation & { type: 'shape' },\n  scale: number,\n  isSelected: boolean\n): React.ReactNode {\n  const { shapeType, x, y, width, height, color, strokeWidth, id } = annotation;\n  const scaledX = x * scale;\n  const scaledY = y * scale;\n  const scaledWidth = width * scale;\n  const scaledHeight = height * scale;\n  const scaledStroke = strokeWidth * scale;\n\n  const commonProps = {\n    stroke: color,\n    strokeWidth: scaledStroke,\n    fill: 'none',\n    className: cn(\n      'cursor-pointer transition-opacity',\n      isSelected && 'opacity-80'\n    ),\n  };\n\n  switch (shapeType) {\n    case 'rect':\n      return (\n        <rect\n          key={id}\n          x={scaledX}\n          y={scaledY}\n          width={scaledWidth}\n          height={scaledHeight}\n          {...commonProps}\n        />\n      );\n    case 'circle':\n      return (\n        <ellipse\n          key={id}\n          cx={scaledX + scaledWidth / 2}\n          cy={scaledY + scaledHeight / 2}\n          rx={scaledWidth / 2}\n          ry={scaledHeight / 2}\n          {...commonProps}\n        />\n      );\n    case 'line':\n      return (\n        <line\n          key={id}\n          x1={scaledX}\n          y1={scaledY}\n          x2={scaledX + scaledWidth}\n          y2={scaledY + scaledHeight}\n          {...commonProps}\n        />\n      );\n    case 'arrow':\n      const endX = scaledX + scaledWidth;\n      const endY = scaledY + scaledHeight;\n      const angle = Math.atan2(scaledHeight, scaledWidth);\n      const arrowLength = 10 * scale;\n      const arrowAngle = Math.PI / 6;\n\n      const arrow1X = endX - arrowLength * Math.cos(angle - arrowAngle);\n      const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);\n      const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);\n      const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);\n\n      return (\n        <g key={id}>\n          <line\n            x1={scaledX}\n            y1={scaledY}\n            x2={endX}\n            y2={endY}\n            {...commonProps}\n          />\n          <line\n            x1={endX}\n            y1={endY}\n            x2={arrow1X}\n            y2={arrow1Y}\n            {...commonProps}\n          />\n          <line\n            x1={endX}\n            y1={endY}\n            x2={arrow2X}\n            y2={arrow2Y}\n            {...commonProps}\n          />\n        </g>\n      );\n    default:\n      return null;\n  }\n}\n\nexport const AnnotationLayer = memo(function AnnotationLayer({\n  pageNumber: _pageNumber,\n  annotations,\n  scale,\n  selectedId,\n  isDrawing,\n  currentDrawingPath,\n  drawingColor = '#ef4444',\n  drawingStrokeWidth = 2,\n  activeAnnotationTool,\n  onAnnotationClick,\n  onNoteClick,\n  onDrawStart,\n  onDrawMove,\n  onDrawEnd,\n  onPageClick,\n  className,\n}: AnnotationLayerProps) {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const isDrawingRef = useRef(false);\n\n  // Get relative coordinates from mouse/touch event\n  const getRelativePoint = useCallback((clientX: number, clientY: number): { x: number; y: number } | null => {\n    if (!containerRef.current) return null;\n    const rect = containerRef.current.getBoundingClientRect();\n    return {\n      x: (clientX - rect.left) / scale,\n      y: (clientY - rect.top) / scale,\n    };\n  }, [scale]);\n\n  const handleMouseDown = useCallback((e: MouseEvent) => {\n    if (activeAnnotationTool !== 'draw') return;\n\n    const point = getRelativePoint(e.clientX, e.clientY);\n    if (point) {\n      isDrawingRef.current = true;\n      onDrawStart?.(point);\n    }\n  }, [activeAnnotationTool, getRelativePoint, onDrawStart]);\n\n  const handleMouseMove = useCallback((e: MouseEvent) => {\n    if (!isDrawingRef.current || activeAnnotationTool !== 'draw') return;\n\n    const point = getRelativePoint(e.clientX, e.clientY);\n    if (point) {\n      onDrawMove?.(point);\n    }\n  }, [activeAnnotationTool, getRelativePoint, onDrawMove]);\n\n  const handleMouseUp = useCallback(() => {\n    if (isDrawingRef.current) {\n      isDrawingRef.current = false;\n      onDrawEnd?.();\n    }\n  }, [onDrawEnd]);\n\n  const handleTouchStart = useCallback((e: TouchEvent) => {\n    if (activeAnnotationTool !== 'draw') return;\n\n    const touch = e.touches[0];\n    if (touch) {\n      const point = getRelativePoint(touch.clientX, touch.clientY);\n      if (point) {\n        isDrawingRef.current = true;\n        onDrawStart?.(point);\n      }\n    }\n  }, [activeAnnotationTool, getRelativePoint, onDrawStart]);\n\n  const handleTouchMove = useCallback((e: TouchEvent) => {\n    if (!isDrawingRef.current || activeAnnotationTool !== 'draw') return;\n\n    const touch = e.touches[0];\n    if (touch) {\n      const point = getRelativePoint(touch.clientX, touch.clientY);\n      if (point) {\n        e.preventDefault(); // Prevent scrolling while drawing\n        onDrawMove?.(point);\n      }\n    }\n  }, [activeAnnotationTool, getRelativePoint, onDrawMove]);\n\n  const handleTouchEnd = useCallback(() => {\n    if (isDrawingRef.current) {\n      isDrawingRef.current = false;\n      onDrawEnd?.();\n    }\n  }, [onDrawEnd]);\n\n  const handleClick = useCallback((e: MouseEvent) => {\n    if (activeAnnotationTool === 'note') {\n      const point = getRelativePoint(e.clientX, e.clientY);\n      if (point) {\n        onPageClick?.(point);\n      }\n    }\n  }, [activeAnnotationTool, getRelativePoint, onPageClick]);\n\n  // Annotations are already filtered for this page by PDFPage component\n  // Separate drawings/shapes from notes\n  const drawings = annotations.filter(a => a.type === 'drawing');\n  const shapes = annotations.filter(a => a.type === 'shape');\n  const notes = annotations.filter(a => a.type === 'note');\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        'pdf-annotation-layer',\n        'absolute inset-0',\n        activeAnnotationTool && 'cursor-crosshair',\n        className\n      )}\n      style={{ zIndex: 50, pointerEvents: activeAnnotationTool ? 'auto' : 'none' }}\n      onMouseDown={handleMouseDown}\n      onMouseMove={handleMouseMove}\n      onMouseUp={handleMouseUp}\n      onMouseLeave={handleMouseUp}\n      onTouchStart={handleTouchStart}\n      onTouchMove={handleTouchMove}\n      onTouchEnd={handleTouchEnd}\n      onClick={handleClick}\n    >\n      {/* SVG layer for drawings and shapes */}\n      <svg\n        className=\"absolute inset-0 w-full h-full pointer-events-none\"\n        style={{ overflow: 'visible' }}\n      >\n        {/* Render completed drawings */}\n        {drawings.map((drawing) => {\n          if (drawing.type !== 'drawing') return null;\n          const isSelected = drawing.id === selectedId;\n\n          return drawing.paths.map((path, pathIndex) => (\n            <path\n              key={`${drawing.id}-${pathIndex}`}\n              d={pointsToPath(path.points, scale)}\n              stroke={drawing.color}\n              strokeWidth={drawing.strokeWidth * scale}\n              fill=\"none\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              className={cn(\n                'cursor-pointer pointer-events-auto',\n                isSelected && 'filter drop-shadow-md'\n              )}\n              onClick={(e) => {\n                e.stopPropagation();\n                onAnnotationClick?.(drawing);\n              }}\n            />\n          ));\n        })}\n\n        {/* Render shapes */}\n        {shapes.map((shape) => {\n          if (shape.type !== 'shape') return null;\n          const isSelected = shape.id === selectedId;\n\n          return (\n            <g\n              key={shape.id}\n              className=\"pointer-events-auto\"\n              onClick={(e) => {\n                e.stopPropagation();\n                onAnnotationClick?.(shape);\n              }}\n            >\n              {renderShape(shape, scale, isSelected)}\n            </g>\n          );\n        })}\n\n        {/* Render current drawing path (preview) */}\n        {isDrawing && currentDrawingPath && currentDrawingPath.points.length > 0 && (\n          <path\n            d={pointsToPath(currentDrawingPath.points, scale)}\n            stroke={drawingColor}\n            strokeWidth={drawingStrokeWidth * scale}\n            fill=\"none\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            opacity={0.8}\n          />\n        )}\n      </svg>\n\n      {/* Sticky notes */}\n      {notes.map((note) => {\n        if (note.type !== 'note') return null;\n        const isSelected = note.id === selectedId;\n\n        return (\n          <div\n            key={note.id}\n            className={cn(\n              'absolute pointer-events-auto cursor-pointer',\n              'w-6 h-6 flex items-center justify-center',\n              'rounded-sm shadow-md transition-transform hover:scale-110',\n              isSelected && 'ring-2 ring-blue-500'\n            )}\n            style={{\n              left: note.x * scale,\n              top: note.y * scale,\n              backgroundColor: note.color,\n            }}\n            onClick={(e) => {\n              e.stopPropagation();\n              onAnnotationClick?.(note);\n              onNoteClick?.(note, { x: e.clientX, y: e.clientY });\n            }}\n            title={note.content}\n          >\n            <svg\n              className=\"w-4 h-4 text-white\"\n              fill=\"currentColor\"\n              viewBox=\"0 0 20 20\"\n            >\n              <path\n                fillRule=\"evenodd\"\n                d=\"M18 10c0 3.866-3.582 7-8 7a8.841 8.841 0 01-4.083-.98L2 17l1.338-3.123C2.493 12.767 2 11.434 2 10c0-3.866 3.582-7 8-7s8 3.134 8 7zM7 9H5v2h2V9zm8 0h-2v2h2V9zM9 9h2v2H9V9z\"\n                clipRule=\"evenodd\"\n              />\n            </svg>\n          </div>\n        );\n      })}\n    </div>\n  );\n});\n","import { useEffect, useState, memo, useCallback, useMemo } from 'react';\nimport type { PDFPageProxy } from 'pdfjs-dist';\nimport { CanvasLayer } from './CanvasLayer';\nimport { TextLayer } from './TextLayer';\nimport { HighlightLayer } from './HighlightLayer';\nimport { AnnotationLayer } from './AnnotationLayer';\nimport { useAnnotationStore } from '../../hooks';\nimport type { Highlight, Annotation } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface PDFPageProps {\n  pageNumber: number;\n  page: PDFPageProxy | null;\n  scale: number;\n  rotation: number;\n  className?: string;\n  showTextLayer?: boolean;\n  showHighlightLayer?: boolean;\n  showAnnotationLayer?: boolean;\n  onPageLoad?: (page: PDFPageProxy) => void;\n  onRenderComplete?: () => void;\n  onRenderError?: (error: Error) => void;\n  onAnnotationClick?: (annotation: Annotation) => void;\n  onPageClick?: (pageNumber: number, point: { x: number; y: number }) => void;\n}\n\nexport const PDFPage = memo(function PDFPage({\n  pageNumber,\n  page,\n  scale,\n  rotation,\n  className,\n  showTextLayer = true,\n  showHighlightLayer = true,\n  showAnnotationLayer = true,\n  onRenderComplete,\n  onRenderError,\n  onAnnotationClick,\n  onPageClick,\n}: PDFPageProps) {\n  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });\n  const [isRendering, setIsRendering] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n\n  // Subscribe to highlights and annotations arrays directly to trigger re-renders\n  const allHighlights = useAnnotationStore((s) => s.highlights);\n  const allAnnotations = useAnnotationStore((s) => s.annotations);\n  const selectHighlight = useAnnotationStore((s) => s.selectHighlight);\n  const selectedHighlightId = useAnnotationStore((s) => s.selectedHighlightId);\n\n  // Get annotations state\n  const selectAnnotation = useAnnotationStore((s) => s.selectAnnotation);\n  const selectedAnnotationId = useAnnotationStore((s) => s.selectedAnnotationId);\n  const activeAnnotationTool = useAnnotationStore((s) => s.activeAnnotationTool);\n  const drawingColor = useAnnotationStore((s) => s.drawingColor);\n  const drawingStrokeWidth = useAnnotationStore((s) => s.drawingStrokeWidth);\n  const currentDrawingPath = useAnnotationStore((s) => s.currentDrawingPath);\n  const currentDrawingPage = useAnnotationStore((s) => s.currentDrawingPage);\n  const startDrawing = useAnnotationStore((s) => s.startDrawing);\n  const addDrawingPoint = useAnnotationStore((s) => s.addDrawingPoint);\n  const finishDrawing = useAnnotationStore((s) => s.finishDrawing);\n\n  // Filter highlights and annotations for this page\n  const highlights = useMemo(\n    () => allHighlights.filter((h) => h.pageNumber === pageNumber),\n    [allHighlights, pageNumber]\n  );\n  const annotations = useMemo(\n    () => allAnnotations.filter((a) => a.pageNumber === pageNumber),\n    [allAnnotations, pageNumber]\n  );\n\n  // Calculate dimensions when page or scale changes\n  useEffect(() => {\n    if (page) {\n      const viewport = page.getViewport({ scale, rotation });\n      setDimensions({\n        width: Math.floor(viewport.width),\n        height: Math.floor(viewport.height),\n      });\n    }\n  }, [page, scale, rotation]);\n\n  const handleRenderStart = useCallback(() => {\n    setIsRendering(true);\n    setError(null);\n  }, []);\n\n  const handleRenderComplete = useCallback(() => {\n    setIsRendering(false);\n    onRenderComplete?.();\n  }, [onRenderComplete]);\n\n  const handleRenderError = useCallback(\n    (err: Error) => {\n      setIsRendering(false);\n      setError(err);\n      onRenderError?.(err);\n    },\n    [onRenderError]\n  );\n\n  const handleHighlightClick = useCallback(\n    (highlight: Highlight) => {\n      selectHighlight(highlight.id);\n    },\n    [selectHighlight]\n  );\n\n  const handleAnnotationClick = useCallback(\n    (annotation: Annotation) => {\n      selectAnnotation(annotation.id);\n      onAnnotationClick?.(annotation);\n    },\n    [selectAnnotation, onAnnotationClick]\n  );\n\n  const handleDrawStart = useCallback(\n    (point: { x: number; y: number }) => {\n      startDrawing(pageNumber, point);\n    },\n    [startDrawing, pageNumber]\n  );\n\n  const handleDrawMove = useCallback(\n    (point: { x: number; y: number }) => {\n      addDrawingPoint(point);\n    },\n    [addDrawingPoint]\n  );\n\n  const handleDrawEnd = useCallback(() => {\n    finishDrawing();\n  }, [finishDrawing]);\n\n  const handlePageClick = useCallback(\n    (point: { x: number; y: number }) => {\n      onPageClick?.(pageNumber, point);\n    },\n    [onPageClick, pageNumber]\n  );\n\n  if (!page) {\n    return (\n      <div\n        className={cn(\n          'pdf-page pdf-page-loading',\n          'relative bg-white shadow-lg',\n          'flex items-center justify-center',\n          className\n        )}\n        style={{ width: 612 * scale, height: 792 * scale }}\n        data-page-number={pageNumber}\n      >\n        <div className=\"text-gray-400\">Loading page {pageNumber}...</div>\n      </div>\n    );\n  }\n\n  if (error) {\n    return (\n      <div\n        className={cn(\n          'pdf-page pdf-page-error',\n          'relative bg-white shadow-lg',\n          'flex items-center justify-center',\n          className\n        )}\n        style={{ width: dimensions.width, height: dimensions.height }}\n        data-page-number={pageNumber}\n      >\n        <div className=\"text-red-500\">Failed to render page {pageNumber}</div>\n      </div>\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        'pdf-page',\n        'relative bg-white shadow-lg',\n        isRendering && 'pdf-page-rendering',\n        className\n      )}\n      style={{\n        width: dimensions.width,\n        height: dimensions.height,\n      }}\n      data-page-number={pageNumber}\n    >\n      <CanvasLayer\n        page={page}\n        scale={scale}\n        rotation={rotation}\n        onRenderStart={handleRenderStart}\n        onRenderComplete={handleRenderComplete}\n        onRenderError={handleRenderError}\n      />\n\n      {showTextLayer && (\n        <TextLayer page={page} scale={scale} rotation={rotation} />\n      )}\n\n      {showHighlightLayer && highlights.length > 0 && (\n        <HighlightLayer\n          highlights={highlights}\n          scale={scale}\n          selectedId={selectedHighlightId}\n          onHighlightClick={handleHighlightClick}\n        />\n      )}\n\n      {showAnnotationLayer && (\n        <AnnotationLayer\n          pageNumber={pageNumber}\n          annotations={annotations}\n          scale={scale}\n          selectedId={selectedAnnotationId}\n          isDrawing={currentDrawingPage === pageNumber}\n          currentDrawingPath={currentDrawingPage === pageNumber ? currentDrawingPath : null}\n          drawingColor={drawingColor}\n          drawingStrokeWidth={drawingStrokeWidth}\n          activeAnnotationTool={activeAnnotationTool}\n          onAnnotationClick={handleAnnotationClick}\n          onDrawStart={handleDrawStart}\n          onDrawMove={handleDrawMove}\n          onDrawEnd={handleDrawEnd}\n          onPageClick={handlePageClick}\n        />\n      )}\n    </div>\n  );\n});\n","import { memo, useMemo } from 'react';\nimport type { FocusedRegion } from '../../types/agent-context';\nimport { cn } from '../../utils';\n\nexport interface FocusRegionLayerProps {\n  focusedRegions: FocusedRegion[];\n  scale: number;\n  pageNumber: number;\n  className?: string;\n}\n\nconst FOCUS_STYLES = {\n  pulse: {\n    animation: 'focus-pulse 2s ease-in-out infinite',\n    border: '3px solid',\n    boxShadow: '0 0 0 0 rgba(59, 130, 246, 0.7)',\n  },\n  glow: {\n    animation: 'focus-glow 1.5s ease-in-out infinite alternate',\n    border: '2px solid',\n    boxShadow: '0 0 20px 5px',\n  },\n  border: {\n    animation: 'none',\n    border: '3px dashed',\n    boxShadow: 'none',\n  },\n};\n\nconst DEFAULT_COLORS = {\n  pulse: '#3b82f6', // blue-500\n  glow: '#f59e0b', // amber-500\n  border: '#10b981', // emerald-500\n};\n\nexport const FocusRegionLayer = memo(function FocusRegionLayer({\n  focusedRegions,\n  scale,\n  pageNumber,\n  className,\n}: FocusRegionLayerProps) {\n  // Filter regions for this page\n  const pageRegions = useMemo(\n    () => focusedRegions.filter((r) => r.pageNumber === pageNumber),\n    [focusedRegions, pageNumber]\n  );\n\n  const renderedRegions = useMemo(() => {\n    return pageRegions.map((region) => {\n      const style = region.style ?? 'pulse';\n      const color = region.color ?? DEFAULT_COLORS[style];\n      const styleConfig = FOCUS_STYLES[style];\n\n      return (\n        <div\n          key={region.id}\n          className={cn(\n            'focus-region',\n            'absolute rounded-sm pointer-events-none',\n            `focus-region-${style}`\n          )}\n          style={{\n            left: region.x * scale,\n            top: region.y * scale,\n            width: region.width * scale,\n            height: region.height * scale,\n            borderColor: color,\n            borderStyle: style === 'border' ? 'dashed' : 'solid',\n            borderWidth: style === 'border' ? '3px' : '2px',\n            boxShadow: style === 'glow' ? `0 0 20px 5px ${color}40` : undefined,\n            animation: styleConfig.animation,\n          }}\n          data-focus-id={region.id}\n          data-focus-style={style}\n        />\n      );\n    });\n  }, [pageRegions, scale]);\n\n  if (pageRegions.length === 0) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\n        'pdf-focus-region-layer',\n        'absolute inset-0 pointer-events-none overflow-hidden',\n        className\n      )}\n      style={{ zIndex: 45 }}\n    >\n      {renderedRegions}\n      <style>{`\n        @keyframes focus-pulse {\n          0% {\n            box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n          }\n          70% {\n            box-shadow: 0 0 0 10px rgba(59, 130, 246, 0);\n          }\n          100% {\n            box-shadow: 0 0 0 0 rgba(59, 130, 246, 0);\n          }\n        }\n\n        @keyframes focus-glow {\n          0% {\n            opacity: 0.8;\n            filter: brightness(1);\n          }\n          100% {\n            opacity: 1;\n            filter: brightness(1.2);\n          }\n        }\n\n        .focus-region-pulse {\n          animation: focus-pulse 2s ease-in-out infinite;\n        }\n\n        .focus-region-glow {\n          animation: focus-glow 1.5s ease-in-out infinite alternate;\n        }\n      `}</style>\n    </div>\n  );\n});\n","export { PDFPage, type PDFPageProps } from './PDFPage';\nexport { CanvasLayer, type CanvasLayerProps } from './CanvasLayer';\nexport { TextLayer, type TextLayerProps } from './TextLayer';\nexport { HighlightLayer, type HighlightLayerProps } from './HighlightLayer';\nexport { AnnotationLayer, type AnnotationLayerProps } from './AnnotationLayer';\nexport { FocusRegionLayer, type FocusRegionLayerProps } from './FocusRegionLayer';\n","import { memo } from 'react';\nimport { cn } from '../../utils';\n\nexport interface PDFLoadingScreenProps {\n  /** 0-100 progress percentage, undefined for indeterminate */\n  progress?: number;\n  /** Bytes loaded */\n  bytesLoaded?: number;\n  /** Total bytes */\n  totalBytes?: number;\n  /** Current loading phase */\n  phase?: 'initializing' | 'fetching' | 'parsing' | 'rendering';\n  /** Optional: document title for context */\n  documentName?: string;\n  /** Additional class name */\n  className?: string;\n  /** Show compact inline mode for streaming progress */\n  compact?: boolean;\n  /** Show streaming progress (when first page is ready but background loading continues) */\n  showStreamingProgress?: boolean;\n}\n\nconst phaseMessages: Record<string, string> = {\n  initializing: 'Preparing viewer',\n  fetching: 'Loading document',\n  parsing: 'Processing pages',\n  rendering: 'Almost ready',\n};\n\n// Phase descriptions for future enhanced loading messages\n// const phaseDescriptions: Record<string, string> = {\n//   initializing: 'Setting up the PDF viewer...',\n//   fetching: 'Downloading the PDF file...',\n//   parsing: 'Analyzing document structure...',\n//   rendering: 'Preparing pages for display...',\n// };\n\nfunction formatBytes(bytes: number): string {\n  if (bytes < 1024) return `${bytes} B`;\n  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/**\n * Beautiful loading screen for PDF documents.\n * Shows animated document icon, progress bar, and phase-specific messages.\n */\nexport const PDFLoadingScreen = memo(function PDFLoadingScreen({\n  progress,\n  bytesLoaded,\n  totalBytes,\n  phase = 'fetching',\n  documentName,\n  className,\n  compact = false,\n  showStreamingProgress = false,\n}: PDFLoadingScreenProps) {\n  const hasProgress = progress !== undefined && progress >= 0;\n  const hasBytes = bytesLoaded !== undefined && totalBytes !== undefined && totalBytes > 0;\n\n  // Compact mode for inline streaming progress\n  if (compact || showStreamingProgress) {\n    return (\n      <div\n        className={cn(\n          'pdf-loading-compact',\n          'flex items-center gap-3 px-4 py-3 bg-gray-800 text-white rounded-lg shadow-lg',\n          className\n        )}\n        role=\"status\"\n        aria-live=\"polite\"\n      >\n        {/* Spinner */}\n        <div\n          style={{\n            width: 20,\n            height: 20,\n            border: '2px solid rgba(255,255,255,0.3)',\n            borderTopColor: '#fff',\n            borderRadius: '50%',\n            animation: 'spin 0.8s linear infinite',\n          }}\n        />\n\n        {/* Text */}\n        <span className=\"text-sm font-medium\">\n          {phaseMessages[phase]}\n        </span>\n\n        {/* Progress */}\n        {hasProgress && (\n          <span className=\"text-sm text-white/70\">\n            {Math.round(progress)}%\n          </span>\n        )}\n\n        {/* Bytes */}\n        {hasBytes && (\n          <span className=\"text-xs text-white/50 font-mono\">\n            {formatBytes(bytesLoaded)} / {formatBytes(totalBytes)}\n          </span>\n        )}\n\n        <style>{`\n          @keyframes spin {\n            0% { transform: rotate(0deg); }\n            100% { transform: rotate(360deg); }\n          }\n        `}</style>\n      </div>\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        'pdf-loading-screen',\n        className\n      )}\n      style={{\n        display: 'flex',\n        flexDirection: 'column',\n        alignItems: 'center',\n        justifyContent: 'center',\n        width: '100%',\n        height: '100%',\n        minHeight: '400px',\n        background: 'linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%)',\n        fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n      }}\n      role=\"status\"\n      aria-live=\"polite\"\n      aria-label={phaseMessages[phase]}\n    >\n      {/* Main loading card */}\n      <div\n        style={{\n          display: 'flex',\n          flexDirection: 'column',\n          alignItems: 'center',\n          padding: '48px 40px',\n          background: 'white',\n          borderRadius: '20px',\n          boxShadow: '0 10px 40px -10px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.05)',\n        }}\n      >\n        {/* Animated document icon */}\n        <div\n          className=\"pdf-loading-icon-container\"\n          style={{\n            position: 'relative',\n            marginBottom: '32px',\n          }}\n        >\n          {/* Glow effect */}\n          <div\n            className=\"pdf-loading-glow\"\n            style={{\n              position: 'absolute',\n              top: '50%',\n              left: '50%',\n              width: '120px',\n              height: '120px',\n              transform: 'translate(-50%, -50%)',\n              background: 'radial-gradient(circle, rgba(59, 130, 246, 0.15) 0%, transparent 70%)',\n              borderRadius: '50%',\n            }}\n          />\n\n          {/* Document icon */}\n          <svg\n            width=\"72\"\n            height=\"88\"\n            viewBox=\"0 0 72 88\"\n            fill=\"none\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n            className=\"pdf-document-icon\"\n            style={{\n              position: 'relative',\n              zIndex: 1,\n              filter: 'drop-shadow(0 8px 16px rgba(0, 0, 0, 0.1))',\n            }}\n          >\n            {/* Page background */}\n            <path\n              d=\"M4 8C4 3.58172 7.58172 0 12 0H44L68 24V80C68 84.4183 64.4183 88 60 88H12C7.58172 88 4 84.4183 4 80V8Z\"\n              fill=\"#ffffff\"\n              stroke=\"#e2e8f0\"\n              strokeWidth=\"2\"\n            />\n            {/* Folded corner */}\n            <path\n              d=\"M44 0L68 24H52C47.5817 24 44 20.4183 44 16V0Z\"\n              fill=\"#dbeafe\"\n            />\n            {/* PDF badge */}\n            <rect\n              x=\"14\"\n              y=\"36\"\n              width=\"44\"\n              height=\"20\"\n              rx=\"4\"\n              fill=\"#3b82f6\"\n            />\n            <text\n              x=\"36\"\n              y=\"50\"\n              textAnchor=\"middle\"\n              fill=\"white\"\n              style={{\n                fontSize: '12px',\n                fontWeight: 700,\n                fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n              }}\n            >\n              PDF\n            </text>\n            {/* Animated lines */}\n            <rect className=\"pdf-line-1\" x=\"14\" y=\"64\" width=\"44\" height=\"4\" rx=\"2\" fill=\"#e2e8f0\" />\n            <rect className=\"pdf-line-2\" x=\"14\" y=\"72\" width=\"32\" height=\"4\" rx=\"2\" fill=\"#e2e8f0\" />\n          </svg>\n        </div>\n\n        {/* Document name if available */}\n        {documentName && (\n          <p\n            style={{\n              fontSize: '13px',\n              fontWeight: 500,\n              color: '#64748b',\n              marginBottom: '8px',\n              maxWidth: '240px',\n              overflow: 'hidden',\n              textOverflow: 'ellipsis',\n              whiteSpace: 'nowrap',\n              textAlign: 'center',\n            }}\n          >\n            {documentName}\n          </p>\n        )}\n\n        {/* Phase message */}\n        <p\n          style={{\n            fontSize: '16px',\n            fontWeight: 600,\n            color: '#1e293b',\n            marginBottom: '24px',\n            textAlign: 'center',\n          }}\n        >\n          {phaseMessages[phase]}\n          <span className=\"pdf-loading-dots\" style={{ display: 'inline-block', width: '24px', textAlign: 'left' }}>\n            <span className=\"pdf-dot-1\">.</span>\n            <span className=\"pdf-dot-2\">.</span>\n            <span className=\"pdf-dot-3\">.</span>\n          </span>\n        </p>\n\n        {/* Progress bar */}\n        <div style={{ width: '240px' }}>\n          <div\n            style={{\n              width: '100%',\n              height: '8px',\n              borderRadius: '4px',\n              background: '#e2e8f0',\n              overflow: 'hidden',\n            }}\n          >\n            <div\n              className={cn(\n                'pdf-loading-progress-fill',\n                !hasProgress && 'pdf-loading-progress-indeterminate'\n              )}\n              style={{\n                height: '100%',\n                borderRadius: '4px',\n                background: 'linear-gradient(90deg, #3b82f6 0%, #60a5fa 50%, #3b82f6 100%)',\n                backgroundSize: '200% 100%',\n                transition: 'width 300ms ease-out',\n                ...(hasProgress ? { width: `${Math.min(100, progress)}%` } : {}),\n              }}\n            />\n          </div>\n\n          {/* Progress details */}\n          {(hasProgress || hasBytes) && (\n            <div\n              style={{\n                display: 'flex',\n                justifyContent: 'space-between',\n                marginTop: '12px',\n                fontSize: '13px',\n                fontWeight: 500,\n              }}\n            >\n              {hasProgress && (\n                <span style={{ color: '#3b82f6' }}>\n                  {Math.round(progress)}%\n                </span>\n              )}\n              {hasBytes && (\n                <span style={{ color: '#94a3b8', fontFamily: 'ui-monospace, monospace', fontSize: '12px' }}>\n                  {formatBytes(bytesLoaded)} / {formatBytes(totalBytes)}\n                </span>\n              )}\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n});\n","export { PDFLoadingScreen } from './PDFLoadingScreen';\nexport type { PDFLoadingScreenProps } from './PDFLoadingScreen';\n","import { memo } from 'react';\nimport { cn } from '../../utils';\n\nexport interface PageSkeletonProps {\n  /** Page number to display */\n  pageNumber: number;\n  /** Width of the skeleton (in pixels) */\n  width: number;\n  /** Height of the skeleton (in pixels) */\n  height: number;\n  /** Additional class name */\n  className?: string;\n  /** Whether this is the first page (show different message) */\n  isFirstPage?: boolean;\n}\n\n/**\n * Page skeleton component shown while a PDF page is loading.\n * Displays an animated placeholder with the page number.\n */\nexport const PageSkeleton = memo(function PageSkeleton({\n  pageNumber,\n  width,\n  height,\n  className,\n  isFirstPage = false,\n}: PageSkeletonProps) {\n  return (\n    <div\n      className={cn(\n        'pdf-page-skeleton',\n        'relative bg-white shadow-lg overflow-hidden',\n        'flex items-center justify-center',\n        className\n      )}\n      style={{\n        width,\n        height,\n        minWidth: width,\n        minHeight: height,\n      }}\n      data-page-number={pageNumber}\n      role=\"img\"\n      aria-label={`Loading page ${pageNumber}`}\n    >\n      {/* Animated shimmer effect */}\n      <div\n        className=\"absolute inset-0 pdf-skeleton-shimmer\"\n        style={{\n          background: 'linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%)',\n          backgroundSize: '200% 100%',\n          animation: 'shimmer 1.5s infinite linear',\n        }}\n      />\n\n      {/* Content placeholder lines */}\n      <div className=\"absolute inset-0 p-6 flex flex-col\" style={{ opacity: 0.4 }}>\n        {/* Header area */}\n        <div\n          className=\"rounded\"\n          style={{\n            width: '60%',\n            height: 12,\n            background: '#e0e0e0',\n            marginBottom: 16,\n          }}\n        />\n\n        {/* Content lines */}\n        {[...Array(Math.min(12, Math.floor(height / 40)))].map((_, i) => (\n          <div\n            key={i}\n            className=\"rounded\"\n            style={{\n              width: `${75 + Math.sin(i * 0.7) * 20}%`,\n              height: 8,\n              background: '#e0e0e0',\n              marginBottom: 12,\n            }}\n          />\n        ))}\n      </div>\n\n      {/* Loading indicator overlay */}\n      <div className=\"relative z-10 flex flex-col items-center gap-3 p-6 rounded-lg bg-white/90 shadow-sm\">\n        {/* Spinner */}\n        <div\n          className=\"pdf-skeleton-spinner\"\n          style={{\n            width: 32,\n            height: 32,\n            border: '3px solid #e5e7eb',\n            borderTopColor: '#3b82f6',\n            borderRadius: '50%',\n            animation: 'spin 0.8s linear infinite',\n          }}\n        />\n\n        {/* Loading text */}\n        <div className=\"text-sm text-gray-500 font-medium\">\n          {isFirstPage ? 'Loading document...' : `Loading page ${pageNumber}`}\n        </div>\n      </div>\n\n      {/* Inline styles for animations */}\n      <style>{`\n        @keyframes shimmer {\n          0% { background-position: 200% 0; }\n          100% { background-position: -200% 0; }\n        }\n        @keyframes spin {\n          0% { transform: rotate(0deg); }\n          100% { transform: rotate(360deg); }\n        }\n      `}</style>\n    </div>\n  );\n});\n\n// Default dimensions based on US Letter size\nexport const DEFAULT_PAGE_WIDTH = 612;\nexport const DEFAULT_PAGE_HEIGHT = 792;\n","import { memo, useEffect, useState, useCallback, useRef } from 'react';\nimport type { TextSelection, HighlightColor } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface SelectionToolbarProps {\n  /** Current text selection */\n  selection: TextSelection | null;\n  /** Callback when a color is clicked to create highlight */\n  onCreateHighlight: (color: HighlightColor) => void;\n  /** Callback when copy button is clicked */\n  onCopy?: () => void;\n  /** Active/default highlight color */\n  activeColor?: HighlightColor;\n  /** Additional class name */\n  className?: string;\n}\n\ninterface ToolbarPosition {\n  top: number;\n  left: number;\n  visible: boolean;\n}\n\nconst HIGHLIGHT_COLOR_BUTTONS: Array<{\n  color: HighlightColor;\n  bg: string;\n  hoverBg: string;\n  ringColor: string;\n}> = [\n  { color: 'yellow', bg: 'bg-yellow-300', hoverBg: 'hover:bg-yellow-400', ringColor: 'ring-yellow-400' },\n  { color: 'green', bg: 'bg-green-300', hoverBg: 'hover:bg-green-400', ringColor: 'ring-green-400' },\n  { color: 'blue', bg: 'bg-blue-300', hoverBg: 'hover:bg-blue-400', ringColor: 'ring-blue-400' },\n  { color: 'pink', bg: 'bg-pink-300', hoverBg: 'hover:bg-pink-400', ringColor: 'ring-pink-400' },\n  { color: 'orange', bg: 'bg-orange-300', hoverBg: 'hover:bg-orange-400', ringColor: 'ring-orange-400' },\n];\n\nfunction calculatePosition(selection: TextSelection): ToolbarPosition {\n  if (!selection || selection.rects.length === 0) {\n    return { top: 0, left: 0, visible: false };\n  }\n\n  // Find the first rect (topmost, leftmost)\n  const firstRect = selection.rects.reduce((min, rect) => {\n    if (rect.top < min.top || (rect.top === min.top && rect.left < min.left)) {\n      return rect;\n    }\n    return min;\n  }, selection.rects[0]);\n\n  // Position toolbar above the selection\n  const top = firstRect.top - 48; // 48px above (40px toolbar height + 8px gap)\n  const left = firstRect.left + firstRect.width / 2;\n\n  return { top, left, visible: true };\n}\n\nexport const SelectionToolbar = memo(function SelectionToolbar({\n  selection,\n  onCreateHighlight,\n  onCopy,\n  activeColor = 'yellow',\n  className,\n}: SelectionToolbarProps) {\n  const [position, setPosition] = useState<ToolbarPosition>({ top: 0, left: 0, visible: false });\n  const toolbarRef = useRef<HTMLDivElement>(null);\n\n  // Calculate position when selection changes\n  useEffect(() => {\n    if (selection && selection.text && selection.rects.length > 0) {\n      const newPosition = calculatePosition(selection);\n\n      // Adjust position to keep toolbar within viewport\n      if (toolbarRef.current && newPosition.visible) {\n        const toolbarWidth = 200; // Approximate toolbar width\n        const viewportWidth = window.innerWidth;\n\n        // Ensure toolbar doesn't go off left edge\n        let adjustedLeft = newPosition.left - toolbarWidth / 2;\n        if (adjustedLeft < 8) adjustedLeft = 8;\n\n        // Ensure toolbar doesn't go off right edge\n        if (adjustedLeft + toolbarWidth > viewportWidth - 8) {\n          adjustedLeft = viewportWidth - toolbarWidth - 8;\n        }\n\n        // Ensure toolbar doesn't go above viewport\n        let adjustedTop = newPosition.top;\n        if (adjustedTop < 8) {\n          // Position below selection instead\n          const lastRect = selection.rects[selection.rects.length - 1];\n          adjustedTop = lastRect.bottom + 8;\n        }\n\n        setPosition({\n          top: adjustedTop,\n          left: adjustedLeft + toolbarWidth / 2,\n          visible: true,\n        });\n      } else {\n        setPosition(newPosition);\n      }\n    } else {\n      setPosition({ top: 0, left: 0, visible: false });\n    }\n  }, [selection]);\n\n  const handleColorClick = useCallback(\n    (color: HighlightColor) => {\n      onCreateHighlight(color);\n    },\n    [onCreateHighlight]\n  );\n\n  const handleCopy = useCallback(() => {\n    onCopy?.();\n  }, [onCopy]);\n\n  if (!position.visible || !selection?.text) {\n    return null;\n  }\n\n  return (\n    <div\n      ref={toolbarRef}\n      className={cn(\n        'selection-toolbar',\n        'fixed z-50',\n        'flex items-center gap-1 p-1.5',\n        'bg-white dark:bg-gray-800',\n        'rounded-lg shadow-lg',\n        'border border-gray-200 dark:border-gray-700',\n        'animate-in fade-in zoom-in-95 duration-150',\n        className\n      )}\n      style={{\n        top: position.top,\n        left: position.left,\n        transform: 'translateX(-50%)',\n      }}\n      onMouseDown={(e) => {\n        // Prevent toolbar clicks from clearing the selection\n        e.preventDefault();\n        e.stopPropagation();\n      }}\n    >\n      {/* Highlight color buttons */}\n      {HIGHLIGHT_COLOR_BUTTONS.map((btn) => (\n        <button\n          key={btn.color}\n          onClick={() => handleColorClick(btn.color)}\n          className={cn(\n            'w-7 h-7 rounded-full',\n            'flex items-center justify-center',\n            'transition-transform duration-100',\n            'hover:scale-110',\n            'focus:outline-none focus:ring-2 focus:ring-offset-1',\n            btn.bg,\n            btn.hoverBg,\n            btn.ringColor,\n            activeColor === btn.color && 'ring-2 ring-offset-1'\n          )}\n          title={`Highlight ${btn.color}`}\n          aria-label={`Highlight with ${btn.color}`}\n        >\n          {/* Highlighter icon */}\n          <svg className=\"w-4 h-4 text-gray-700\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n            <path\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth={2}\n              d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\"\n            />\n          </svg>\n        </button>\n      ))}\n\n      {/* Divider */}\n      <div className=\"w-px h-6 bg-gray-300 dark:bg-gray-600 mx-1\" />\n\n      {/* Copy button */}\n      <button\n        onClick={handleCopy}\n        className={cn(\n          'p-1.5 rounded-md',\n          'text-gray-600 dark:text-gray-300',\n          'hover:bg-gray-100 dark:hover:bg-gray-700',\n          'focus:outline-none focus:ring-2 focus:ring-blue-500'\n        )}\n        title=\"Copy text\"\n        aria-label=\"Copy selected text\"\n      >\n        <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n          <path\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth={2}\n            d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n          />\n        </svg>\n      </button>\n    </div>\n  );\n});\n\nexport default SelectionToolbar;\n","export { SelectionToolbar, type SelectionToolbarProps } from './SelectionToolbar';\n","import { memo, useCallback, useState, useRef, useEffect } from 'react';\nimport type { Highlight, HighlightColor } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface HighlightPopoverProps {\n  /** The highlight to show the popover for */\n  highlight: Highlight | null;\n  /** The scale of the PDF page */\n  scale: number;\n  /** The page element containing the highlight */\n  pageElement: HTMLElement | null;\n  /** Callback when color is changed */\n  onColorChange: (id: string, color: HighlightColor) => void;\n  /** Callback when comment is updated */\n  onCommentChange: (id: string, comment: string) => void;\n  /** Callback when delete is clicked */\n  onDelete: (id: string) => void;\n  /** Callback when copy is clicked */\n  onCopy?: (text: string) => void;\n  /** Callback when popover is closed */\n  onClose: () => void;\n  /** Additional class name */\n  className?: string;\n}\n\ninterface PopoverPosition {\n  top: number;\n  left: number;\n  visible: boolean;\n}\n\nconst HIGHLIGHT_COLOR_OPTIONS: Array<{\n  color: HighlightColor;\n  bg: string;\n  hoverBg: string;\n  borderColor: string;\n}> = [\n  { color: 'yellow', bg: 'bg-yellow-300', hoverBg: 'hover:bg-yellow-400', borderColor: 'border-yellow-400' },\n  { color: 'green', bg: 'bg-green-300', hoverBg: 'hover:bg-green-400', borderColor: 'border-green-400' },\n  { color: 'blue', bg: 'bg-blue-300', hoverBg: 'hover:bg-blue-400', borderColor: 'border-blue-400' },\n  { color: 'pink', bg: 'bg-pink-300', hoverBg: 'hover:bg-pink-400', borderColor: 'border-pink-400' },\n  { color: 'orange', bg: 'bg-orange-300', hoverBg: 'hover:bg-orange-400', borderColor: 'border-orange-400' },\n];\n\nfunction calculatePopoverPosition(\n  highlight: Highlight,\n  scale: number,\n  pageElement: HTMLElement | null\n): PopoverPosition {\n  if (!pageElement || !highlight.rects.length) {\n    return { top: 0, left: 0, visible: false };\n  }\n\n  const pageRect = pageElement.getBoundingClientRect();\n\n  // Find the first rect of the highlight\n  const firstRect = highlight.rects[0];\n  const scaledTop = firstRect.y * scale + pageRect.top;\n  const scaledLeft = firstRect.x * scale + pageRect.left;\n  const scaledWidth = firstRect.width * scale;\n\n  // Position popover above the highlight\n  const top = scaledTop - 8;\n  const left = scaledLeft + scaledWidth / 2;\n\n  return { top, left, visible: true };\n}\n\nexport const HighlightPopover = memo(function HighlightPopover({\n  highlight,\n  scale,\n  pageElement,\n  onColorChange,\n  onCommentChange,\n  onDelete,\n  onCopy,\n  onClose,\n  className,\n}: HighlightPopoverProps) {\n  const [isEditingComment, setIsEditingComment] = useState(false);\n  const [comment, setComment] = useState(highlight?.comment ?? '');\n  const [position, setPosition] = useState<PopoverPosition>({ top: 0, left: 0, visible: false });\n  const popoverRef = useRef<HTMLDivElement>(null);\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n  // Update comment state when highlight changes\n  useEffect(() => {\n    setComment(highlight?.comment ?? '');\n    setIsEditingComment(false);\n  }, [highlight?.id, highlight?.comment]);\n\n  // Calculate position when highlight or page element changes\n  useEffect(() => {\n    if (highlight && pageElement) {\n      const newPosition = calculatePopoverPosition(highlight, scale, pageElement);\n\n      if (newPosition.visible && popoverRef.current) {\n        const popoverWidth = 280;\n        const viewportWidth = window.innerWidth;\n\n        let adjustedLeft = newPosition.left;\n        if (adjustedLeft - popoverWidth / 2 < 8) {\n          adjustedLeft = popoverWidth / 2 + 8;\n        } else if (adjustedLeft + popoverWidth / 2 > viewportWidth - 8) {\n          adjustedLeft = viewportWidth - popoverWidth / 2 - 8;\n        }\n\n        let adjustedTop = newPosition.top;\n        const popoverHeight = isEditingComment ? 200 : 120;\n        if (adjustedTop - popoverHeight < 8) {\n          // Position below the highlight instead\n          const lastRect = highlight.rects[highlight.rects.length - 1];\n          adjustedTop = (lastRect.y + lastRect.height) * scale + pageElement.getBoundingClientRect().top + 8;\n        }\n\n        setPosition({\n          top: adjustedTop,\n          left: adjustedLeft,\n          visible: true,\n        });\n      } else {\n        setPosition(newPosition);\n      }\n    } else {\n      setPosition({ top: 0, left: 0, visible: false });\n    }\n  }, [highlight, pageElement, scale, isEditingComment]);\n\n  // Focus textarea when editing starts\n  useEffect(() => {\n    if (isEditingComment && textareaRef.current) {\n      textareaRef.current.focus();\n    }\n  }, [isEditingComment]);\n\n  // Close popover when clicking outside\n  useEffect(() => {\n    function handleClickOutside(event: MouseEvent) {\n      if (popoverRef.current && !popoverRef.current.contains(event.target as Node)) {\n        onClose();\n      }\n    }\n\n    if (position.visible) {\n      document.addEventListener('mousedown', handleClickOutside);\n      return () => document.removeEventListener('mousedown', handleClickOutside);\n    }\n  }, [position.visible, onClose]);\n\n  // Handle escape key\n  useEffect(() => {\n    function handleKeyDown(event: KeyboardEvent) {\n      if (event.key === 'Escape') {\n        if (isEditingComment) {\n          setIsEditingComment(false);\n          setComment(highlight?.comment ?? '');\n        } else {\n          onClose();\n        }\n      }\n    }\n\n    if (position.visible) {\n      document.addEventListener('keydown', handleKeyDown);\n      return () => document.removeEventListener('keydown', handleKeyDown);\n    }\n  }, [position.visible, isEditingComment, highlight?.comment, onClose]);\n\n  const handleColorClick = useCallback(\n    (color: HighlightColor) => {\n      if (highlight) {\n        onColorChange(highlight.id, color);\n      }\n    },\n    [highlight, onColorChange]\n  );\n\n  const handleSaveComment = useCallback(() => {\n    if (highlight) {\n      onCommentChange(highlight.id, comment.trim());\n      setIsEditingComment(false);\n    }\n  }, [highlight, comment, onCommentChange]);\n\n  const handleDeleteClick = useCallback(() => {\n    if (highlight) {\n      onDelete(highlight.id);\n      onClose();\n    }\n  }, [highlight, onDelete, onClose]);\n\n  const handleCopyClick = useCallback(() => {\n    if (highlight?.text) {\n      navigator.clipboard.writeText(highlight.text);\n      onCopy?.(highlight.text);\n    }\n  }, [highlight, onCopy]);\n\n  if (!highlight || !position.visible) {\n    return null;\n  }\n\n  return (\n    <div\n      ref={popoverRef}\n      className={cn(\n        'highlight-popover',\n        'fixed z-50',\n        'bg-white dark:bg-gray-800',\n        'rounded-lg shadow-xl',\n        'border border-gray-200 dark:border-gray-700',\n        'animate-in fade-in zoom-in-95 duration-150',\n        className\n      )}\n      style={{\n        top: position.top,\n        left: position.left,\n        transform: 'translate(-50%, -100%)',\n        width: 280,\n      }}\n    >\n      {/* Color picker row */}\n      <div className=\"flex items-center justify-between p-2 border-b border-gray-200 dark:border-gray-700\">\n        <div className=\"flex items-center gap-1\">\n          {HIGHLIGHT_COLOR_OPTIONS.map((opt) => (\n            <button\n              key={opt.color}\n              onClick={() => handleColorClick(opt.color)}\n              className={cn(\n                'w-6 h-6 rounded-full',\n                'transition-transform duration-100',\n                'hover:scale-110',\n                'focus:outline-none',\n                opt.bg,\n                opt.hoverBg,\n                highlight.color === opt.color && `ring-2 ring-offset-1 ${opt.borderColor}`\n              )}\n              title={`Change to ${opt.color}`}\n              aria-label={`Change highlight color to ${opt.color}`}\n            />\n          ))}\n        </div>\n\n        {/* Delete button */}\n        <button\n          onClick={handleDeleteClick}\n          className={cn(\n            'p-1.5 rounded-md',\n            'text-red-500 hover:text-red-600',\n            'hover:bg-red-50 dark:hover:bg-red-900/20',\n            'focus:outline-none focus:ring-2 focus:ring-red-500'\n          )}\n          title=\"Delete highlight\"\n          aria-label=\"Delete highlight\"\n        >\n          <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n            <path\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth={2}\n              d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n            />\n          </svg>\n        </button>\n      </div>\n\n      {/* Comment section */}\n      <div className=\"p-2\">\n        {isEditingComment ? (\n          <div className=\"space-y-2\">\n            <textarea\n              ref={textareaRef}\n              value={comment}\n              onChange={(e) => setComment(e.target.value)}\n              placeholder=\"Add a note...\"\n              className={cn(\n                'w-full p-2 text-sm',\n                'rounded-md border border-gray-300 dark:border-gray-600',\n                'bg-white dark:bg-gray-700',\n                'text-gray-900 dark:text-gray-100',\n                'placeholder-gray-500 dark:placeholder-gray-400',\n                'focus:outline-none focus:ring-2 focus:ring-blue-500',\n                'resize-none'\n              )}\n              rows={3}\n            />\n            <div className=\"flex justify-end gap-2\">\n              <button\n                onClick={() => {\n                  setIsEditingComment(false);\n                  setComment(highlight.comment ?? '');\n                }}\n                className={cn(\n                  'px-3 py-1 text-sm rounded-md',\n                  'text-gray-600 dark:text-gray-300',\n                  'hover:bg-gray-100 dark:hover:bg-gray-700',\n                  'focus:outline-none focus:ring-2 focus:ring-gray-500'\n                )}\n              >\n                Cancel\n              </button>\n              <button\n                onClick={handleSaveComment}\n                className={cn(\n                  'px-3 py-1 text-sm rounded-md',\n                  'bg-blue-500 text-white',\n                  'hover:bg-blue-600',\n                  'focus:outline-none focus:ring-2 focus:ring-blue-500'\n                )}\n              >\n                Save\n              </button>\n            </div>\n          </div>\n        ) : (\n          <div className=\"space-y-2\">\n            {/* Text preview */}\n            <p className=\"text-xs text-gray-500 dark:text-gray-400 line-clamp-2\">\n              &ldquo;{highlight.text.slice(0, 100)}{highlight.text.length > 100 ? '...' : ''}&rdquo;\n            </p>\n\n            {/* Comment display or add button */}\n            {highlight.comment ? (\n              <button\n                onClick={() => setIsEditingComment(true)}\n                className={cn(\n                  'w-full text-left p-2 rounded-md',\n                  'bg-gray-50 dark:bg-gray-700/50',\n                  'text-sm text-gray-700 dark:text-gray-200',\n                  'hover:bg-gray-100 dark:hover:bg-gray-700',\n                  'focus:outline-none focus:ring-2 focus:ring-blue-500'\n                )}\n              >\n                {highlight.comment}\n              </button>\n            ) : (\n              <button\n                onClick={() => setIsEditingComment(true)}\n                className={cn(\n                  'w-full text-left p-2 rounded-md',\n                  'text-sm text-gray-500 dark:text-gray-400',\n                  'hover:bg-gray-50 dark:hover:bg-gray-700/50',\n                  'focus:outline-none focus:ring-2 focus:ring-blue-500'\n                )}\n              >\n                + Add a note...\n              </button>\n            )}\n\n            {/* Copy button */}\n            <button\n              onClick={handleCopyClick}\n              className={cn(\n                'flex items-center gap-2 w-full p-2 rounded-md',\n                'text-sm text-gray-600 dark:text-gray-300',\n                'hover:bg-gray-50 dark:hover:bg-gray-700/50',\n                'focus:outline-none focus:ring-2 focus:ring-blue-500'\n              )}\n            >\n              <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n                />\n              </svg>\n              Copy text\n            </button>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n});\n\nexport default HighlightPopover;\n","export { HighlightPopover, type HighlightPopoverProps } from './HighlightPopover';\n","import { memo, useEffect, useState, useRef, useCallback } from 'react';\nimport type { PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist';\nimport { PDFPage } from '../PDFPage';\nimport { PDFLoadingScreen } from '../PDFLoadingScreen';\nimport { PageSkeleton, DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT } from './PageSkeleton';\nimport { usePDFViewer, usePDFViewerStores, useTextSelection, useTouchGestures, useIsTouchDevice, useViewerStore } from '../../hooks';\nimport { useHighlights } from '../../hooks/useHighlights';\nimport { SelectionToolbar } from '../SelectionToolbar';\nimport { HighlightPopover } from '../HighlightPopover';\nimport { cn } from '../../utils';\nimport type { HighlightColor } from '../../types';\n\nexport interface DocumentContainerProps {\n  className?: string;\n  /** Enable touch gestures for mobile */\n  enableTouchGestures?: boolean;\n}\n\nexport const DocumentContainer = memo(function DocumentContainer({\n  className,\n  enableTouchGestures = true,\n}: DocumentContainerProps) {\n  const {\n    document,\n    currentPage,\n    scale,\n    rotation,\n    theme,\n    isLoading,\n    setScale,\n    nextPage,\n    previousPage,\n  } = usePDFViewer();\n\n  // Get scroll request from store\n  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);\n  const { viewerStore } = usePDFViewerStores();\n  const [currentPageObj, setCurrentPageObj] = useState<PDFPageProxy | null>(null);\n  const [isLoadingPage, setIsLoadingPage] = useState(false);\n  const [pageLoadError, setPageLoadError] = useState<Error | null>(null);\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  const documentRef = useRef<PDFDocumentProxy | null>(null);\n  const baseScaleRef = useRef(scale);\n  const isTouchDevice = useIsTouchDevice();\n\n  // Get progressive loading state\n  const documentLoadingState = useViewerStore((s) => s.documentLoadingState);\n\n  // Text selection handling\n  const { selection, clearSelection, copySelection } = useTextSelection();\n\n  // Touch gesture handlers\n  const handlePinchZoom = useCallback(\n    (pinchScale: number) => {\n      const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));\n      setScale(newScale);\n    },\n    [setScale]\n  );\n\n  const handleSwipeLeft = useCallback(() => {\n    nextPage();\n  }, [nextPage]);\n\n  const handleSwipeRight = useCallback(() => {\n    previousPage();\n  }, [previousPage]);\n\n  const handleDoubleTap = useCallback(\n    (_position: { x: number; y: number }) => {\n      // Toggle between 1x and 2x zoom on double tap\n      const newScale = scale < 1.5 ? 2 : 1;\n      setScale(newScale);\n    },\n    [scale, setScale]\n  );\n\n  // Update base scale when scale changes from other sources\n  useEffect(() => {\n    baseScaleRef.current = scale;\n  }, [scale]);\n\n  // Set up touch gestures\n  const { ref: touchRef } = useTouchGestures<HTMLDivElement>({\n    onPinchZoom: handlePinchZoom,\n    onSwipeLeft: handleSwipeLeft,\n    onSwipeRight: handleSwipeRight,\n    onDoubleTap: handleDoubleTap,\n    enabled: enableTouchGestures && isTouchDevice,\n    swipeThreshold: 50,\n    doubleTapInterval: 300,\n  });\n\n  // Highlight management\n  const {\n    createHighlightFromSelection,\n    updateHighlight,\n    deleteHighlight,\n    selectedHighlight,\n    selectHighlight,\n    activeColor,\n  } = useHighlights();\n\n  // Clear page when document changes\n  useEffect(() => {\n    if (document !== documentRef.current) {\n      documentRef.current = document;\n      setCurrentPageObj(null);\n      setPageLoadError(null);\n    }\n  }, [document]);\n\n  // Load the current page\n  useEffect(() => {\n    if (!document) {\n      setCurrentPageObj(null);\n      setPageLoadError(null);\n      return;\n    }\n\n    let cancelled = false;\n\n    const loadPage = async () => {\n      setIsLoadingPage(true);\n      setPageLoadError(null);\n\n      try {\n        const page = await document.getPage(currentPage);\n\n        if (!cancelled && document === documentRef.current) {\n          setCurrentPageObj(page);\n\n          // Complete scroll request if this page load was requested\n          if (scrollToPageRequest && scrollToPageRequest.page === currentPage) {\n            // Use requestAnimationFrame to ensure page is rendered\n            requestAnimationFrame(() => {\n              viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);\n            });\n          }\n        }\n      } catch (error) {\n        if (!cancelled) {\n          // Silently ignore errors from document switching/destruction\n          const errorMessage = error instanceof Error ? error.message : String(error);\n          const isDocumentDestroyed =\n            errorMessage.includes('destroyed') ||\n            errorMessage.includes('sendWithStream') ||\n            errorMessage.includes('sendWithPromise') ||\n            errorMessage.includes('Cannot read properties of null');\n          if (!isDocumentDestroyed) {\n            console.error('Error loading page:', error);\n            setPageLoadError(error instanceof Error ? error : new Error(errorMessage));\n          }\n        }\n      } finally {\n        if (!cancelled) {\n          setIsLoadingPage(false);\n        }\n      }\n    };\n\n    loadPage();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [document, currentPage, scrollToPageRequest, viewerStore]);\n\n  // Get the page element for coordinate calculations\n  const getPageElement = useCallback((): HTMLElement | null => {\n    return containerRef.current?.querySelector(`[data-page-number=\"${currentPage}\"]`) as HTMLElement | null;\n  }, [currentPage]);\n\n  // Handle creating a highlight from selection\n  const handleCreateHighlight = useCallback(\n    (color: HighlightColor) => {\n      if (!selection) return;\n\n      const pageElement = getPageElement();\n      if (!pageElement) return;\n\n      createHighlightFromSelection(selection, pageElement, scale, color);\n      clearSelection();\n    },\n    [selection, getPageElement, createHighlightFromSelection, scale, clearSelection]\n  );\n\n  // Handle copying selected text\n  const handleCopySelection = useCallback(() => {\n    copySelection();\n  }, [copySelection]);\n\n  // Handle changing highlight color\n  const handleColorChange = useCallback(\n    (id: string, color: HighlightColor) => {\n      updateHighlight(id, { color });\n    },\n    [updateHighlight]\n  );\n\n  // Handle changing highlight comment\n  const handleCommentChange = useCallback(\n    (id: string, comment: string) => {\n      updateHighlight(id, { comment: comment || undefined });\n    },\n    [updateHighlight]\n  );\n\n  // Handle closing the popover\n  const handleClosePopover = useCallback(() => {\n    selectHighlight(null);\n  }, [selectHighlight]);\n\n  // Combine refs for container - must be before any early returns\n  const setContainerRef = useCallback(\n    (element: HTMLDivElement | null) => {\n      containerRef.current = element;\n      touchRef(element);\n    },\n    [touchRef]\n  );\n\n  // Theme-based background\n  const themeStyles = {\n    light: 'bg-gray-100',\n    dark: 'bg-gray-900',\n    sepia: 'bg-amber-50',\n  };\n\n  if (!document) {\n    return (\n      <div\n        className={cn(\n          'document-container',\n          'flex-1',\n          themeStyles[theme],\n          className\n        )}\n      >\n        <PDFLoadingScreen phase={isLoading ? 'fetching' : 'initializing'} />\n      </div>\n    );\n  }\n\n  // Render page content or skeleton\n  const renderPageContent = () => {\n    // Show error state if page failed to load\n    if (pageLoadError && !currentPageObj) {\n      return (\n        <div\n          className=\"relative bg-white shadow-lg flex flex-col items-center justify-center gap-2 text-gray-500\"\n          style={{\n            width: DEFAULT_PAGE_WIDTH * scale,\n            height: DEFAULT_PAGE_HEIGHT * scale,\n          }}\n          data-page-number={currentPage}\n        >\n          <svg className=\"w-8 h-8 text-red-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n            <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n          </svg>\n          <span className=\"text-sm\">Failed to load page {currentPage}</span>\n        </div>\n      );\n    }\n\n    // Show skeleton when page is loading\n    if (isLoadingPage && !currentPageObj) {\n      return (\n        <PageSkeleton\n          pageNumber={currentPage}\n          width={Math.floor(DEFAULT_PAGE_WIDTH * scale)}\n          height={Math.floor(DEFAULT_PAGE_HEIGHT * scale)}\n          isFirstPage={currentPage === 1 && documentLoadingState !== 'ready'}\n        />\n      );\n    }\n\n    // Show the actual page\n    return (\n      <PDFPage\n        pageNumber={currentPage}\n        page={currentPageObj}\n        scale={scale}\n        rotation={rotation}\n      />\n    );\n  };\n\n  return (\n    <div\n      ref={setContainerRef}\n      className={cn(\n        'document-container',\n        'flex-1 overflow-auto',\n        'flex flex-col items-center',\n        'p-4 gap-4',\n        themeStyles[theme],\n        className\n      )}\n    >\n      {/* For single page view, show current page or skeleton */}\n      {renderPageContent()}\n\n      {/* Selection toolbar - appears when text is selected */}\n      <SelectionToolbar\n        selection={selection}\n        onCreateHighlight={handleCreateHighlight}\n        onCopy={handleCopySelection}\n        activeColor={activeColor}\n      />\n\n      {/* Highlight popover - appears when a highlight is clicked */}\n      <HighlightPopover\n        highlight={selectedHighlight}\n        scale={scale}\n        pageElement={getPageElement()}\n        onColorChange={handleColorChange}\n        onCommentChange={handleCommentChange}\n        onDelete={deleteHighlight}\n        onClose={handleClosePopover}\n      />\n    </div>\n  );\n});\n","import { memo, useEffect, useState, useRef, useCallback } from 'react';\nimport type { PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist';\nimport { PDFPage } from '../PDFPage';\nimport { PDFLoadingScreen } from '../PDFLoadingScreen';\nimport { PageSkeleton } from './PageSkeleton';\nimport { usePDFViewer, usePDFViewerStores, useTextSelection, useTouchGestures, useIsTouchDevice, useViewerStore } from '../../hooks';\nimport { useHighlights } from '../../hooks/useHighlights';\nimport { SelectionToolbar } from '../SelectionToolbar';\nimport { HighlightPopover } from '../HighlightPopover';\nimport { cn } from '../../utils';\nimport type { HighlightColor } from '../../types';\n\nexport interface VirtualizedDocumentContainerProps {\n  /** Number of pages to render above/below viewport */\n  overscan?: number;\n  /** Gap between pages in pixels */\n  pageGap?: number;\n  /** Enable touch gestures */\n  enableTouchGestures?: boolean;\n  className?: string;\n}\n\ninterface PageInfo {\n  pageNumber: number;\n  top: number;\n  height: number;\n}\n\n// Default page dimensions for placeholder (US Letter)\nconst DEFAULT_PAGE_WIDTH = 612;\nconst DEFAULT_PAGE_HEIGHT = 792;\n\n/**\n * VirtualizedDocumentContainer efficiently renders only visible pages.\n *\n * Mobile optimizations:\n * - Only pages in/near viewport are rendered (virtualization)\n * - Smooth scrolling with -webkit-overflow-scrolling\n * - Touch gestures for pinch-zoom and swipe navigation\n * - Passive event listeners for scroll performance\n * - Smart page caching to avoid re-fetching\n */\nexport const VirtualizedDocumentContainer = memo(function VirtualizedDocumentContainer({\n  overscan = 2,\n  pageGap = 16,\n  enableTouchGestures = true,\n  className,\n}: VirtualizedDocumentContainerProps) {\n  const {\n    document,\n    numPages,\n    currentPage,\n    scale,\n    rotation,\n    theme,\n    isLoading,\n    setScale,\n    goToPage,\n    nextPage,\n    previousPage,\n  } = usePDFViewer();\n\n  // Get scroll request from store\n  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);\n  const { viewerStore } = usePDFViewerStores();\n\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n  const documentRef = useRef<PDFDocumentProxy | null>(null);\n  const pageCache = useRef<Map<number, PDFPageProxy>>(new Map());\n  const pageDimensionsCache = useRef<Map<number, { width: number; height: number }>>(new Map());\n  const baseScaleRef = useRef(scale);\n  const isTouchDevice = useIsTouchDevice();\n\n  const [visiblePages, setVisiblePages] = useState<number[]>([1]);\n  const [pageObjects, setPageObjects] = useState<Map<number, PDFPageProxy>>(new Map());\n  const [totalHeight, setTotalHeight] = useState(0);\n  const [pageInfos, setPageInfos] = useState<PageInfo[]>([]);\n\n  // Text selection and highlights\n  const { selection, clearSelection, copySelection } = useTextSelection();\n  const {\n    createHighlightFromSelection,\n    updateHighlight,\n    deleteHighlight,\n    selectedHighlight,\n    selectHighlight,\n    activeColor,\n  } = useHighlights();\n\n  // Track default page dimensions, taken from page 1. Most PDFs are uniform,\n  // so using page 1's dimensions for unknown pages gives a layout that's\n  // already correct for the vast majority of pages.\n  const [defaultDims, setDefaultDims] = useState<{ width: number; height: number }>({\n    width: DEFAULT_PAGE_WIDTH,\n    height: DEFAULT_PAGE_HEIGHT,\n  });\n  // Bumped whenever pageDimensionsCache changes so layout recomputes.\n  const [dimsVersion, setDimsVersion] = useState(0);\n\n  // Clear cache when document changes\n  useEffect(() => {\n    if (document !== documentRef.current) {\n      documentRef.current = document;\n      pageCache.current.clear();\n      pageDimensionsCache.current.clear();\n      setPageObjects(new Map());\n    }\n  }, [document]);\n\n  // Cached dimensions are rotation-dependent, so invalidate them when\n  // rotation changes. The default-dims effect will re-seed page 1 and the\n  // visible-page loader will re-record the others as they come back into\n  // view.\n  useEffect(() => {\n    pageDimensionsCache.current.clear();\n    setDimsVersion((v) => v + 1);\n  }, [rotation]);\n\n  // Fetch page 1 dimensions once per document so we can use them as the\n  // placeholder height for every other page. CRITICAL: do NOT iterate every\n  // page here — for a 400 MB PDF that triggers thousands of network\n  // round-trips and forces the entire document into memory just to lay out\n  // the scroll container.\n  useEffect(() => {\n    if (!document || numPages === 0) return;\n    let cancelled = false;\n    (async () => {\n      try {\n        const page = pageCache.current.get(1) ?? (await document.getPage(1));\n        if (cancelled) return;\n        pageCache.current.set(1, page);\n        const viewport = page.getViewport({ scale: 1, rotation });\n        const dims = { width: viewport.width, height: viewport.height };\n        pageDimensionsCache.current.set(1, dims);\n        setDefaultDims(dims);\n        setDimsVersion((v) => v + 1);\n      } catch {\n        // Document may have been destroyed; fall back to defaults.\n      }\n    })();\n    return () => {\n      cancelled = true;\n    };\n  }, [document, numPages, rotation]);\n\n  // Calculate page positions using cached dimensions where known, falling\n  // back to `defaultDims` for unknown pages. Layout recomputes when\n  // `dimsVersion` bumps as more pages are loaded with different dimensions.\n  useEffect(() => {\n    if (!document || numPages === 0) {\n      setPageInfos([]);\n      setTotalHeight(0);\n      return;\n    }\n\n    const infos: PageInfo[] = [];\n    let currentTop = 0;\n\n    for (let i = 1; i <= numPages; i++) {\n      const dimensions = pageDimensionsCache.current.get(i) ?? defaultDims;\n      const scaledHeight = Math.floor(dimensions.height * scale);\n      infos.push({ pageNumber: i, top: currentTop, height: scaledHeight });\n      currentTop += scaledHeight + pageGap;\n    }\n\n    setPageInfos(infos);\n    setTotalHeight(Math.max(0, currentTop - pageGap)); // Remove last gap\n  }, [document, numPages, scale, rotation, pageGap, defaultDims, dimsVersion]);\n\n  // Update visible pages based on scroll\n  const updateVisiblePages = useCallback(() => {\n    if (!scrollContainerRef.current || pageInfos.length === 0) return;\n\n    const container = scrollContainerRef.current;\n    const scrollTop = container.scrollTop;\n    const viewportHeight = container.clientHeight;\n    const scrollBottom = scrollTop + viewportHeight;\n\n    const visible: number[] = [];\n    let firstVisiblePage = 1;\n    let maxVisibleArea = 0;\n\n    for (const info of pageInfos) {\n      const pageTop = info.top;\n      const pageBottom = info.top + info.height;\n\n      // Check if page is in viewport (with overscan)\n      const overscanTop = scrollTop - overscan * viewportHeight;\n      const overscanBottom = scrollBottom + overscan * viewportHeight;\n\n      if (pageBottom > overscanTop && pageTop < overscanBottom) {\n        visible.push(info.pageNumber);\n      }\n\n      // Calculate which page has most visible area (for current page tracking)\n      if (pageBottom > scrollTop && pageTop < scrollBottom) {\n        const visibleTop = Math.max(pageTop, scrollTop);\n        const visibleBottom = Math.min(pageBottom, scrollBottom);\n        const visibleArea = visibleBottom - visibleTop;\n\n        if (visibleArea > maxVisibleArea) {\n          maxVisibleArea = visibleArea;\n          firstVisiblePage = info.pageNumber;\n        }\n      }\n    }\n\n    setVisiblePages(visible);\n\n    // Update current page if it changed\n    if (firstVisiblePage !== currentPage) {\n      goToPage(firstVisiblePage);\n    }\n  }, [pageInfos, overscan, currentPage, goToPage]);\n\n  // Set up scroll listener with passive option for better performance\n  useEffect(() => {\n    const container = scrollContainerRef.current;\n    if (!container) return;\n\n    const handleScroll = () => {\n      requestAnimationFrame(updateVisiblePages);\n    };\n\n    container.addEventListener('scroll', handleScroll, { passive: true });\n    updateVisiblePages(); // Initial update\n\n    return () => container.removeEventListener('scroll', handleScroll);\n  }, [updateVisiblePages]);\n\n  // Load page objects for visible pages\n  useEffect(() => {\n    if (!document) return;\n\n    const loadPages = async () => {\n      const newPageObjects = new Map(pageObjects);\n      let hasChanges = false;\n      let dimsChanged = false;\n\n      for (const pageNum of visiblePages) {\n        if (!newPageObjects.has(pageNum)) {\n          try {\n            let page = pageCache.current.get(pageNum);\n            if (!page) {\n              page = await document.getPage(pageNum);\n              pageCache.current.set(pageNum, page);\n            }\n            newPageObjects.set(pageNum, page);\n            hasChanges = true;\n\n            // Record real dimensions on first sight of this page so the\n            // virtual layout corrects itself for non-uniform PDFs.\n            if (!pageDimensionsCache.current.has(pageNum)) {\n              const vp = page.getViewport({ scale: 1, rotation });\n              pageDimensionsCache.current.set(pageNum, {\n                width: vp.width,\n                height: vp.height,\n              });\n              dimsChanged = true;\n            }\n          } catch (error) {\n            // Silently ignore errors from document switching/destruction\n            const errorMessage = error instanceof Error ? error.message : String(error);\n            const isDocumentDestroyed =\n              errorMessage.includes('destroyed') ||\n              errorMessage.includes('sendWithStream') ||\n              errorMessage.includes('sendWithPromise') ||\n              errorMessage.includes('Cannot read properties of null');\n            if (!isDocumentDestroyed) {\n              console.error(`Error loading page ${pageNum}:`, error);\n            }\n          }\n        }\n      }\n\n      // Unload pages that are far from viewport to save memory\n      const visibleSet = new Set(visiblePages);\n      for (const [pageNum] of newPageObjects) {\n        if (!visibleSet.has(pageNum)) {\n          newPageObjects.delete(pageNum);\n          hasChanges = true;\n        }\n      }\n\n      if (hasChanges) {\n        setPageObjects(newPageObjects);\n      }\n      if (dimsChanged) {\n        setDimsVersion((v) => v + 1);\n      }\n    };\n\n    loadPages();\n  }, [document, visiblePages, pageObjects, rotation]);\n\n  // Handle scroll requests from the store\n  useEffect(() => {\n    if (!scrollToPageRequest || !scrollContainerRef.current || pageInfos.length === 0) return;\n\n    const { page, requestId, behavior } = scrollToPageRequest;\n    const pageInfo = pageInfos.find((p) => p.pageNumber === page);\n\n    if (!pageInfo) {\n      // Page not found, complete the request immediately\n      viewerStore.getState().completeScrollRequest(requestId);\n      return;\n    }\n\n    const container = scrollContainerRef.current;\n    const targetScroll = pageInfo.top - pageGap;\n\n    // Check if already at target\n    const scrollTop = container.scrollTop;\n    const viewportHeight = container.clientHeight;\n    const isVisible = targetScroll >= scrollTop && pageInfo.top + pageInfo.height <= scrollTop + viewportHeight;\n\n    if (isVisible) {\n      // Already visible, complete immediately\n      viewerStore.getState().completeScrollRequest(requestId);\n      return;\n    }\n\n    // Perform scroll\n    container.scrollTo({\n      top: targetScroll,\n      behavior,\n    });\n\n    // Handle scroll completion\n    if (behavior === 'instant') {\n      // For instant scrolls, complete immediately after setting scroll position\n      requestAnimationFrame(() => {\n        viewerStore.getState().completeScrollRequest(requestId);\n      });\n    } else {\n      // For smooth scrolls, detect scroll end\n      let scrollEndTimeout: ReturnType<typeof setTimeout>;\n      const handleScrollEnd = () => {\n        clearTimeout(scrollEndTimeout);\n        scrollEndTimeout = setTimeout(() => {\n          container.removeEventListener('scroll', handleScrollEnd);\n          viewerStore.getState().completeScrollRequest(requestId);\n        }, 100);\n      };\n\n      container.addEventListener('scroll', handleScrollEnd, { passive: true });\n      handleScrollEnd(); // Start the timeout\n    }\n  }, [scrollToPageRequest, pageInfos, pageGap, viewerStore]);\n\n  // Scroll to page when currentPage changes externally (without scroll request)\n  useEffect(() => {\n    // Skip if there's an active scroll request (it will handle scrolling)\n    if (scrollToPageRequest) return;\n    if (!scrollContainerRef.current || pageInfos.length === 0) return;\n\n    const pageInfo = pageInfos.find((p) => p.pageNumber === currentPage);\n    if (pageInfo) {\n      const container = scrollContainerRef.current;\n      const targetScroll = pageInfo.top - pageGap;\n\n      // Only scroll if not already visible\n      const scrollTop = container.scrollTop;\n      const viewportHeight = container.clientHeight;\n\n      if (targetScroll < scrollTop || pageInfo.top + pageInfo.height > scrollTop + viewportHeight) {\n        container.scrollTo({\n          top: targetScroll,\n          behavior: 'smooth',\n        });\n      }\n    }\n  }, [currentPage, pageInfos, pageGap, scrollToPageRequest]);\n\n  // Touch gesture handlers\n  const handlePinchZoom = useCallback(\n    (pinchScale: number) => {\n      const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));\n      setScale(newScale);\n    },\n    [setScale]\n  );\n\n  useEffect(() => {\n    baseScaleRef.current = scale;\n  }, [scale]);\n\n  const { ref: touchRef } = useTouchGestures<HTMLDivElement>({\n    onPinchZoom: handlePinchZoom,\n    onSwipeLeft: nextPage,\n    onSwipeRight: previousPage,\n    enabled: enableTouchGestures && isTouchDevice,\n  });\n\n  // Combine refs\n  const setContainerRef = useCallback(\n    (element: HTMLDivElement | null) => {\n      scrollContainerRef.current = element;\n      touchRef(element);\n    },\n    [touchRef]\n  );\n\n  // Highlight handlers\n  const getPageElement = useCallback(\n    (pageNumber: number): HTMLElement | null => {\n      return containerRef.current?.querySelector(`[data-page-number=\"${pageNumber}\"]`) as HTMLElement | null;\n    },\n    []\n  );\n\n  const handleCreateHighlight = useCallback(\n    (color: HighlightColor) => {\n      if (!selection) return;\n      const pageElement = getPageElement(selection.pageNumber);\n      if (!pageElement) return;\n      createHighlightFromSelection(selection, pageElement, scale, color);\n      clearSelection();\n    },\n    [selection, getPageElement, createHighlightFromSelection, scale, clearSelection]\n  );\n\n  const handleColorChange = useCallback(\n    (id: string, color: HighlightColor) => {\n      updateHighlight(id, { color });\n    },\n    [updateHighlight]\n  );\n\n  const handleCommentChange = useCallback(\n    (id: string, comment: string) => {\n      updateHighlight(id, { comment: comment || undefined });\n    },\n    [updateHighlight]\n  );\n\n  // Theme styles\n  const themeStyles = {\n    light: 'bg-gray-100',\n    dark: 'bg-gray-900',\n    sepia: 'bg-amber-50',\n  };\n\n  if (!document) {\n    return (\n      <div\n        className={cn(\n          'virtualized-document-container',\n          'flex-1',\n          themeStyles[theme],\n          className\n        )}\n      >\n        <PDFLoadingScreen phase={isLoading ? 'fetching' : 'initializing'} />\n      </div>\n    );\n  }\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        'virtualized-document-container',\n        'flex-1 relative',\n        themeStyles[theme],\n        className\n      )}\n    >\n      <div\n        ref={setContainerRef}\n        className=\"absolute inset-0 overflow-auto\"\n        style={{\n          // Smooth scrolling on iOS\n          WebkitOverflowScrolling: 'touch',\n        }}\n      >\n        {/* Scroll container with total height */}\n        <div\n          className=\"relative mx-auto\"\n          style={{\n            height: totalHeight,\n            minHeight: '100%',\n          }}\n        >\n          {/* Render visible pages or skeletons */}\n          {pageInfos\n            .filter((info) => visiblePages.includes(info.pageNumber))\n            .map((info) => {\n              const page = pageObjects.get(info.pageNumber);\n              const dimensions = pageDimensionsCache.current.get(info.pageNumber);\n              const scaledWidth = dimensions\n                ? Math.floor(dimensions.width * scale)\n                : Math.floor(DEFAULT_PAGE_WIDTH * scale);\n              const scaledHeight = dimensions\n                ? Math.floor(dimensions.height * scale)\n                : Math.floor(DEFAULT_PAGE_HEIGHT * scale);\n\n              return (\n                <div\n                  key={info.pageNumber}\n                  className=\"absolute left-1/2 -translate-x-1/2\"\n                  style={{\n                    top: info.top,\n                    width: scaledWidth,\n                  }}\n                >\n                  {page ? (\n                    <PDFPage\n                      pageNumber={info.pageNumber}\n                      page={page}\n                      scale={scale}\n                      rotation={rotation}\n                    />\n                  ) : (\n                    <PageSkeleton\n                      pageNumber={info.pageNumber}\n                      width={scaledWidth}\n                      height={scaledHeight}\n                      isFirstPage={info.pageNumber === 1}\n                    />\n                  )}\n                </div>\n              );\n            })}\n        </div>\n      </div>\n\n      {/* Selection toolbar */}\n      <SelectionToolbar\n        selection={selection}\n        onCreateHighlight={handleCreateHighlight}\n        onCopy={copySelection}\n        activeColor={activeColor}\n      />\n\n      {/* Highlight popover */}\n      <HighlightPopover\n        highlight={selectedHighlight}\n        scale={scale}\n        pageElement={selectedHighlight ? getPageElement(selectedHighlight.pageNumber) : null}\n        onColorChange={handleColorChange}\n        onCommentChange={handleCommentChange}\n        onDelete={deleteHighlight}\n        onClose={() => selectHighlight(null)}\n      />\n    </div>\n  );\n});\n","import { memo } from 'react';\nimport {\n  VirtualizedDocumentContainer,\n  type VirtualizedDocumentContainerProps,\n} from './VirtualizedDocumentContainer';\n\nexport interface ContinuousScrollContainerProps extends VirtualizedDocumentContainerProps {\n  /** Scroll to page smoothly */\n  smoothScroll?: boolean;\n}\n\n/**\n * ContinuousScrollContainer is a convenience wrapper around VirtualizedDocumentContainer\n * that provides continuous scrolling behavior with all pages visible in a single\n * scrollable view.\n *\n * Features:\n * - All pages rendered in a continuous scroll view\n * - Virtualized rendering for performance (only visible pages + buffer are rendered)\n * - Automatic page tracking based on scroll position\n * - Scroll-to-page functionality\n * - Memory management (unloads distant pages)\n */\nexport const ContinuousScrollContainer = memo(function ContinuousScrollContainer(\n  props: ContinuousScrollContainerProps\n) {\n  // ContinuousScrollContainer is essentially the same as VirtualizedDocumentContainer\n  // with default settings optimized for continuous reading\n  return (\n    <VirtualizedDocumentContainer\n      overscan={3} // Render more pages for smoother scrolling\n      pageGap={16}\n      {...props}\n    />\n  );\n});\n\n// Re-export the virtualized container for direct use\nexport { VirtualizedDocumentContainer };\n","import { memo, useEffect, useState, useRef, useCallback } from 'react';\nimport type { PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist';\nimport { PDFPage } from '../PDFPage';\nimport { PDFLoadingScreen } from '../PDFLoadingScreen';\nimport { usePDFViewer, usePDFViewerStores, useTextSelection, useTouchGestures, useIsTouchDevice, useViewerStore } from '../../hooks';\nimport { useHighlights } from '../../hooks/useHighlights';\nimport { SelectionToolbar } from '../SelectionToolbar';\nimport { HighlightPopover } from '../HighlightPopover';\nimport { cn } from '../../utils';\nimport type { HighlightColor } from '../../types';\n\nexport interface DualPageContainerProps {\n  /** Show the first page alone (like a book cover) */\n  showCover?: boolean;\n  /** Book spread mode: odd pages on right side */\n  bookSpread?: boolean;\n  /** Gap between the two pages */\n  pageGap?: number;\n  /** Enable touch gestures */\n  enableTouchGestures?: boolean;\n  className?: string;\n}\n\nexport const DualPageContainer = memo(function DualPageContainer({\n  showCover = true,\n  bookSpread = true,\n  pageGap = 4,\n  enableTouchGestures = true,\n  className,\n}: DualPageContainerProps) {\n  const {\n    document,\n    numPages,\n    currentPage,\n    scale,\n    rotation,\n    theme,\n    isLoading: isDocumentLoading,\n    setScale,\n    goToPage,\n  } = usePDFViewer();\n\n  // Get scroll request from store\n  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);\n  const { viewerStore } = usePDFViewerStores();\n\n  const containerRef = useRef<HTMLDivElement | null>(null);\n  const documentRef = useRef<PDFDocumentProxy | null>(null);\n  const baseScaleRef = useRef(scale);\n  const isTouchDevice = useIsTouchDevice();\n\n  const [leftPage, setLeftPage] = useState<PDFPageProxy | null>(null);\n  const [rightPage, setRightPage] = useState<PDFPageProxy | null>(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  // Text selection and highlights\n  const { selection, clearSelection, copySelection } = useTextSelection();\n  const {\n    createHighlightFromSelection,\n    updateHighlight,\n    deleteHighlight,\n    selectedHighlight,\n    selectHighlight,\n    activeColor,\n  } = useHighlights();\n\n  // Calculate which pages to show in dual view\n  const getSpreadPages = useCallback(\n    (page: number): { left: number | null; right: number | null } => {\n      // Cover page mode: first page is shown alone on right\n      if (showCover && page === 1) {\n        return { left: null, right: 1 };\n      }\n\n      if (bookSpread) {\n        // Book spread: even pages on left, odd pages on right\n        // After cover: page 2 is alone on left, then 3-4, 5-6, etc.\n        if (showCover) {\n          if (page === 2) {\n            return { left: 2, right: null };\n          }\n          // For pages 3 and above, pair odd with the next even\n          const effectivePage = page > 2 ? page : 3;\n          if (effectivePage % 2 === 1) {\n            // Odd page: this is on right, previous even on left\n            return {\n              left: effectivePage - 1 > 1 ? effectivePage - 1 : null,\n              right: effectivePage <= numPages ? effectivePage : null,\n            };\n          } else {\n            // Even page: this is on left, next odd on right\n            return {\n              left: effectivePage,\n              right: effectivePage + 1 <= numPages ? effectivePage + 1 : null,\n            };\n          }\n        } else {\n          // No cover: pages 1-2, 3-4, etc.\n          if (page % 2 === 1) {\n            return {\n              left: page,\n              right: page + 1 <= numPages ? page + 1 : null,\n            };\n          } else {\n            return {\n              left: page - 1,\n              right: page,\n            };\n          }\n        }\n      } else {\n        // Simple dual view: show current page and next\n        return {\n          left: page,\n          right: page + 1 <= numPages ? page + 1 : null,\n        };\n      }\n    },\n    [showCover, bookSpread, numPages]\n  );\n\n  // Clear pages when document changes\n  useEffect(() => {\n    if (document !== documentRef.current) {\n      documentRef.current = document;\n      setLeftPage(null);\n      setRightPage(null);\n    }\n  }, [document]);\n\n  // Load pages when currentPage changes\n  useEffect(() => {\n    if (!document) {\n      setLeftPage(null);\n      setRightPage(null);\n      return;\n    }\n\n    const spread = getSpreadPages(currentPage);\n    let cancelled = false;\n\n    const loadPages = async () => {\n      setIsLoading(true);\n\n      try {\n        const [left, right] = await Promise.all([\n          spread.left ? document.getPage(spread.left) : Promise.resolve(null),\n          spread.right ? document.getPage(spread.right) : Promise.resolve(null),\n        ]);\n\n        if (!cancelled) {\n          setLeftPage(left);\n          setRightPage(right);\n\n          // Complete scroll request if the requested page is now visible\n          if (scrollToPageRequest) {\n            const requestedPage = scrollToPageRequest.page;\n            if (requestedPage === spread.left || requestedPage === spread.right) {\n              requestAnimationFrame(() => {\n                viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);\n              });\n            }\n          }\n        }\n      } catch (error) {\n        if (!cancelled) {\n          // Silently ignore errors from document switching/destruction\n          const errorMessage = error instanceof Error ? error.message : String(error);\n          const isDocumentDestroyed =\n            errorMessage.includes('destroyed') ||\n            errorMessage.includes('sendWithStream') ||\n            errorMessage.includes('sendWithPromise') ||\n            errorMessage.includes('Cannot read properties of null');\n          if (!isDocumentDestroyed) {\n            console.error('Error loading pages:', error);\n          }\n        }\n      } finally {\n        if (!cancelled) {\n          setIsLoading(false);\n        }\n      }\n    };\n\n    loadPages();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [document, currentPage, getSpreadPages, scrollToPageRequest, viewerStore]);\n\n  // Navigate by spread\n  const goToPreviousSpread = useCallback(() => {\n    const spread = getSpreadPages(currentPage);\n    const leftmostPage = spread.left || spread.right || currentPage;\n\n    if (showCover && leftmostPage === 2) {\n      goToPage(1);\n    } else if (showCover && leftmostPage <= 3) {\n      goToPage(2);\n    } else {\n      const newPage = Math.max(1, leftmostPage - 2);\n      goToPage(newPage);\n    }\n  }, [currentPage, showCover, getSpreadPages, goToPage]);\n\n  const goToNextSpread = useCallback(() => {\n    const spread = getSpreadPages(currentPage);\n    const rightmostPage = spread.right || spread.left || currentPage;\n\n    if (rightmostPage < numPages) {\n      goToPage(Math.min(numPages, rightmostPage + 1));\n    }\n  }, [currentPage, numPages, getSpreadPages, goToPage]);\n\n  // Touch gesture handlers\n  const handlePinchZoom = useCallback(\n    (pinchScale: number) => {\n      const newScale = Math.max(0.25, Math.min(4, baseScaleRef.current * pinchScale));\n      setScale(newScale);\n    },\n    [setScale]\n  );\n\n  useEffect(() => {\n    baseScaleRef.current = scale;\n  }, [scale]);\n\n  const { ref: touchRef } = useTouchGestures<HTMLDivElement>({\n    onPinchZoom: handlePinchZoom,\n    onSwipeLeft: goToNextSpread,\n    onSwipeRight: goToPreviousSpread,\n    enabled: enableTouchGestures && isTouchDevice,\n  });\n\n  // Combine refs\n  const setContainerRef = useCallback(\n    (element: HTMLDivElement | null) => {\n      containerRef.current = element;\n      touchRef(element);\n    },\n    [touchRef]\n  );\n\n  // Highlight handlers\n  const getPageElement = useCallback(\n    (pageNumber: number): HTMLElement | null => {\n      return containerRef.current?.querySelector(`[data-page-number=\"${pageNumber}\"]`) as HTMLElement | null;\n    },\n    []\n  );\n\n  const handleCreateHighlight = useCallback(\n    (color: HighlightColor) => {\n      if (!selection) return;\n      const pageElement = getPageElement(selection.pageNumber);\n      if (!pageElement) return;\n      createHighlightFromSelection(selection, pageElement, scale, color);\n      clearSelection();\n    },\n    [selection, getPageElement, createHighlightFromSelection, scale, clearSelection]\n  );\n\n  const handleColorChange = useCallback(\n    (id: string, color: HighlightColor) => {\n      updateHighlight(id, { color });\n    },\n    [updateHighlight]\n  );\n\n  const handleCommentChange = useCallback(\n    (id: string, comment: string) => {\n      updateHighlight(id, { comment: comment || undefined });\n    },\n    [updateHighlight]\n  );\n\n  // Theme styles\n  const themeStyles = {\n    light: 'bg-gray-100',\n    dark: 'bg-gray-900',\n    sepia: 'bg-amber-50',\n  };\n\n  const spread = getSpreadPages(currentPage);\n\n  if (!document) {\n    return (\n      <div\n        className={cn(\n          'dual-page-container',\n          'flex-1',\n          themeStyles[theme],\n          className\n        )}\n      >\n        <PDFLoadingScreen phase={isDocumentLoading ? 'fetching' : 'initializing'} />\n      </div>\n    );\n  }\n\n  return (\n    <div\n      ref={setContainerRef}\n      className={cn(\n        'dual-page-container',\n        'flex-1 overflow-auto',\n        'flex items-center justify-center',\n        'p-4',\n        themeStyles[theme],\n        className\n      )}\n    >\n      {/* Page spread */}\n      <div\n        className=\"flex items-center\"\n        style={{ gap: pageGap }}\n      >\n        {/* Left page */}\n        {spread.left && (\n          <PDFPage\n            pageNumber={spread.left}\n            page={leftPage}\n            scale={scale}\n            rotation={rotation}\n          />\n        )}\n\n        {/* Center divider for book spread effect */}\n        {spread.left && spread.right && (\n          <div\n            className=\"w-px h-full bg-gray-300 dark:bg-gray-600 opacity-50\"\n            style={{ minHeight: '100%' }}\n          />\n        )}\n\n        {/* Right page */}\n        {spread.right && (\n          <PDFPage\n            pageNumber={spread.right}\n            page={rightPage}\n            scale={scale}\n            rotation={rotation}\n          />\n        )}\n\n        {/* Placeholder for single page spread */}\n        {(!spread.left || !spread.right) && (\n          <div\n            className=\"flex items-center justify-center\"\n            style={{\n              width: spread.left ? 0 : 612 * scale,\n              height: spread.right ? 792 * scale : 0,\n            }}\n          />\n        )}\n      </div>\n\n      {/* Selection toolbar */}\n      <SelectionToolbar\n        selection={selection}\n        onCreateHighlight={handleCreateHighlight}\n        onCopy={copySelection}\n        activeColor={activeColor}\n      />\n\n      {/* Highlight popover */}\n      <HighlightPopover\n        highlight={selectedHighlight}\n        scale={scale}\n        pageElement={selectedHighlight ? getPageElement(selectedHighlight.pageNumber) : null}\n        onColorChange={handleColorChange}\n        onCommentChange={handleCommentChange}\n        onDelete={deleteHighlight}\n        onClose={() => selectHighlight(null)}\n      />\n\n      {/* Loading indicator */}\n      {isLoading && (\n        <div className=\"fixed bottom-4 right-4 px-3 py-2 bg-black/75 text-white text-sm rounded-lg\">\n          Loading...\n        </div>\n      )}\n    </div>\n  );\n});\n","import React, { memo, useEffect, useMemo, useState, useRef, useCallback } from 'react';\nimport type { PDFPageProxy } from 'pdfjs-dist';\nimport HTMLFlipBook from 'react-pageflip';\nimport { PDFPage } from '../PDFPage';\nimport { PDFLoadingScreen } from '../PDFLoadingScreen';\nimport { usePDFViewer, usePDFViewerStores, useViewerStore } from '../../hooks';\nimport { cn } from '../../utils';\n\n/**\n * How many pages on each side of the current page to keep loaded in book\n * mode. Anything outside this window renders as an empty placeholder until\n * the user flips towards it. This is what prevents a 400 MB PDF from\n * fetching every page just to display the first spread.\n */\nconst BOOK_MODE_OVERSCAN = 4;\n\nexport interface BookModeContainerProps {\n  className?: string;\n  /** Flip animation duration in ms (default: 800) */\n  flippingTime?: number;\n  /** Draw page shadows during flip (default: true) */\n  drawShadow?: boolean;\n  /** Max shadow opacity 0-1 (default: 0.7) */\n  maxShadowOpacity?: number;\n}\n\n/** A single page inside the flipbook — must use forwardRef for react-pageflip */\nconst BookPage = React.forwardRef<HTMLDivElement, {\n  pageNumber: number;\n  page: PDFPageProxy | null;\n  scale: number;\n  rotation: number;\n  width: number;\n  height: number;\n}>(function BookPage({ pageNumber, page, scale, rotation, width, height }, ref) {\n  return (\n    <div ref={ref} className=\"book-page\" data-page-number={pageNumber}>\n      <div style={{ width, height, overflow: 'hidden' }}>\n        <PDFPage\n          pageNumber={pageNumber}\n          page={page}\n          scale={scale}\n          rotation={rotation}\n          showTextLayer={false}\n          showAnnotationLayer={false}\n          showHighlightLayer={false}\n        />\n      </div>\n    </div>\n  );\n});\n\nexport const BookModeContainer = memo(function BookModeContainer({\n  className,\n  flippingTime = 800,\n  drawShadow = true,\n  maxShadowOpacity = 0.7,\n}: BookModeContainerProps) {\n  const {\n    document,\n    currentPage,\n    numPages,\n    scale,\n    rotation,\n    theme,\n    isLoading,\n    goToPage,\n  } = usePDFViewer();\n\n  const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);\n  const { viewerStore } = usePDFViewerStores();\n\n  // Lazily-populated map of page proxies. Pages outside the overscan window\n  // around `currentPage` are simply absent — they render as empty placeholders\n  // and only get fetched when the user flips towards them.\n  const [pages, setPages] = useState<Map<number, PDFPageProxy>>(new Map());\n  // Raw PDF page dimensions (at scale=1, rotation=0)\n  const [rawPageDims, setRawPageDims] = useState({ width: 612, height: 792 });\n  const [hasFirstPage, setHasFirstPage] = useState(false);\n  const pageRequestsRef = useRef<Set<number>>(new Set());\n\n  // Container measurement for responsive sizing\n  const containerRef = useRef<HTMLDivElement>(null);\n  const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });\n\n  // Flipbook ref for programmatic control\n  const flipBookRef = useRef<any>(null);\n\n  // Track whether we're syncing from flipbook → store (to avoid loops)\n  const isSyncingRef = useRef(false);\n\n  // ─── Measure container ──────────────────────────────────────────────\n\n  useEffect(() => {\n    const el = containerRef.current;\n    if (!el) return;\n\n    const measure = () => {\n      setContainerSize({ width: el.clientWidth, height: el.clientHeight });\n    };\n\n    measure();\n\n    const ro = new ResizeObserver(measure);\n    ro.observe(el);\n    return () => ro.disconnect();\n  }, []);\n\n  // ─── Reset cached pages when the document changes ─────────────────\n\n  useEffect(() => {\n    setPages(new Map());\n    pageRequestsRef.current.clear();\n    setHasFirstPage(false);\n  }, [document]);\n\n  // ─── Lazily load pages near the current spread ────────────────────\n  //\n  // This is the load-everything-at-once fix for book mode. We never iterate\n  // `numPages` here — for a 400 MB PDF that fetches the entire document just\n  // to render the first spread.\n\n  useEffect(() => {\n    if (!document || numPages === 0) return;\n\n    const start = Math.max(1, currentPage - BOOK_MODE_OVERSCAN);\n    const end = Math.min(numPages, currentPage + BOOK_MODE_OVERSCAN);\n    const isFirstLoad = !hasFirstPage;\n\n    let cancelled = false;\n    const wanted: number[] = [];\n    if (isFirstLoad && !pages.has(1) && !pageRequestsRef.current.has(1)) {\n      // Always request page 1 first — we need its viewport for\n      // `rawPageDims`, which determines the flipbook's display size.\n      wanted.push(1);\n      pageRequestsRef.current.add(1);\n    }\n    for (let i = start; i <= end; i++) {\n      if (pages.has(i) || pageRequestsRef.current.has(i)) continue;\n      wanted.push(i);\n      pageRequestsRef.current.add(i);\n    }\n\n    if (wanted.length === 0) return;\n\n    (async () => {\n      const results = await Promise.allSettled(\n        wanted.map((i) => document.getPage(i).then((p) => [i, p] as const))\n      );\n      if (cancelled) return;\n\n      const next = new Map(pages);\n      let firstPageJustLoaded: PDFPageProxy | null = null;\n      for (const r of results) {\n        if (r.status === 'fulfilled') {\n          const [i, page] = r.value;\n          next.set(i, page);\n          if (i === 1) firstPageJustLoaded = page;\n        }\n      }\n      // Drop pages outside the window so memory doesn't grow unbounded as the\n      // user flips through a long book. Page 1 is kept so we can always\n      // recover its viewport for `rawPageDims`.\n      for (const i of next.keys()) {\n        if (i !== 1 && (i < start || i > end)) {\n          next.delete(i);\n        }\n      }\n      setPages(next);\n\n      if (firstPageJustLoaded) {\n        const vp = firstPageJustLoaded.getViewport({ scale: 1, rotation });\n        setRawPageDims({ width: vp.width, height: vp.height });\n        setHasFirstPage(true);\n      }\n\n      for (const i of wanted) {\n        pageRequestsRef.current.delete(i);\n      }\n    })();\n\n    return () => {\n      cancelled = true;\n      for (const i of wanted) {\n        pageRequestsRef.current.delete(i);\n      }\n    };\n  }, [document, numPages, currentPage, rotation, pages, hasFirstPage]);\n\n  // ─── Update raw page dimensions when rotation changes ──────────────\n\n  useEffect(() => {\n    const firstPage = pages.get(1);\n    if (firstPage) {\n      const vp = firstPage.getViewport({ scale: 1, rotation });\n      setRawPageDims({ width: vp.width, height: vp.height });\n    }\n  }, [pages, rotation]);\n\n  // ─── Compute fitted dimensions ─────────────────────────────────────\n\n  const padding = 8; // px padding around the flipbook\n  const fitWidth = Math.max(containerSize.width - padding * 2, 200);\n  const fitHeight = Math.max(containerSize.height - padding * 2, 300);\n\n  const pageAspect = rawPageDims.width / rawPageDims.height;\n  let displayWidth: number;\n  let displayHeight: number;\n\n  // Fit within container maintaining aspect ratio\n  if (fitWidth / fitHeight > pageAspect) {\n    // Container is wider — height is the constraint\n    displayHeight = fitHeight;\n    displayWidth = Math.floor(fitHeight * pageAspect);\n  } else {\n    // Container is taller — width is the constraint\n    displayWidth = fitWidth;\n    displayHeight = Math.floor(fitWidth / pageAspect);\n  }\n\n  // Compute the scale needed to render the PDF page at the display size\n  const renderScale = displayWidth / rawPageDims.width;\n\n  // ─── Sync viewer store → flipbook (e.g. toolbar page input) ──────\n\n  useEffect(() => {\n    const pageFlip = flipBookRef.current?.pageFlip();\n    if (!pageFlip) return;\n\n    const flipBookPage = pageFlip.getCurrentPageIndex();\n    const targetIndex = currentPage - 1; // flipbook is 0-indexed\n\n    if (flipBookPage !== targetIndex) {\n      isSyncingRef.current = true;\n      pageFlip.turnToPage(targetIndex);\n      // Reset sync flag after a short delay\n      setTimeout(() => { isSyncingRef.current = false; }, 100);\n    }\n  }, [currentPage]);\n\n  // Handle scroll-to-page requests\n  useEffect(() => {\n    if (scrollToPageRequest) {\n      requestAnimationFrame(() => {\n        viewerStore.getState().completeScrollRequest(scrollToPageRequest.requestId);\n      });\n    }\n  }, [scrollToPageRequest, viewerStore]);\n\n  // ─── Flipbook → viewer store sync (on page flip) ─────────────────\n\n  const handleFlip = useCallback((e: { data: number }) => {\n    if (isSyncingRef.current) return;\n    const newPage = e.data + 1; // flipbook is 0-indexed, viewer is 1-indexed\n    if (newPage !== currentPage && newPage >= 1 && newPage <= numPages) {\n      goToPage(newPage);\n    }\n  }, [currentPage, numPages, goToPage]);\n\n  // ─── Theme ────────────────────────────────────────────────────────\n\n  const themeStyles = {\n    light: 'bg-gray-100',\n    dark: 'bg-gray-900',\n    sepia: 'bg-amber-50',\n  };\n\n  const themeClass = theme === 'dark' ? 'dark' : theme === 'sepia' ? 'sepia' : '';\n\n  // We're \"ready\" as soon as we have page 1's viewport (and therefore the\n  // flipbook display size). Other pages render placeholders until they\n  // stream in.\n  const ready = !!document && hasFirstPage;\n  const hasContainer = containerSize.width > 0 && containerSize.height > 0;\n\n  // Build the children for HTMLFlipBook lazily — react-pageflip needs one\n  // child per page, but each is just a thin <BookPage> that renders an empty\n  // placeholder until its `page` proxy is in the map.\n  const pageChildren = useMemo(() => {\n    if (numPages === 0) return null;\n    const out = new Array<React.ReactNode>(numPages);\n    for (let i = 0; i < numPages; i++) {\n      const pageNumber = i + 1;\n      out[i] = (\n        <BookPage\n          key={pageNumber}\n          pageNumber={pageNumber}\n          page={pages.get(pageNumber) ?? null}\n          scale={renderScale}\n          rotation={rotation}\n          width={displayWidth}\n          height={displayHeight}\n        />\n      );\n    }\n    return out;\n  }, [numPages, pages, renderScale, rotation, displayWidth, displayHeight]);\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        'book-mode-container',\n        'flex-1 h-full w-full overflow-hidden',\n        'flex items-center justify-center',\n        themeStyles[theme],\n        themeClass,\n        className\n      )}\n      style={{ userSelect: 'none', WebkitUserSelect: 'none' }}\n    >\n      {!ready && (\n        <PDFLoadingScreen\n          phase={!document ? (isLoading ? 'fetching' : 'initializing') : 'rendering'}\n        />\n      )}\n\n      {ready && hasContainer && (\n        <HTMLFlipBook\n          ref={flipBookRef}\n          width={displayWidth}\n          height={displayHeight}\n          size=\"fixed\"\n          minWidth={displayWidth}\n          maxWidth={displayWidth}\n          minHeight={displayHeight}\n          maxHeight={displayHeight}\n          drawShadow={drawShadow}\n          maxShadowOpacity={maxShadowOpacity}\n          flippingTime={flippingTime}\n          usePortrait={true}\n          startPage={currentPage - 1}\n          showCover={false}\n          mobileScrollSupport={true}\n          swipeDistance={30}\n          showPageCorners={true}\n          useMouseEvents={true}\n          clickEventForward={false}\n          onFlip={handleFlip}\n          className=\"book-flipbook\"\n          style={{}}\n          startZIndex={0}\n          autoSize={false}\n          renderOnlyPageLengthChange={false}\n          disableFlipByClick={false}\n        >\n          {pageChildren}\n        </HTMLFlipBook>\n      )}\n\n    </div>\n  );\n});\n","import { memo, useCallback } from 'react';\nimport { useViewerStore, usePDFViewerStores } from '../../hooks';\nimport { cn } from '../../utils';\n\nexport interface FloatingZoomControlsProps {\n  /** Position of the controls */\n  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n  /** Additional class name */\n  className?: string;\n  /** Show fit to width button */\n  showFitToWidth?: boolean;\n  /** Show fit to page button */\n  showFitToPage?: boolean;\n  /** Show zoom percentage */\n  showZoomLevel?: boolean;\n}\n\n/**\n * Floating zoom controls for easy zoom adjustment.\n * Shows +/- buttons and optionally fit-to-width/fit-to-page buttons.\n */\nexport const FloatingZoomControls = memo(function FloatingZoomControls({\n  position = 'bottom-right',\n  className,\n  showFitToWidth = true,\n  showFitToPage = false,\n  showZoomLevel = true,\n}: FloatingZoomControlsProps) {\n  const { viewerStore } = usePDFViewerStores();\n  const scale = useViewerStore((s) => s.scale);\n  const document = useViewerStore((s) => s.document);\n\n  const handleZoomIn = useCallback(() => {\n    const currentScale = viewerStore.getState().scale;\n    const newScale = Math.min(4, currentScale + 0.05);\n    viewerStore.getState().setScale(newScale);\n  }, [viewerStore]);\n\n  const handleZoomOut = useCallback(() => {\n    const currentScale = viewerStore.getState().scale;\n    const newScale = Math.max(0.1, currentScale - 0.05);\n    viewerStore.getState().setScale(newScale);\n  }, [viewerStore]);\n\n  const handleFitToWidth = useCallback(() => {\n    // This will be calculated based on container width\n    // For now, set a reasonable default that typically fits width\n    viewerStore.getState().setScale(1.0);\n  }, [viewerStore]);\n\n  const handleFitToPage = useCallback(() => {\n    viewerStore.getState().setScale(0.75);\n  }, [viewerStore]);\n\n  // Don't render if no document\n  if (!document) return null;\n\n  const positionClasses = {\n    'bottom-right': 'bottom-4 right-4',\n    'bottom-left': 'bottom-4 left-4',\n    'top-right': 'top-4 right-4',\n    'top-left': 'top-4 left-4',\n  };\n\n  const zoomPercentage = Math.round(scale * 100);\n\n  return (\n    <div\n      className={cn(\n        'fixed z-50 flex items-center gap-1',\n        'bg-white dark:bg-gray-800 rounded-lg shadow-lg',\n        'border border-gray-200 dark:border-gray-700',\n        'p-1',\n        positionClasses[position],\n        className\n      )}\n    >\n      {/* Zoom Out */}\n      <button\n        onClick={handleZoomOut}\n        className={cn(\n          'w-8 h-8 flex items-center justify-center rounded',\n          'text-gray-700 dark:text-gray-300',\n          'hover:bg-gray-100 dark:hover:bg-gray-700',\n          'transition-colors',\n          'disabled:opacity-50 disabled:cursor-not-allowed'\n        )}\n        disabled={scale <= 0.25}\n        title=\"Zoom Out\"\n        aria-label=\"Zoom Out\"\n      >\n        <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M20 12H4\" />\n        </svg>\n      </button>\n\n      {/* Zoom Level */}\n      {showZoomLevel && (\n        <span className=\"min-w-[48px] text-center text-sm font-medium text-gray-700 dark:text-gray-300\">\n          {zoomPercentage}%\n        </span>\n      )}\n\n      {/* Zoom In */}\n      <button\n        onClick={handleZoomIn}\n        className={cn(\n          'w-8 h-8 flex items-center justify-center rounded',\n          'text-gray-700 dark:text-gray-300',\n          'hover:bg-gray-100 dark:hover:bg-gray-700',\n          'transition-colors',\n          'disabled:opacity-50 disabled:cursor-not-allowed'\n        )}\n        disabled={scale >= 4}\n        title=\"Zoom In\"\n        aria-label=\"Zoom In\"\n      >\n        <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n          <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n        </svg>\n      </button>\n\n      {/* Divider */}\n      {(showFitToWidth || showFitToPage) && (\n        <div className=\"w-px h-6 bg-gray-200 dark:bg-gray-700 mx-1\" />\n      )}\n\n      {/* Fit to Width */}\n      {showFitToWidth && (\n        <button\n          onClick={handleFitToWidth}\n          className={cn(\n            'w-8 h-8 flex items-center justify-center rounded',\n            'text-gray-700 dark:text-gray-300',\n            'hover:bg-gray-100 dark:hover:bg-gray-700',\n            'transition-colors'\n          )}\n          title=\"Fit to Width\"\n          aria-label=\"Fit to Width\"\n        >\n          <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n            <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4\" />\n          </svg>\n        </button>\n      )}\n\n      {/* Fit to Page */}\n      {showFitToPage && (\n        <button\n          onClick={handleFitToPage}\n          className={cn(\n            'w-8 h-8 flex items-center justify-center rounded',\n            'text-gray-700 dark:text-gray-300',\n            'hover:bg-gray-100 dark:hover:bg-gray-700',\n            'transition-colors'\n          )}\n          title=\"Fit to Page\"\n          aria-label=\"Fit to Page\"\n        >\n          <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n            <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n          </svg>\n        </button>\n      )}\n    </div>\n  );\n});\n","export { FloatingZoomControls } from './FloatingZoomControls';\nexport type { FloatingZoomControlsProps } from './FloatingZoomControls';\n","import {\n  useEffect,\n  useCallback,\n  memo,\n  useRef,\n  useState,\n  forwardRef,\n} from 'react';\nimport { PDFViewerProvider, usePDFViewerStores, useViewerStore } from '../../hooks';\nimport { loadDocumentWithCallbacks, clearDocumentCache } from '../../utils';\nimport { Toolbar } from '../Toolbar';\nimport { Sidebar } from '../Sidebar';\nimport { AnnotationToolbar } from '../AnnotationToolbar';\nimport { DocumentContainer } from './DocumentContainer';\nimport { ContinuousScrollContainer } from './ContinuousScrollContainer';\nimport { DualPageContainer } from './DualPageContainer';\nimport { BookModeContainer } from './BookModeContainer';\nimport { FloatingZoomControls } from '../FloatingZoomControls';\nimport { PDFLoadingScreen } from '../PDFLoadingScreen';\nimport { cn } from '../../utils';\nimport type {\n  PDFViewerProps,\n  PDFViewerHandle,\n  HighlightTextOptions,\n  DrawRectOptions,\n  DrawCircleOptions,\n  AddNoteOptions,\n  SearchOptions,\n  HighlightRect,\n  GoToPageOptions,\n  SearchAndHighlightOptions,\n  SearchAndHighlightResult,\n  ViewerState,\n} from '../../types';\n\ninterface PDFViewerInnerProps extends PDFViewerProps {\n  onReady?: (handle: PDFViewerHandle) => void;\n}\n\n/**\n * Generate a stable identifier for the src prop.\n */\nfunction getSrcIdentifier(src: string | ArrayBuffer | Uint8Array): string {\n  if (typeof src === 'string') {\n    return src;\n  }\n\n  const data = src instanceof ArrayBuffer ? new Uint8Array(src) : src;\n  const len = data.byteLength;\n\n  if (len === 0) return 'empty';\n\n  const first = Array.from(data.slice(0, 4))\n    .map((b) => b.toString(16).padStart(2, '0'))\n    .join('');\n  const last = Array.from(data.slice(-4))\n    .map((b) => b.toString(16).padStart(2, '0'))\n    .join('');\n\n  return `binary:${len}:${first}:${last}`;\n}\n\n\nconst PDFViewerInner = memo(function PDFViewerInner({\n  src,\n  initialPage = 1,\n  page: controlledPage,\n  initialScale = 'auto',\n  showToolbar = true,\n  showSidebar = true,\n  showAnnotationToolbar = false,\n  showFloatingZoom = true,\n  viewMode = 'single',\n  onDocumentLoad,\n  onPageChange,\n  onScaleChange,\n  onZoomChange,\n  onError,\n  onPageRenderStart,\n  onPageRenderComplete,\n  onHighlightAdded,\n  onHighlightRemoved,\n  onAnnotationAdded,\n  workerSrc,\n  className,\n  loadingComponent,\n  errorComponent,\n  onReady,\n}: PDFViewerInnerProps) {\n  const { viewerStore, annotationStore, searchStore } = usePDFViewerStores();\n\n  // Track mount state\n  const mountedRef = useRef(true);\n  const [, setLoadState] = useState<'idle' | 'loading' | 'loaded' | 'error'>('idle');\n\n  // Store callbacks in refs\n  const onDocumentLoadRef = useRef(onDocumentLoad);\n  const onErrorRef = useRef(onError);\n  const onPageChangeRef = useRef(onPageChange);\n  const onScaleChangeRef = useRef(onScaleChange);\n  const onZoomChangeRef = useRef(onZoomChange);\n  const onPageRenderStartRef = useRef(onPageRenderStart);\n  const onPageRenderCompleteRef = useRef(onPageRenderComplete);\n  const onHighlightAddedRef = useRef(onHighlightAdded);\n  const onHighlightRemovedRef = useRef(onHighlightRemoved);\n  const onAnnotationAddedRef = useRef(onAnnotationAdded);\n  const onReadyRef = useRef(onReady);\n\n  onDocumentLoadRef.current = onDocumentLoad;\n  onErrorRef.current = onError;\n  onPageChangeRef.current = onPageChange;\n  onScaleChangeRef.current = onScaleChange;\n  onZoomChangeRef.current = onZoomChange;\n  onPageRenderStartRef.current = onPageRenderStart;\n  onPageRenderCompleteRef.current = onPageRenderComplete;\n  onHighlightAddedRef.current = onHighlightAdded;\n  onHighlightRemovedRef.current = onHighlightRemoved;\n  onAnnotationAddedRef.current = onAnnotationAdded;\n  onReadyRef.current = onReady;\n\n  // Controlled mode tracking\n  const isControlled = controlledPage !== undefined;\n  const prevControlledPageRef = useRef(controlledPage);\n\n  const srcIdRef = useRef<string | null>(null);\n\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const scale = useViewerStore((s) => s.scale);\n  const theme = useViewerStore((s) => s.theme);\n  const isLoading = useViewerStore((s) => s.isLoading);\n  const loadingProgress = useViewerStore((s) => s.loadingProgress);\n  const error = useViewerStore((s) => s.error);\n  const sidebarOpen = useViewerStore((s) => s.sidebarOpen);\n  const streamingProgress = useViewerStore((s) => s.streamingProgress);\n\n  const srcId = getSrcIdentifier(src);\n\n  // ============================================================================\n  // Imperative Handle Implementation\n  // ============================================================================\n\n  const handleRef = useRef<PDFViewerHandle | null>(null);\n\n  // Create the imperative handle\n  useEffect(() => {\n    const handle: PDFViewerHandle = {\n      // ==================== Text Highlighting ====================\n      highlightText: async (text: string, options?: HighlightTextOptions) => {\n        const doc = viewerStore.getState().document;\n        if (!doc) return [];\n\n        const color = options?.color ?? 'yellow';\n        const targetPage = options?.page;\n        const caseSensitive = options?.caseSensitive ?? false;\n        const scrollTo = options?.scrollTo ?? true;\n\n        const highlightIds: string[] = [];\n        const searchText = caseSensitive ? text : text.toLowerCase();\n\n        // Search through pages\n        const pagesToSearch = targetPage\n          ? [targetPage]\n          : Array.from({ length: doc.numPages }, (_, i) => i + 1);\n\n        for (const pageNum of pagesToSearch) {\n          try {\n            const page = await doc.getPage(pageNum);\n            const textContent = await page.getTextContent();\n            const viewport = page.getViewport({ scale: 1 });\n\n            // Build text items array with proper tracking\n            let fullText = '';\n            const textItems: Array<{ text: string; transform: number[]; width: number; height: number }> = [];\n\n            for (const item of textContent.items) {\n              if ('str' in item && item.str) {\n                textItems.push({\n                  text: item.str,\n                  transform: item.transform as number[],\n                  width: (item.width as number) ?? 0,\n                  height: (item.height as number) ?? 12,\n                });\n                fullText += item.str;\n              }\n            }\n\n            // Find matches\n            const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();\n            let startIndex = 0;\n\n            while (true) {\n              const matchIndex = textToSearch.indexOf(searchText, startIndex);\n              if (matchIndex === -1) break;\n\n              // Calculate rects by finding which text items contain the match\n              const matchRects = calculateMatchRects(textItems, matchIndex, text.length, viewport);\n\n              if (matchRects.length > 0) {\n                // Create highlight\n                const highlight = annotationStore.getState().addHighlight({\n                  pageNumber: pageNum,\n                  rects: matchRects,\n                  color,\n                  text: fullText.substring(matchIndex, matchIndex + text.length),\n                });\n\n                highlightIds.push(highlight.id);\n              }\n              startIndex = matchIndex + 1;\n            }\n          } catch {\n            // Skip pages that fail\n          }\n        }\n\n        // Scroll to first match\n        if (scrollTo && highlightIds.length > 0) {\n          const firstHighlight = annotationStore.getState().highlights.find(h => h.id === highlightIds[0]);\n          if (firstHighlight) {\n            viewerStore.getState().goToPage(firstHighlight.pageNumber);\n          }\n        }\n\n        return highlightIds;\n      },\n\n      removeHighlight: (id: string) => {\n        annotationStore.getState().removeHighlight(id);\n      },\n\n      clearHighlights: () => {\n        const highlights = annotationStore.getState().highlights;\n        for (const h of highlights) {\n          annotationStore.getState().removeHighlight(h.id);\n        }\n      },\n\n      // ==================== Annotations ====================\n      drawRect: (options: DrawRectOptions) => {\n        const annotation = annotationStore.getState().addAnnotation({\n          type: 'shape',\n          shapeType: 'rect',\n          pageNumber: options.page,\n          x: options.x,\n          y: options.y,\n          width: options.width,\n          height: options.height,\n          color: options.color ?? 'blue',\n          strokeWidth: options.strokeWidth ?? 2,\n        } as Omit<import('../../types').ShapeAnnotation, 'id' | 'createdAt' | 'updatedAt'>);\n        return annotation.id;\n      },\n\n      drawCircle: (options: DrawCircleOptions) => {\n        const annotation = annotationStore.getState().addAnnotation({\n          type: 'shape',\n          shapeType: 'circle',\n          pageNumber: options.page,\n          x: options.x,\n          y: options.y,\n          width: options.radius * 2,\n          height: options.radius * 2,\n          color: options.color ?? 'blue',\n          strokeWidth: options.strokeWidth ?? 2,\n        } as Omit<import('../../types').ShapeAnnotation, 'id' | 'createdAt' | 'updatedAt'>);\n        return annotation.id;\n      },\n\n      addNote: (options: AddNoteOptions) => {\n        const annotation = annotationStore.getState().addAnnotation({\n          type: 'note',\n          pageNumber: options.page,\n          x: options.x,\n          y: options.y,\n          content: options.content,\n          color: options.color ?? 'yellow',\n        } as Omit<import('../../types').NoteAnnotation, 'id' | 'createdAt' | 'updatedAt'>);\n        return annotation.id;\n      },\n\n      removeAnnotation: (id: string) => {\n        annotationStore.getState().removeAnnotation(id);\n      },\n\n      clearAnnotations: () => {\n        const annotations = annotationStore.getState().annotations;\n        for (const a of annotations) {\n          annotationStore.getState().removeAnnotation(a.id);\n        }\n      },\n\n      // ==================== Navigation ====================\n      goToPage: async (page: number, options?: GoToPageOptions) => {\n        const behavior = options?.behavior ?? 'smooth';\n        await viewerStore.getState().requestScrollToPage(page, behavior);\n      },\n\n      nextPage: () => {\n        viewerStore.getState().nextPage();\n      },\n\n      previousPage: () => {\n        viewerStore.getState().previousPage();\n      },\n\n      getCurrentPage: () => {\n        return viewerStore.getState().currentPage;\n      },\n\n      getNumPages: () => {\n        return viewerStore.getState().numPages;\n      },\n\n      // ==================== Zoom ====================\n      setZoom: (scale: number) => {\n        viewerStore.getState().setScale(scale);\n      },\n\n      getZoom: () => {\n        return viewerStore.getState().scale;\n      },\n\n      zoomIn: () => {\n        viewerStore.getState().zoomIn();\n      },\n\n      zoomOut: () => {\n        viewerStore.getState().zoomOut();\n      },\n\n      // ==================== Search ====================\n      search: async (query: string, options?: SearchOptions) => {\n        const doc = viewerStore.getState().document;\n        if (!doc) return [];\n\n        searchStore.getState().setQuery(query);\n        if (options?.caseSensitive !== undefined) {\n          searchStore.getState().setCaseSensitive(options.caseSensitive);\n        }\n        if (options?.wholeWord !== undefined) {\n          searchStore.getState().setWholeWord(options.wholeWord);\n        }\n\n        await searchStore.getState().search(doc);\n        return searchStore.getState().results;\n      },\n\n      nextSearchResult: () => {\n        searchStore.getState().nextResult();\n        const results = searchStore.getState().results;\n        const index = searchStore.getState().currentResultIndex;\n        if (results[index]) {\n          viewerStore.getState().goToPage(results[index].pageNumber);\n        }\n      },\n\n      previousSearchResult: () => {\n        searchStore.getState().previousResult();\n        const results = searchStore.getState().results;\n        const index = searchStore.getState().currentResultIndex;\n        if (results[index]) {\n          viewerStore.getState().goToPage(results[index].pageNumber);\n        }\n      },\n\n      clearSearch: () => {\n        searchStore.getState().clearSearch();\n      },\n\n      // ==================== Combined Search & Highlight ====================\n      searchAndHighlight: async (query: string, options?: SearchAndHighlightOptions): Promise<SearchAndHighlightResult> => {\n        const doc = viewerStore.getState().document;\n        if (!doc) {\n          return { matchCount: 0, highlightIds: [], matches: [] };\n        }\n\n        const color = options?.color ?? 'yellow';\n        const caseSensitive = options?.caseSensitive ?? false;\n        const wholeWord = options?.wholeWord ?? false;\n        const scrollToFirst = options?.scrollToFirst ?? true;\n        const clearPrevious = options?.clearPrevious ?? true;\n\n        // Clear previous search highlights if requested\n        if (clearPrevious) {\n          const existingHighlights = annotationStore.getState().highlights;\n          for (const h of existingHighlights) {\n            if (h.source === 'search') {\n              annotationStore.getState().removeHighlight(h.id);\n            }\n          }\n        }\n\n        // Determine which pages to search\n        let pagesToSearch: number[];\n        if (options?.pageRange) {\n          if (Array.isArray(options.pageRange)) {\n            pagesToSearch = options.pageRange;\n          } else {\n            const { start, end } = options.pageRange;\n            pagesToSearch = Array.from({ length: end - start + 1 }, (_, i) => start + i);\n          }\n        } else {\n          pagesToSearch = Array.from({ length: doc.numPages }, (_, i) => i + 1);\n        }\n\n        const result: SearchAndHighlightResult = {\n          matchCount: 0,\n          highlightIds: [],\n          matches: [],\n        };\n\n        const searchText = caseSensitive ? query : query.toLowerCase();\n\n        for (const pageNum of pagesToSearch) {\n          if (pageNum < 1 || pageNum > doc.numPages) continue;\n\n          try {\n            const page = await doc.getPage(pageNum);\n            const textContent = await page.getTextContent();\n            const viewport = page.getViewport({ scale: 1 });\n\n            // Build text items array with proper tracking\n            let fullText = '';\n            const textItems: Array<{ text: string; transform: number[]; width: number; height: number }> = [];\n\n            for (const item of textContent.items) {\n              if ('str' in item && item.str) {\n                textItems.push({\n                  text: item.str,\n                  transform: item.transform as number[],\n                  width: (item.width as number) ?? 0,\n                  height: (item.height as number) ?? 12,\n                });\n                fullText += item.str;\n              }\n            }\n\n            // Find matches\n            const textToSearch = caseSensitive ? fullText : fullText.toLowerCase();\n            let startIndex = 0;\n\n            while (true) {\n              const matchIndex = textToSearch.indexOf(searchText, startIndex);\n              if (matchIndex === -1) break;\n\n              // Check whole word if required\n              if (wholeWord) {\n                const beforeChar = matchIndex > 0 ? textToSearch[matchIndex - 1] : ' ';\n                const afterChar = matchIndex + query.length < textToSearch.length\n                  ? textToSearch[matchIndex + query.length]\n                  : ' ';\n\n                if (/\\w/.test(beforeChar) || /\\w/.test(afterChar)) {\n                  startIndex = matchIndex + 1;\n                  continue;\n                }\n              }\n\n              // Calculate rects by finding which text items contain the match\n              const matchRects = calculateMatchRects(textItems, matchIndex, query.length, viewport);\n\n              if (matchRects.length > 0) {\n                // Create highlight with source marker\n                const highlight = annotationStore.getState().addHighlight({\n                  pageNumber: pageNum,\n                  rects: matchRects,\n                  color,\n                  text: fullText.substring(matchIndex, matchIndex + query.length),\n                  source: 'search',\n                });\n\n                result.matchCount++;\n                result.highlightIds.push(highlight.id);\n                result.matches.push({\n                  pageNumber: pageNum,\n                  text: fullText.substring(matchIndex, matchIndex + query.length),\n                  highlightId: highlight.id,\n                  rects: matchRects,\n                });\n              }\n\n              startIndex = matchIndex + 1;\n            }\n          } catch {\n            // Skip pages that fail to load\n          }\n        }\n\n        // Scroll to first match if requested\n        if (scrollToFirst && result.matches.length > 0) {\n          const firstMatch = result.matches[0];\n          await viewerStore.getState().requestScrollToPage(firstMatch.pageNumber, 'smooth');\n        }\n\n        return result;\n      },\n\n      // ==================== Agent Tools ====================\n      agentTools: {\n        navigateToPage: async (page: number) => {\n          try {\n            const { currentPage, numPages } = viewerStore.getState();\n            if (numPages === 0) {\n              return {\n                success: false,\n                error: { code: 'NO_DOCUMENT', message: 'No document is loaded' },\n              };\n            }\n            if (page < 1 || page > numPages) {\n              return {\n                success: false,\n                error: { code: 'INVALID_PAGE', message: `Page ${page} is out of range (1-${numPages})` },\n              };\n            }\n\n            const previousPage = currentPage;\n            await viewerStore.getState().requestScrollToPage(page, 'smooth');\n\n            return {\n              success: true,\n              data: { previousPage, currentPage: page },\n            };\n          } catch (err) {\n            return {\n              success: false,\n              error: { code: 'NAVIGATION_FAILED', message: err instanceof Error ? err.message : 'Unknown error' },\n            };\n          }\n        },\n\n        highlightText: async (text: string, options?: HighlightTextOptions) => {\n          try {\n            const highlightIds = await handle.highlightText(text, options);\n            return {\n              success: true,\n              data: { matchCount: highlightIds.length, highlightIds },\n            };\n          } catch (err) {\n            return {\n              success: false,\n              error: { code: 'HIGHLIGHT_FAILED', message: err instanceof Error ? err.message : 'Unknown error' },\n            };\n          }\n        },\n\n        getPageContent: async (page: number) => {\n          try {\n            const doc = viewerStore.getState().document;\n            if (!doc) {\n              return {\n                success: false,\n                error: { code: 'NO_DOCUMENT', message: 'No document is loaded' },\n              };\n            }\n            if (page < 1 || page > doc.numPages) {\n              return {\n                success: false,\n                error: { code: 'INVALID_PAGE', message: `Page ${page} is out of range (1-${doc.numPages})` },\n              };\n            }\n\n            const pageObj = await doc.getPage(page);\n            const textContent = await pageObj.getTextContent();\n            const text = textContent.items\n              .filter((item): item is (typeof textContent.items[number] & { str: string }) => 'str' in item)\n              .map(item => item.str)\n              .join('');\n\n            return {\n              success: true,\n              data: { text },\n            };\n          } catch (err) {\n            return {\n              success: false,\n              error: { code: 'CONTENT_FETCH_FAILED', message: err instanceof Error ? err.message : 'Unknown error' },\n            };\n          }\n        },\n\n        clearAllVisuals: async () => {\n          try {\n            const highlights = annotationStore.getState().highlights;\n            for (const h of highlights) {\n              annotationStore.getState().removeHighlight(h.id);\n            }\n\n            const annotations = annotationStore.getState().annotations;\n            for (const a of annotations) {\n              annotationStore.getState().removeAnnotation(a.id);\n            }\n\n            return { success: true };\n          } catch (err) {\n            return {\n              success: false,\n              error: { code: 'CLEAR_FAILED', message: err instanceof Error ? err.message : 'Unknown error' },\n            };\n          }\n        },\n      },\n\n      // ==================== Coordinate Helpers ====================\n      coordinates: {\n        getPageDimensions: (page: number) => {\n          const doc = viewerStore.getState().document;\n          if (!doc || page < 1 || page > doc.numPages) {\n            return null;\n          }\n\n          // Note: This is synchronous, so we return cached dimensions if available\n          // For a full implementation, you might want to cache page dimensions\n          // This returns null if dimensions aren't immediately available\n          try {\n            // PDF.js viewport gives us the actual dimensions\n            // We can't access this synchronously, so we return a placeholder\n            // In practice, components should use async methods or subscribe to page loads\n            return {\n              width: 612, // Default US Letter width\n              height: 792, // Default US Letter height\n              rotation: viewerStore.getState().rotation,\n            };\n          } catch {\n            return null;\n          }\n        },\n\n        percentToPixels: (xPercent: number, yPercent: number, page: number) => {\n          const dimensions = handle.coordinates.getPageDimensions(page);\n          if (!dimensions) return null;\n\n          const scale = viewerStore.getState().scale;\n          return {\n            x: (xPercent / 100) * dimensions.width * scale,\n            y: (yPercent / 100) * dimensions.height * scale,\n          };\n        },\n\n        pixelsToPercent: (x: number, y: number, page: number) => {\n          const dimensions = handle.coordinates.getPageDimensions(page);\n          if (!dimensions) return null;\n\n          const scale = viewerStore.getState().scale;\n          return {\n            x: (x / (dimensions.width * scale)) * 100,\n            y: (y / (dimensions.height * scale)) * 100,\n          };\n        },\n      },\n\n      // ==================== Document ====================\n      getDocument: () => {\n        return viewerStore.getState().document;\n      },\n\n      isLoaded: () => {\n        return viewerStore.getState().document !== null;\n      },\n    };\n\n    handleRef.current = handle;\n    onReadyRef.current?.(handle);\n  }, [viewerStore, annotationStore, searchStore]);\n\n  // Retry handler\n  const handleRetry = useCallback(() => {\n    srcIdRef.current = null;\n    if (abortControllerRef.current) {\n      abortControllerRef.current.abort();\n      abortControllerRef.current = null;\n    }\n    viewerStore.getState().setError(null);\n    setLoadState('idle');\n  }, [viewerStore]);\n\n  // AbortController for cancelling document loading\n  const abortControllerRef = useRef<AbortController | null>(null);\n\n  // Track the current src for cleanup\n  const currentSrcRef = useRef<string | ArrayBuffer | Uint8Array | null>(null);\n\n  // Gate teardown behind a deferred timer so React 18 StrictMode's synthetic\n  // unmount+remount pair does not trigger a cache clear + document destroy.\n  const teardownTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n  // Mount tracking\n  useEffect(() => {\n    mountedRef.current = true;\n    if (teardownTimerRef.current !== null) {\n      clearTimeout(teardownTimerRef.current);\n      teardownTimerRef.current = null;\n    }\n    return () => {\n      teardownTimerRef.current = setTimeout(() => {\n        teardownTimerRef.current = null;\n        mountedRef.current = false;\n        if (abortControllerRef.current) {\n          abortControllerRef.current.abort();\n          abortControllerRef.current = null;\n        }\n\n        if (currentSrcRef.current && typeof currentSrcRef.current === 'string') {\n          clearDocumentCache(currentSrcRef.current);\n        }\n\n        srcIdRef.current = null;\n        currentSrcRef.current = null;\n\n        const currentDoc = viewerStore.getState().document;\n        if (currentDoc) {\n          try {\n            currentDoc.destroy();\n          } catch {\n            // Ignore errors if already destroyed\n          }\n        }\n        viewerStore.getState().setDocument(null);\n        viewerStore.getState().setLoading(false);\n        viewerStore.getState().setError(null);\n      }, 0);\n    };\n  }, [viewerStore]);\n\n  // Store cancel function for streaming loader\n  const cancelLoaderRef = useRef<(() => void) | null>(null);\n\n  // Load document with progressive/streaming approach\n  useEffect(() => {\n    // Short-circuit if a load for this srcId is already complete or still\n    // in-flight. The in-flight check matters under React 18 StrictMode:\n    // the synthetic unmount+remount pair preserves abortControllerRef\n    // (because the mount effect's teardown is deferred and cancelled by\n    // the remount), so the first mount's load is still alive when the\n    // second mount's effect body runs.\n    const existingAC = abortControllerRef.current;\n    const loadInFlight = existingAC !== null && !existingAC.signal.aborted;\n    if (\n      srcIdRef.current === srcId &&\n      (viewerStore.getState().document || loadInFlight)\n    ) {\n      return;\n    }\n\n    const loadId = srcId;\n    srcIdRef.current = srcId;\n    currentSrcRef.current = src;\n\n    // Cancel any previous loading task (e.g., src changed mid-load)\n    if (abortControllerRef.current) {\n      abortControllerRef.current.abort();\n    }\n    if (cancelLoaderRef.current) {\n      cancelLoaderRef.current();\n      cancelLoaderRef.current = null;\n    }\n\n    // Create new AbortController for this load\n    const abortController = new AbortController();\n    abortControllerRef.current = abortController;\n\n    const currentDoc = viewerStore.getState().document;\n    if (currentDoc) {\n      try {\n        currentDoc.destroy();\n      } catch {\n        // Ignore if already destroyed\n      }\n    }\n\n    // Set loading state with progressive loading states\n    viewerStore.setState({\n      document: null,\n      isLoading: true,\n      loadingProgress: { phase: 'initializing' },\n      error: null,\n      documentLoadingState: 'initializing',\n      firstPageReady: false,\n      streamingProgress: null,\n    });\n    setLoadState('loading');\n\n    // Throttle progress updates to reduce re-renders\n    let lastProgressUpdate = 0;\n    let lastPercent = -1;\n    const PROGRESS_THROTTLE_MS = 100;\n    const PROGRESS_MIN_CHANGE = 5;\n\n    // Use streaming loader with callbacks\n    const { promise, cancel } = loadDocumentWithCallbacks({\n      src,\n      workerSrc,\n      signal: abortController.signal,\n      onProgress: ({ loaded, total }) => {\n        if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {\n          return;\n        }\n\n        const now = Date.now();\n        const percent = total > 0 ? Math.round((loaded / total) * 100) : 0;\n\n        // Only update if enough time passed AND percent changed significantly\n        const timePassed = now - lastProgressUpdate >= PROGRESS_THROTTLE_MS;\n        const percentChanged = Math.abs(percent - lastPercent) >= PROGRESS_MIN_CHANGE;\n        const isComplete = percent >= 100;\n\n        if ((timePassed && percentChanged) || isComplete) {\n          lastProgressUpdate = now;\n          lastPercent = percent;\n          viewerStore.setState({\n            loadingProgress: {\n              phase: 'fetching',\n              percent,\n              bytesLoaded: loaded,\n              totalBytes: total,\n            },\n            streamingProgress: { loaded, total },\n            documentLoadingState: 'loading',\n          });\n        }\n      },\n      onDocumentReady: (document, numPages) => {\n        if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {\n          return;\n        }\n\n        // Document structure is ready - update state but don't clear loading yet\n        viewerStore.setState({\n          document,\n          numPages,\n          loadingProgress: { phase: 'parsing' },\n          documentLoadingState: 'loading',\n        });\n      },\n      onFirstPageReady: () => {\n        if (!mountedRef.current || srcIdRef.current !== loadId || abortController.signal.aborted) {\n          return;\n        }\n\n        // First page is ready - hide loading screen and show content\n        viewerStore.setState({\n          isLoading: false,\n          firstPageReady: true,\n          loadingProgress: null,\n          documentLoadingState: 'ready',\n        });\n        setLoadState('loaded');\n      },\n    });\n\n    cancelLoaderRef.current = cancel;\n\n    // Handle final completion\n    promise\n      .then(({ document, numPages }) => {\n        if (mountedRef.current && srcIdRef.current === loadId && !abortController.signal.aborted) {\n          // Ensure document is set (may already be set by onDocumentReady)\n          if (!viewerStore.getState().document) {\n            viewerStore.getState().setDocument(document);\n          }\n\n          // Handle initial page and scale if needed (batched)\n          if (initialPage !== 1 || typeof initialScale === 'number' || initialScale === 'page-fit') {\n            const updates: Partial<ViewerState> = {};\n            if (initialPage !== 1) {\n              updates.currentPage = Math.max(1, Math.min(initialPage, numPages));\n            }\n            if (typeof initialScale === 'number') {\n              updates.scale = initialScale;\n            } else if (initialScale === 'page-fit') {\n              updates.scale = 0.75;\n            }\n            if (Object.keys(updates).length > 0) {\n              viewerStore.setState(updates);\n            }\n          }\n\n          onDocumentLoadRef.current?.({ document, numPages });\n        }\n      })\n      .catch((err) => {\n        // Ignore abort errors - component is unmounting or loading was cancelled\n        if (err instanceof DOMException && err.name === 'AbortError') {\n          return;\n        }\n\n        // Ignore network errors caused by abort\n        const errorMessage = err instanceof Error ? err.message : String(err);\n        if (abortController.signal.aborted ||\n            errorMessage.includes('network error') ||\n            errorMessage.includes('aborted')) {\n          return;\n        }\n\n        if (mountedRef.current && srcIdRef.current === loadId) {\n          const error = err instanceof Error ? err : new Error('Failed to load document');\n          viewerStore.getState().setError(error);\n          setLoadState('error');\n          onErrorRef.current?.(error);\n        }\n      });\n\n    // Intentionally no cleanup returned: aborting here would fire on\n    // StrictMode's synthetic unmount, orphaning the first load and\n    // causing the synthetic remount to start a duplicate fetch. Abort\n    // is owned by two other sites: (a) the top of this effect when deps\n    // change — `abortControllerRef.current.abort()` above cancels the\n    // previous load before starting a new one — and (b) the mount\n    // effect's deferred teardown, which aborts on real unmount after\n    // setTimeout(0) (a real unmount does not remount to cancel it).\n    // Note: `src` is intentionally excluded from deps — `srcId` is derived\n    // from `src` and is stable across re-renders when the underlying content\n    // is unchanged, including ArrayBuffer/Uint8Array inputs whose identity\n    // may change on each parent render.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [srcId, workerSrc, initialPage, initialScale, viewerStore]);\n\n  // Page change notifications\n  const prevPageRef = useRef(currentPage);\n  useEffect(() => {\n    if (prevPageRef.current !== currentPage) {\n      prevPageRef.current = currentPage;\n      onPageChangeRef.current?.(currentPage);\n    }\n  }, [currentPage]);\n\n  // Scale change notifications\n  const prevScaleRef = useRef(scale);\n  useEffect(() => {\n    if (prevScaleRef.current !== scale) {\n      prevScaleRef.current = scale;\n      onScaleChangeRef.current?.(scale);\n      onZoomChangeRef.current?.(scale);\n    }\n  }, [scale]);\n\n  // Controlled mode: sync viewer to controlled page prop\n  useEffect(() => {\n    if (!isControlled || controlledPage === undefined) return;\n    if (prevControlledPageRef.current === controlledPage) return;\n\n    prevControlledPageRef.current = controlledPage;\n    const { numPages, currentPage } = viewerStore.getState();\n\n    // Only navigate if document is loaded and page is different\n    if (numPages > 0 && controlledPage !== currentPage) {\n      viewerStore.getState().requestScrollToPage(controlledPage, 'smooth');\n    }\n  }, [controlledPage, isControlled, viewerStore]);\n\n  const themeClass = theme === 'dark' ? 'dark' : '';\n\n  if (error) {\n    // Use custom error component if provided\n    if (errorComponent) {\n      const errorContent = typeof errorComponent === 'function'\n        ? errorComponent(error, handleRetry)\n        : errorComponent;\n\n      return (\n        <div\n          className={cn(\n            'pdf-viewer pdf-viewer-error',\n            'flex flex-col h-full',\n            'bg-white dark:bg-gray-900',\n            themeClass,\n            className\n          )}\n        >\n          {errorContent}\n        </div>\n      );\n    }\n\n    return (\n      <div\n        className={cn(\n          'pdf-viewer pdf-viewer-error',\n          'flex flex-col h-full',\n          'bg-white dark:bg-gray-900',\n          themeClass,\n          className\n        )}\n      >\n        <div className=\"flex-1 flex items-center justify-center\">\n          <div className=\"text-center p-8\">\n            <div className=\"text-red-500 text-lg font-semibold mb-2\">\n              Failed to load PDF\n            </div>\n            <div className=\"text-gray-500 text-sm\">{error.message}</div>\n            <button\n              onClick={handleRetry}\n              className=\"mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600\"\n            >\n              Retry\n            </button>\n          </div>\n        </div>\n      </div>\n    );\n  }\n\n  const renderContainer = () => {\n    switch (viewMode) {\n      case 'continuous':\n        return <ContinuousScrollContainer />;\n      case 'dual':\n        return <DualPageContainer />;\n      case 'book':\n        return <BookModeContainer />;\n      case 'single':\n      default:\n        return <DocumentContainer />;\n    }\n  };\n\n  return (\n    <div\n      className={cn(\n        'pdf-viewer',\n        'flex flex-col h-full relative',\n        'bg-white dark:bg-gray-900',\n        'text-gray-900 dark:text-gray-100',\n        themeClass,\n        className\n      )}\n    >\n      {showToolbar && <Toolbar />}\n      {showAnnotationToolbar && <AnnotationToolbar />}\n\n      <div className=\"flex flex-1 overflow-hidden\">\n        {showSidebar && sidebarOpen && <Sidebar />}\n        {renderContainer()}\n      </div>\n\n      {/* Floating Zoom Controls */}\n      {showFloatingZoom && <FloatingZoomControls position=\"bottom-right\" />}\n\n      {isLoading && (\n        <div className=\"absolute inset-0 z-50\">\n          {loadingComponent ?? (\n            <PDFLoadingScreen\n              phase={loadingProgress?.phase ?? 'fetching'}\n              progress={loadingProgress?.percent}\n              bytesLoaded={loadingProgress?.bytesLoaded}\n              totalBytes={loadingProgress?.totalBytes}\n            />\n          )}\n        </div>\n      )}\n\n      {/* Inline streaming progress indicator - shows when first page is ready but background loading continues */}\n      {!isLoading && streamingProgress && streamingProgress.total > 0 && streamingProgress.loaded < streamingProgress.total && (\n        <div className=\"absolute bottom-20 right-4 z-40 px-3 py-2 bg-gray-900/80 text-white text-xs rounded-lg shadow-lg flex items-center gap-2\">\n          <div className=\"w-3 h-3 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n          <span>Loading pages...</span>\n          <span className=\"text-white/60\">\n            {Math.round((streamingProgress.loaded / streamingProgress.total) * 100)}%\n          </span>\n        </div>\n      )}\n    </div>\n  );\n});\n\n/**\n * Calculate the bounding rectangles for a text match by tracking text item offsets.\n * This is the correct approach - it finds which text items contain the match\n * and calculates the proper rect position from each item's transform.\n */\nfunction calculateMatchRects(\n  textItems: Array<{ text: string; transform: number[]; width: number; height: number }>,\n  startOffset: number,\n  length: number,\n  viewport: { width: number; height: number }\n): HighlightRect[] {\n  const rects: HighlightRect[] = [];\n  let currentOffset = 0;\n\n  for (const item of textItems) {\n    const itemStart = currentOffset;\n    const itemEnd = currentOffset + item.text.length;\n\n    // Check if this item overlaps with our match\n    if (itemEnd > startOffset && itemStart < startOffset + length) {\n      const [, , c, d, tx, ty] = item.transform;\n\n      // Convert PDF coordinates to viewport coordinates\n      const x = tx;\n      const y = viewport.height - ty;\n\n      // Approximate height from transform matrix\n      const height = Math.sqrt(c * c + d * d);\n\n      // Calculate the portion of this item that's part of the match\n      const matchStartInItem = Math.max(0, startOffset - itemStart);\n      const matchEndInItem = Math.min(item.text.length, startOffset + length - itemStart);\n      const charWidth = item.text.length > 0 ? item.width / item.text.length : item.width;\n      const matchWidth = charWidth * (matchEndInItem - matchStartInItem);\n      const matchX = x + charWidth * matchStartInItem;\n\n      // Adjust Y position: ty is the baseline, we need to position highlight\n      // lower to align with the actual text glyphs (not the baseline)\n      const yOffset = height * 0.30; // Shift down by 30% of height\n\n      rects.push({\n        x: matchX,\n        y: y - height + yOffset,\n        width: matchWidth,\n        height: height,\n      });\n    }\n\n    currentOffset = itemEnd;\n  }\n\n  return rects;\n}\n\n// ============================================================================\n// Inner component with ref forwarding\n// ============================================================================\n\ninterface InnerWithRefProps extends PDFViewerProps {}\n\nconst PDFViewerInnerWithRef = forwardRef<PDFViewerHandle, InnerWithRefProps>(\n  function PDFViewerInnerWithRef(props, ref) {\n    const handleRef = useRef<PDFViewerHandle | null>(null);\n\n    // Forward the handle when ready\n    const handleReady = useCallback((handle: PDFViewerHandle) => {\n      handleRef.current = handle;\n      if (typeof ref === 'function') {\n        ref(handle);\n      } else if (ref) {\n        ref.current = handle;\n      }\n    }, [ref]);\n\n    return <PDFViewerInner {...props} onReady={handleReady} />;\n  }\n);\n\n// ============================================================================\n// Public Component\n// ============================================================================\n\n/**\n * PDF Viewer component with imperative API.\n *\n * @example\n * ```tsx\n * const viewerRef = useRef<PDFViewerHandle>(null);\n *\n * <PDFViewerClient\n *   ref={viewerRef}\n *   src=\"/document.pdf\"\n *   onDocumentLoad={() => {\n *     // Highlight text when document loads\n *     viewerRef.current?.highlightText(\"important\", { color: \"yellow\" });\n *   }}\n * />\n *\n * // Call methods anytime\n * viewerRef.current?.goToPage(5);\n * viewerRef.current?.drawRect({ page: 1, x: 10, y: 20, width: 30, height: 10 });\n * ```\n */\nexport const PDFViewerClient = memo(\n  forwardRef<PDFViewerHandle, PDFViewerProps>(function PDFViewerClient(props, ref) {\n    return (\n      <PDFViewerProvider\n        theme={props.theme}\n        defaultSidebarPanel={props.defaultSidebarPanel}\n      >\n        <PDFViewerInnerWithRef ref={ref} {...props} />\n      </PDFViewerProvider>\n    );\n  })\n);\n","import { lazy, Suspense, memo } from 'react';\nimport type { PDFViewerProps } from '../../types';\nimport { cn } from '../../utils';\n\n// Lazy load the client component to ensure it's only loaded on the client\nconst PDFViewerClient = lazy(() =>\n  import('./PDFViewerClient').then((mod) => ({ default: mod.PDFViewerClient }))\n);\n\ninterface PDFViewerLoadingProps {\n  className?: string;\n}\n\nconst PDFViewerLoading = memo(function PDFViewerLoading({\n  className,\n}: PDFViewerLoadingProps) {\n  return (\n    <div\n      className={cn(\n        'pdf-viewer pdf-viewer-loading',\n        'flex flex-col h-full',\n        'bg-white dark:bg-gray-900',\n        className\n      )}\n    >\n      <div className=\"flex-1 flex items-center justify-center\">\n        <div className=\"flex flex-col items-center\">\n          <div className=\"w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin\" />\n          <div className=\"mt-2 text-sm text-gray-500\">Loading PDF viewer...</div>\n        </div>\n      </div>\n    </div>\n  );\n});\n\n/**\n * Main PDF Viewer component.\n *\n * This component is SSR-safe and will only render on the client side.\n * It uses React.lazy and Suspense to defer loading of the PDF viewer\n * which depends on browser APIs.\n *\n * @example\n * ```tsx\n * import { PDFViewer } from 'pdfjs-reader-core';\n *\n * function App() {\n *   return (\n *     <PDFViewer\n *       src=\"/document.pdf\"\n *       showToolbar\n *       showSidebar\n *       onDocumentLoad={(doc) => console.log('Loaded', doc.numPages, 'pages')}\n *     />\n *   );\n * }\n * ```\n */\nexport const PDFViewer = memo(function PDFViewer(props: PDFViewerProps) {\n  // Check if we're on the server\n  if (typeof window === 'undefined') {\n    return <PDFViewerLoading className={props.className} />;\n  }\n\n  return (\n    <Suspense fallback={<PDFViewerLoading className={props.className} />}>\n      <PDFViewerClient {...props} />\n    </Suspense>\n  );\n});\n","export { PDFViewer } from './PDFViewer';\nexport { PDFViewerClient } from './PDFViewerClient';\nexport { DocumentContainer, type DocumentContainerProps } from './DocumentContainer';\nexport { VirtualizedDocumentContainer, type VirtualizedDocumentContainerProps } from './VirtualizedDocumentContainer';\nexport { ContinuousScrollContainer, type ContinuousScrollContainerProps } from './ContinuousScrollContainer';\nexport { DualPageContainer, type DualPageContainerProps } from './DualPageContainer';\nexport { PageSkeleton, type PageSkeletonProps, DEFAULT_PAGE_WIDTH, DEFAULT_PAGE_HEIGHT } from './PageSkeleton';\nexport { BookModeContainer, type BookModeContainerProps } from './BookModeContainer';\n","// Components\nexport {\n  // PDF Viewer\n  PDFViewer,\n  PDFViewerClient,\n  DocumentContainer,\n  VirtualizedDocumentContainer,\n  ContinuousScrollContainer,\n  DualPageContainer,\n  BookModeContainer,\n  // PDF Page\n  PDFPage,\n  CanvasLayer,\n  TextLayer,\n  HighlightLayer,\n  AnnotationLayer,\n  FocusRegionLayer,\n  // Toolbar\n  Toolbar,\n  MobileToolbar,\n  // Sidebar\n  Sidebar,\n  MobileSidebar,\n  ThumbnailPanel,\n  SearchPanel,\n  OutlinePanel,\n  HighlightsPanel,\n  BookmarksPanel,\n  TakeawaysPanel,\n  // Popovers\n  SelectionToolbar,\n  HighlightPopover,\n  // Annotations\n  AnnotationToolbar,\n  StickyNote,\n  DrawingCanvas,\n  ShapeRenderer,\n  ShapePreview,\n  QuickNoteButton,\n  QuickNotePopover,\n  // Ask About\n  AskAboutOverlay,\n  AskAboutTrigger,\n  // Minimap\n  Minimap,\n  // Floating Controls\n  FloatingZoomControls,\n  // Thumbnail Navigation\n  PDFThumbnailNav,\n  // Error Boundary\n  PDFErrorBoundary,\n  // Loading Screen\n  PDFLoadingScreen,\n  withErrorBoundary,\n} from './components';\n\n// Director (for advanced consumers who want to use the engine/director directly)\nexport {\n  directStoryboard,\n  type LlmConfig,\n  type DirectorInput,\n  type DirectorResult,\n} from './director/llm-director';\nexport { StoryboardEngine } from './director/storyboard-engine';\nexport {\n  buildUserPrompt,\n  SYSTEM_PROMPT,\n  truncate,\n  type BuildUserPromptInput,\n} from './director/prompts';\nexport {\n  StoryboardSchema,\n  StoryboardActionSchema,\n  storyboardJsonSchema,\n  type StoryboardParsed,\n} from './director/storyboard-schema';\nexport {\n  matchChunkToBlock,\n  storyboardFromMatch,\n  cosineSimilarity,\n  type EmbeddingProvider,\n  type BlockMatch,\n} from './director/embedding-fallback';\nexport { getLocalMiniLM } from './director/transformers-embedding';\n\nexport {\n  // Tutor Mode\n  TutorModeContainer,\n  CinemaLayer,\n  CameraView,\n  SpotlightMask,\n  AnimatedUnderline,\n  AnimatedHighlight,\n  PulseOverlay,\n  CalloutArrow,\n  GhostReference,\n  BoxOverlay,\n  StickyLabel,\n  SubtitleBar,\n  buildBBoxIndex,\n} from './components';\n\n// Hooks\nexport {\n  PDFViewerProvider,\n  PDFViewerContext,\n  useViewerStore,\n  useAnnotationStore,\n  useSearchStore,\n  useAgentStore,\n  useStudentStore,\n  usePDFViewerStores,\n  usePDFViewer,\n  usePageNavigation,\n  useZoom,\n  useTextSelection,\n  useHighlights,\n  useAnnotations,\n  useTouchGestures,\n  useIsTouchDevice,\n  useIsMobile,\n  usePlugins,\n  // Student Learning Hooks\n  useAgentContext,\n  useAskAbout,\n  useBookmarks,\n  useQuickNotes,\n  useStudentProgress,\n} from './hooks';\n\n// Stores\nexport {\n  createViewerStore,\n  createAnnotationStore,\n  createSearchStore,\n  createAgentStore,\n  createStudentStore,\n  createNarrationStore,\n  makeOverlayId,\n} from './store';\n\n// Plugins\nexport {\n  PluginManager,\n  getPluginManager,\n  createPluginManager,\n} from './plugins';\n\n// Utils\nexport {\n  cn,\n  initializePDFJS,\n  isPDFJSInitialized,\n  loadDocument,\n  loadDocumentWithCallbacks,\n  getPage,\n  getPageTextContent,\n  getOutline,\n  getMetadata,\n  pdfjsLib,\n  // Highlight storage\n  saveHighlights,\n  loadHighlights,\n  clearHighlights,\n  getAllDocumentIds,\n  exportHighlightsAsJSON,\n  importHighlightsFromJSON,\n  exportHighlightsAsMarkdown,\n  generateDocumentId,\n  // Convenience API\n  createPDFViewer,\n  quickViewer,\n  // Student Learning Utils\n  exportAnnotationsAsMarkdown,\n  exportAnnotationsAsJSON,\n  downloadAnnotationsAsMarkdown,\n  downloadAnnotationsAsJSON,\n  downloadFile,\n  // Student Storage\n  saveStudentData,\n  loadStudentData,\n  clearStudentData,\n  getAllStudentDataDocumentIds,\n  getStorageStats,\n  // Agent API\n  createAgentAPI,\n  // Text Search Utilities\n  extractPageText,\n  findTextOnPage,\n  findTextInDocument,\n  mergeAdjacentRects,\n  getPageText,\n  countTextOnPage,\n  // Page Turn Sound\n  playPageTurnSound,\n  // Coordinate Utilities\n  pdfToViewport,\n  viewportToPDF,\n  percentToPDF,\n  pdfToPercent,\n  percentToViewport,\n  viewportToPercent,\n  applyRotation,\n  removeRotation,\n  getRotatedDimensions,\n  scaleRect,\n  isPointInRect,\n  doRectsIntersect,\n  getRectIntersection,\n} from './utils';\n\n// Types\nexport type {\n  // Core types\n  PDFViewerProps,\n  PDFDocumentLoadedEvent,\n  TextSelection,\n  PDFPageState,\n  PageDimensions,\n\n  // Imperative API types\n  PDFViewerHandle,\n  HighlightTextOptions,\n  DrawRectOptions,\n  DrawCircleOptions,\n  AddNoteOptions,\n  SearchOptions,\n\n  // Viewer types\n  ViewerState,\n  ViewerActions,\n  ViewMode,\n  ScrollMode,\n  Theme,\n  SidebarPanel,\n\n  // Highlight types\n  Highlight,\n  HighlightRect,\n  HighlightColor,\n\n  // Annotation types\n  Annotation,\n  AnnotationType,\n  NoteAnnotation,\n  DrawingAnnotation,\n  DrawingPath,\n  ShapeAnnotation,\n\n  // Search types\n  SearchResult,\n  SearchState,\n\n  // Outline types\n  OutlineItem,\n\n  // Plugin types\n  Plugin,\n  PluginAPI,\n  ToolbarItem,\n  SidebarPanelConfig,\n  ContextMenuItem,\n  PDFViewerEventMap,\n\n  // Tutor Mode types\n  BlockType,\n  DefaultAction,\n  BBoxCoords,\n  Block,\n  PageDimensionsDpi,\n  PageBBoxData,\n  BBoxIndex,\n  EasingName,\n  SpotlightShape,\n  UnderlineStyle,\n  ArrowCurve,\n  PulseIntensity,\n  BoxStyle,\n  LabelPosition,\n  GhostPosition,\n  ClearTarget,\n  StoryboardAction,\n  ActionCamera,\n  ActionSpotlight,\n  ActionUnderline,\n  ActionHighlight,\n  ActionPulse,\n  ActionCallout,\n  ActionGhostReference,\n  ActionBox,\n  ActionLabel,\n  ActionClear,\n  StoryboardStep,\n  Storyboard,\n  ActiveOverlay,\n  CameraState,\n\n  // Agent & Student Learning types\n  AgentContext,\n  AskAboutContext,\n  PDFRegion,\n  FocusedRegion,\n  Bookmark,\n  QuickNote,\n  Takeaway,\n  AgentHighlightParams,\n  AgentAPI,\n  StudentState,\n  StudentActions,\n  AgentState,\n  AgentActions,\n  StudentModeCallbacks,\n  StudentModeProps,\n\n  // New types\n  ScrollToPageRequest,\n  GoToPageOptions,\n  SearchAndHighlightOptions,\n  SearchAndHighlightResult,\n  AgentToolResult,\n  AgentTools,\n  PageCoordinates,\n  PageDimensionsInfo,\n  CoordinateHelpers,\n  LoadingPhase,\n  LoadingProgress,\n  DocumentLoadingState,\n  StreamingProgress,\n} from './types';\n\n// Component types\nexport type { PDFLoadingScreenProps } from './components';\n\n// Store types\nexport type {\n  ViewerStore,\n  ViewerStoreApi,\n  AnnotationStore,\n  AnnotationStoreApi,\n  AnnotationState,\n  AnnotationActions,\n  AnnotationTool,\n  ShapeType,\n  SearchStore,\n  SearchStoreApi,\n  SearchActions,\n  AgentStore,\n  AgentStoreApi,\n  StudentStore,\n  StudentStoreApi,\n  NarrationStore,\n  NarrationStoreApi,\n  NarrationState,\n  NarrationActions,\n  EngineStatus,\n  LlmStatus,\n  ChunkHistoryEntry,\n  DebugEvent,\n} from './store';\n\n// Hook types\nexport type {\n  PDFViewerProviderProps,\n  PDFViewerContextValue,\n  UsePageNavigationOptions,\n  UseZoomOptions,\n  UseTextSelectionOptions,\n  UseHighlightsOptions,\n  UseHighlightsReturn,\n  UseAnnotationsOptions,\n  UseAnnotationsReturn,\n  UseTouchGesturesOptions,\n  UsePluginsOptions,\n  UsePluginsReturn,\n  UseAgentContextOptions,\n  UseAgentContextReturn,\n  UseAskAboutOptions,\n  UseAskAboutReturn,\n  UseBookmarksOptions,\n  UseBookmarksReturn,\n  UseQuickNotesOptions,\n  UseQuickNotesReturn,\n  UseStudentProgressOptions,\n  UseStudentProgressReturn,\n} from './hooks';\n\n// Component types\nexport type {\n  PDFPageProps,\n  CanvasLayerProps,\n  TextLayerProps,\n  HighlightLayerProps,\n  AnnotationLayerProps,\n  FocusRegionLayerProps,\n  ToolbarProps,\n  MobileToolbarProps,\n  SidebarProps,\n  MobileSidebarProps,\n  ThumbnailPanelProps,\n  SearchPanelProps,\n  OutlinePanelProps,\n  HighlightsPanelProps,\n  BookmarksPanelProps,\n  TakeawaysPanelProps,\n  DocumentContainerProps,\n  VirtualizedDocumentContainerProps,\n  ContinuousScrollContainerProps,\n  DualPageContainerProps,\n  BookModeContainerProps,\n  SelectionToolbarProps,\n  HighlightPopoverProps,\n  AnnotationToolbarProps,\n  StickyNoteProps,\n  DrawingCanvasProps,\n  ShapeRendererProps,\n  ShapePreviewProps,\n  QuickNoteButtonProps,\n  QuickNotePopoverProps,\n  AskAboutOverlayProps,\n  AskAboutTriggerProps,\n  MinimapProps,\n  FloatingZoomControlsProps,\n  PDFThumbnailNavProps,\n  PDFErrorBoundaryProps,\n  WithErrorBoundaryProps,\n  TutorModeContainerProps,\n  StoryboardProviderInput,\n  CinemaLayerProps,\n  CameraViewProps,\n  SpotlightMaskProps,\n  AnimatedUnderlineProps,\n  AnimatedHighlightProps,\n  PulseOverlayProps,\n  CalloutArrowProps,\n  GhostReferenceProps,\n  BoxOverlayProps,\n  StickyLabelProps,\n  SubtitleBarProps,\n} from './components';\n\n// Plugin types\nexport type { PluginManagerOptions } from './plugins';\n\n// Utils types\nexport type {\n  LoadDocumentOptions,\n  LoadDocumentResult,\n  LoadDocumentWithCallbacksOptions,\n  LoadDocumentWithCallbacksResult,\n  PDFViewerController,\n  PDFViewerControllerOptions,\n  ExportData,\n  StoredStudentData,\n  StudentData,\n  AgentAPIStores,\n  AgentAPIInstance,\n  TextMatch,\n  FindTextOptions,\n  CharPosition,\n} from './utils';\n","export {\n  PDFViewer,\n  PDFViewerClient,\n  DocumentContainer,\n  VirtualizedDocumentContainer,\n  ContinuousScrollContainer,\n  DualPageContainer,\n  BookModeContainer,\n} from './PDFViewer';\nexport { PDFPage, CanvasLayer, TextLayer, HighlightLayer, AnnotationLayer, FocusRegionLayer } from './PDFPage';\nexport { Toolbar, MobileToolbar } from './Toolbar';\nexport { Sidebar, MobileSidebar, ThumbnailPanel, SearchPanel, OutlinePanel, HighlightsPanel, BookmarksPanel, TakeawaysPanel } from './Sidebar';\nexport { SelectionToolbar } from './SelectionToolbar';\nexport { HighlightPopover } from './HighlightPopover';\nexport { AnnotationToolbar } from './AnnotationToolbar';\nexport { StickyNote, DrawingCanvas, ShapeRenderer, ShapePreview, QuickNoteButton, QuickNotePopover } from './Annotations';\nexport { AskAboutOverlay, AskAboutTrigger } from './AskAbout';\nexport { Minimap } from './Minimap';\nexport { FloatingZoomControls } from './FloatingZoomControls';\nexport { PDFThumbnailNav } from './PDFThumbnailNav';\nexport { PDFErrorBoundary, withErrorBoundary } from './ErrorBoundary';\nexport { PDFLoadingScreen } from './PDFLoadingScreen';\nexport {\n  TutorModeContainer,\n  CinemaLayer,\n  CameraView,\n  SpotlightMask,\n  AnimatedUnderline,\n  AnimatedHighlight,\n  PulseOverlay,\n  CalloutArrow,\n  GhostReference,\n  BoxOverlay,\n  StickyLabel,\n  SubtitleBar,\n  buildBBoxIndex,\n} from './TutorMode';\n\n// Re-export types\nexport type { PDFPageProps, CanvasLayerProps, TextLayerProps, HighlightLayerProps, AnnotationLayerProps, FocusRegionLayerProps } from './PDFPage';\nexport type { ToolbarProps, MobileToolbarProps } from './Toolbar';\nexport type { SidebarProps, MobileSidebarProps, ThumbnailPanelProps, SearchPanelProps, OutlinePanelProps, HighlightsPanelProps, BookmarksPanelProps, TakeawaysPanelProps } from './Sidebar';\nexport type {\n  DocumentContainerProps,\n  VirtualizedDocumentContainerProps,\n  ContinuousScrollContainerProps,\n  DualPageContainerProps,\n  BookModeContainerProps,\n} from './PDFViewer';\nexport type { SelectionToolbarProps } from './SelectionToolbar';\nexport type { HighlightPopoverProps } from './HighlightPopover';\nexport type { AnnotationToolbarProps } from './AnnotationToolbar';\nexport type { StickyNoteProps, DrawingCanvasProps, ShapeRendererProps, ShapePreviewProps, QuickNoteButtonProps, QuickNotePopoverProps } from './Annotations';\nexport type { AskAboutOverlayProps, AskAboutTriggerProps } from './AskAbout';\nexport type { MinimapProps } from './Minimap';\nexport type { FloatingZoomControlsProps } from './FloatingZoomControls';\nexport type { PDFThumbnailNavProps } from './PDFThumbnailNav';\nexport type { PDFErrorBoundaryProps, WithErrorBoundaryProps } from './ErrorBoundary';\nexport type { PDFLoadingScreenProps } from './PDFLoadingScreen';\nexport type {\n  TutorModeContainerProps,\n  StoryboardProviderInput,\n  CinemaLayerProps,\n  CameraViewProps,\n  SpotlightMaskProps,\n  AnimatedUnderlineProps,\n  AnimatedHighlightProps,\n  PulseOverlayProps,\n  CalloutArrowProps,\n  GhostReferenceProps,\n  BoxOverlayProps,\n  StickyLabelProps,\n  SubtitleBarProps,\n} from './TutorMode';\n","import { memo, useState, useRef, useEffect, useCallback, KeyboardEvent } from 'react';\nimport type { NoteAnnotation } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface StickyNoteProps {\n  note: NoteAnnotation;\n  scale: number;\n  isSelected?: boolean;\n  isEditing?: boolean;\n  onSelect?: () => void;\n  onUpdate?: (updates: Partial<NoteAnnotation>) => void;\n  onDelete?: () => void;\n  onStartEdit?: () => void;\n  onEndEdit?: () => void;\n  onDragStart?: (e: React.MouseEvent | React.TouchEvent) => void;\n  className?: string;\n}\n\nconst NOTE_COLORS = [\n  '#fef08a', // yellow\n  '#bbf7d0', // green\n  '#bfdbfe', // blue\n  '#fbcfe8', // pink\n  '#fed7aa', // orange\n];\n\nexport const StickyNote = memo(function StickyNote({\n  note,\n  scale,\n  isSelected,\n  isEditing,\n  onSelect,\n  onUpdate,\n  onDelete,\n  onStartEdit,\n  onEndEdit,\n  onDragStart,\n  className,\n}: StickyNoteProps) {\n  const [isExpanded, setIsExpanded] = useState(false);\n  const [localContent, setLocalContent] = useState(note.content);\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n  const noteRef = useRef<HTMLDivElement>(null);\n\n  // Update local content when note changes\n  useEffect(() => {\n    setLocalContent(note.content);\n  }, [note.content]);\n\n  // Focus textarea when editing starts\n  useEffect(() => {\n    if (isEditing && textareaRef.current) {\n      textareaRef.current.focus();\n      textareaRef.current.select();\n    }\n  }, [isEditing]);\n\n  const handleClick = useCallback((e: React.MouseEvent) => {\n    e.stopPropagation();\n    onSelect?.();\n    if (!isExpanded) {\n      setIsExpanded(true);\n    }\n  }, [isExpanded, onSelect]);\n\n  const handleDoubleClick = useCallback((e: React.MouseEvent) => {\n    e.stopPropagation();\n    onStartEdit?.();\n  }, [onStartEdit]);\n\n  const handleBlur = useCallback(() => {\n    if (isEditing && localContent !== note.content) {\n      onUpdate?.({ content: localContent });\n    }\n    onEndEdit?.();\n  }, [isEditing, localContent, note.content, onUpdate, onEndEdit]);\n\n  const handleKeyDown = useCallback((e: KeyboardEvent<HTMLTextAreaElement>) => {\n    if (e.key === 'Escape') {\n      setLocalContent(note.content);\n      onEndEdit?.();\n    } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n      handleBlur();\n    }\n  }, [note.content, onEndEdit, handleBlur]);\n\n  const handleColorChange = useCallback((color: string) => {\n    onUpdate?.({ color });\n  }, [onUpdate]);\n\n  const handleCollapse = useCallback((e: React.MouseEvent) => {\n    e.stopPropagation();\n    setIsExpanded(false);\n    onEndEdit?.();\n  }, [onEndEdit]);\n\n  // Collapsed note icon\n  if (!isExpanded) {\n    return (\n      <div\n        ref={noteRef}\n        className={cn(\n          'absolute cursor-pointer transition-transform hover:scale-110',\n          'w-6 h-6 rounded-sm shadow-md',\n          'flex items-center justify-center',\n          isSelected && 'ring-2 ring-blue-500 ring-offset-1',\n          className\n        )}\n        style={{\n          left: note.x * scale,\n          top: note.y * scale,\n          backgroundColor: note.color,\n          zIndex: isSelected ? 60 : 55,\n        }}\n        onClick={handleClick}\n        onMouseDown={onDragStart}\n        onTouchStart={onDragStart}\n        title={note.content || 'Empty note'}\n      >\n        <svg\n          className=\"w-4 h-4 opacity-70\"\n          fill=\"currentColor\"\n          viewBox=\"0 0 20 20\"\n          style={{ color: '#333' }}\n        >\n          <path\n            fillRule=\"evenodd\"\n            d=\"M18 10c0 3.866-3.582 7-8 7a8.841 8.841 0 01-4.083-.98L2 17l1.338-3.123C2.493 12.767 2 11.434 2 10c0-3.866 3.582-7 8-7s8 3.134 8 7zM7 9H5v2h2V9zm8 0h-2v2h2V9zM9 9h2v2H9V9z\"\n            clipRule=\"evenodd\"\n          />\n        </svg>\n      </div>\n    );\n  }\n\n  // Expanded note\n  return (\n    <div\n      ref={noteRef}\n      className={cn(\n        'absolute rounded shadow-lg transition-shadow',\n        'min-w-[180px] max-w-[280px]',\n        isSelected && 'ring-2 ring-blue-500',\n        className\n      )}\n      style={{\n        left: note.x * scale,\n        top: note.y * scale,\n        backgroundColor: note.color,\n        zIndex: isSelected ? 60 : 55,\n      }}\n      onClick={handleClick}\n    >\n      {/* Header */}\n      <div\n        className=\"flex items-center justify-between px-2 py-1 border-b border-black/10 cursor-move\"\n        onMouseDown={onDragStart}\n        onTouchStart={onDragStart}\n      >\n        {/* Color picker */}\n        <div className=\"flex gap-1\">\n          {NOTE_COLORS.map((color) => (\n            <button\n              key={color}\n              className={cn(\n                'w-4 h-4 rounded-full border border-black/20',\n                'hover:scale-110 transition-transform',\n                note.color === color && 'ring-1 ring-black/30'\n              )}\n              style={{ backgroundColor: color }}\n              onClick={(e) => {\n                e.stopPropagation();\n                handleColorChange(color);\n              }}\n              title={`Change to ${color}`}\n            />\n          ))}\n        </div>\n\n        {/* Actions */}\n        <div className=\"flex gap-1\">\n          <button\n            className=\"p-0.5 hover:bg-black/10 rounded\"\n            onClick={(e) => {\n              e.stopPropagation();\n              onDelete?.();\n            }}\n            title=\"Delete note\"\n          >\n            <svg className=\"w-3.5 h-3.5 text-gray-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" />\n            </svg>\n          </button>\n          <button\n            className=\"p-0.5 hover:bg-black/10 rounded\"\n            onClick={handleCollapse}\n            title=\"Collapse note\"\n          >\n            <svg className=\"w-3.5 h-3.5 text-gray-600\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n              <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n            </svg>\n          </button>\n        </div>\n      </div>\n\n      {/* Content */}\n      <div className=\"p-2\">\n        {isEditing ? (\n          <textarea\n            ref={textareaRef}\n            className={cn(\n              'w-full min-h-[60px] resize-none bg-transparent',\n              'text-sm text-gray-800 placeholder-gray-500',\n              'border-none outline-none focus:ring-0'\n            )}\n            value={localContent}\n            onChange={(e) => setLocalContent(e.target.value)}\n            onBlur={handleBlur}\n            onKeyDown={handleKeyDown}\n            placeholder=\"Enter note...\"\n          />\n        ) : (\n          <div\n            className={cn(\n              'text-sm text-gray-800 whitespace-pre-wrap min-h-[40px]',\n              !note.content && 'text-gray-500 italic'\n            )}\n            onDoubleClick={handleDoubleClick}\n          >\n            {note.content || 'Double-click to edit...'}\n          </div>\n        )}\n      </div>\n\n      {/* Timestamp */}\n      <div className=\"px-2 pb-1 text-[10px] text-gray-500\">\n        {new Date(note.updatedAt).toLocaleDateString()}\n      </div>\n    </div>\n  );\n});\n","import { memo, useRef, useCallback, useState } from 'react';\nimport type { DrawingPath } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface DrawingCanvasProps {\n  width: number;\n  height: number;\n  scale: number;\n  color?: string;\n  strokeWidth?: number;\n  isActive?: boolean;\n  onDrawingComplete?: (path: DrawingPath) => void;\n  className?: string;\n}\n\n// Convert points to SVG path string\nfunction pointsToSvgPath(points: { x: number; y: number }[]): string {\n  if (points.length === 0) return '';\n  if (points.length === 1) {\n    const p = points[0];\n    return `M ${p.x} ${p.y} L ${p.x} ${p.y}`;\n  }\n\n  // Use quadratic bezier curves for smoother lines\n  let path = `M ${points[0].x} ${points[0].y}`;\n\n  for (let i = 1; i < points.length - 1; i++) {\n    const p1 = points[i];\n    const p2 = points[i + 1];\n\n    // Calculate control point as midpoint\n    const midX = (p1.x + p2.x) / 2;\n    const midY = (p1.y + p2.y) / 2;\n\n    // Quadratic curve to the midpoint using p1 as control point\n    path += ` Q ${p1.x} ${p1.y} ${midX} ${midY}`;\n  }\n\n  // Line to the last point\n  if (points.length > 1) {\n    const lastPoint = points[points.length - 1];\n    path += ` L ${lastPoint.x} ${lastPoint.y}`;\n  }\n\n  return path;\n}\n\n// Simplify path by removing redundant points\nfunction simplifyPath(\n  points: { x: number; y: number }[],\n  tolerance: number = 1\n): { x: number; y: number }[] {\n  if (points.length < 3) return points;\n\n  const result: { x: number; y: number }[] = [points[0]];\n  let lastAdded = points[0];\n\n  for (let i = 1; i < points.length - 1; i++) {\n    const point = points[i];\n    const dx = point.x - lastAdded.x;\n    const dy = point.y - lastAdded.y;\n    const dist = Math.sqrt(dx * dx + dy * dy);\n\n    if (dist >= tolerance) {\n      result.push(point);\n      lastAdded = point;\n    }\n  }\n\n  // Always add the last point\n  result.push(points[points.length - 1]);\n  return result;\n}\n\nexport const DrawingCanvas = memo(function DrawingCanvas({\n  width,\n  height,\n  scale,\n  color = '#ef4444',\n  strokeWidth = 2,\n  isActive = false,\n  onDrawingComplete,\n  className,\n}: DrawingCanvasProps) {\n  const svgRef = useRef<SVGSVGElement>(null);\n  const [isDrawing, setIsDrawing] = useState(false);\n  const [currentPath, setCurrentPath] = useState<{ x: number; y: number }[]>([]);\n\n  const getPoint = useCallback((e: React.MouseEvent | React.TouchEvent): { x: number; y: number } | null => {\n    if (!svgRef.current) return null;\n\n    const svg = svgRef.current;\n    const rect = svg.getBoundingClientRect();\n\n    let clientX: number;\n    let clientY: number;\n\n    if ('touches' in e) {\n      const touch = e.touches[0];\n      if (!touch) return null;\n      clientX = touch.clientX;\n      clientY = touch.clientY;\n    } else {\n      clientX = e.clientX;\n      clientY = e.clientY;\n    }\n\n    return {\n      x: (clientX - rect.left) / scale,\n      y: (clientY - rect.top) / scale,\n    };\n  }, [scale]);\n\n  const handleStart = useCallback((e: React.MouseEvent | React.TouchEvent) => {\n    if (!isActive) return;\n\n    const point = getPoint(e);\n    if (point) {\n      setIsDrawing(true);\n      setCurrentPath([point]);\n    }\n  }, [isActive, getPoint]);\n\n  const handleMove = useCallback((e: React.MouseEvent | React.TouchEvent) => {\n    if (!isDrawing || !isActive) return;\n\n    const point = getPoint(e);\n    if (point) {\n      setCurrentPath(prev => [...prev, point]);\n    }\n  }, [isDrawing, isActive, getPoint]);\n\n  const handleEnd = useCallback(() => {\n    if (!isDrawing) return;\n\n    setIsDrawing(false);\n\n    if (currentPath.length >= 2) {\n      const simplifiedPoints = simplifyPath(currentPath, 2);\n      onDrawingComplete?.({ points: simplifiedPoints });\n    }\n\n    setCurrentPath([]);\n  }, [isDrawing, currentPath, onDrawingComplete]);\n\n  return (\n    <svg\n      ref={svgRef}\n      className={cn(\n        'drawing-canvas',\n        isActive && 'cursor-crosshair',\n        className\n      )}\n      width={width * scale}\n      height={height * scale}\n      viewBox={`0 0 ${width} ${height}`}\n      style={{ touchAction: isActive ? 'none' : 'auto' }}\n      onMouseDown={handleStart}\n      onMouseMove={handleMove}\n      onMouseUp={handleEnd}\n      onMouseLeave={handleEnd}\n      onTouchStart={handleStart}\n      onTouchMove={handleMove}\n      onTouchEnd={handleEnd}\n    >\n      {/* Current drawing path preview */}\n      {isDrawing && currentPath.length > 0 && (\n        <path\n          d={pointsToSvgPath(currentPath)}\n          fill=\"none\"\n          stroke={color}\n          strokeWidth={strokeWidth}\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          opacity={0.8}\n        />\n      )}\n    </svg>\n  );\n});\n\n// Export helper functions for reuse\nexport { pointsToSvgPath, simplifyPath };\n","import { memo, useCallback, useState, useRef } from 'react';\nimport type { ShapeAnnotation } from '../../types';\nimport { cn } from '../../utils';\n\nexport interface ShapeRendererProps {\n  shape: ShapeAnnotation;\n  scale: number;\n  isSelected?: boolean;\n  isEditing?: boolean;\n  onSelect?: () => void;\n  onUpdate?: (updates: Partial<ShapeAnnotation>) => void;\n  onDelete?: () => void;\n  className?: string;\n}\n\ninterface ResizeHandle {\n  position: 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w';\n  cursor: string;\n  x: number;\n  y: number;\n}\n\nexport const ShapeRenderer = memo(function ShapeRenderer({\n  shape,\n  scale,\n  isSelected,\n  isEditing,\n  onSelect,\n  onUpdate,\n  onDelete: _onDelete,\n  className,\n}: ShapeRendererProps) {\n  const [_isDragging, setIsDragging] = useState(false);\n  const [_isResizing, setIsResizing] = useState(false);\n  const [activeHandle, setActiveHandle] = useState<string | null>(null);\n  const startPosRef = useRef({ x: 0, y: 0 });\n  const startShapeRef = useRef({ x: 0, y: 0, width: 0, height: 0 });\n\n  const { shapeType, x, y, width, height, color, strokeWidth, id: _id } = shape;\n  const scaledX = x * scale;\n  const scaledY = y * scale;\n  const scaledWidth = width * scale;\n  const scaledHeight = height * scale;\n  const scaledStroke = strokeWidth * scale;\n\n  // Calculate resize handles positions\n  const getResizeHandles = useCallback((): ResizeHandle[] => {\n    const handleSize = 8;\n    const half = handleSize / 2;\n\n    return [\n      { position: 'nw', cursor: 'nwse-resize', x: scaledX - half, y: scaledY - half },\n      { position: 'n', cursor: 'ns-resize', x: scaledX + scaledWidth / 2 - half, y: scaledY - half },\n      { position: 'ne', cursor: 'nesw-resize', x: scaledX + scaledWidth - half, y: scaledY - half },\n      { position: 'e', cursor: 'ew-resize', x: scaledX + scaledWidth - half, y: scaledY + scaledHeight / 2 - half },\n      { position: 'se', cursor: 'nwse-resize', x: scaledX + scaledWidth - half, y: scaledY + scaledHeight - half },\n      { position: 's', cursor: 'ns-resize', x: scaledX + scaledWidth / 2 - half, y: scaledY + scaledHeight - half },\n      { position: 'sw', cursor: 'nesw-resize', x: scaledX - half, y: scaledY + scaledHeight - half },\n      { position: 'w', cursor: 'ew-resize', x: scaledX - half, y: scaledY + scaledHeight / 2 - half },\n    ];\n  }, [scaledX, scaledY, scaledWidth, scaledHeight]);\n\n  const handleMouseDown = useCallback((e: React.MouseEvent, handle?: string) => {\n    e.stopPropagation();\n    onSelect?.();\n\n    if (!isEditing) return;\n\n    startPosRef.current = { x: e.clientX, y: e.clientY };\n    startShapeRef.current = { x, y, width, height };\n\n    if (handle) {\n      setIsResizing(true);\n      setActiveHandle(handle);\n    } else {\n      setIsDragging(true);\n    }\n\n    const handleMouseMove = (moveEvent: MouseEvent) => {\n      const dx = (moveEvent.clientX - startPosRef.current.x) / scale;\n      const dy = (moveEvent.clientY - startPosRef.current.y) / scale;\n\n      if (handle) {\n        // Resizing\n        let newX = startShapeRef.current.x;\n        let newY = startShapeRef.current.y;\n        let newWidth = startShapeRef.current.width;\n        let newHeight = startShapeRef.current.height;\n\n        switch (handle) {\n          case 'nw':\n            newX += dx;\n            newY += dy;\n            newWidth -= dx;\n            newHeight -= dy;\n            break;\n          case 'n':\n            newY += dy;\n            newHeight -= dy;\n            break;\n          case 'ne':\n            newY += dy;\n            newWidth += dx;\n            newHeight -= dy;\n            break;\n          case 'e':\n            newWidth += dx;\n            break;\n          case 'se':\n            newWidth += dx;\n            newHeight += dy;\n            break;\n          case 's':\n            newHeight += dy;\n            break;\n          case 'sw':\n            newX += dx;\n            newWidth -= dx;\n            newHeight += dy;\n            break;\n          case 'w':\n            newX += dx;\n            newWidth -= dx;\n            break;\n        }\n\n        // Ensure minimum size\n        if (newWidth >= 10 && newHeight >= 10) {\n          onUpdate?.({ x: newX, y: newY, width: newWidth, height: newHeight });\n        }\n      } else {\n        // Dragging\n        onUpdate?.({\n          x: startShapeRef.current.x + dx,\n          y: startShapeRef.current.y + dy,\n        });\n      }\n    };\n\n    const handleMouseUp = () => {\n      setIsDragging(false);\n      setIsResizing(false);\n      setActiveHandle(null);\n      document.removeEventListener('mousemove', handleMouseMove);\n      document.removeEventListener('mouseup', handleMouseUp);\n    };\n\n    document.addEventListener('mousemove', handleMouseMove);\n    document.addEventListener('mouseup', handleMouseUp);\n  }, [isEditing, x, y, width, height, scale, onSelect, onUpdate]);\n\n  const renderShape = useCallback(() => {\n    const commonProps = {\n      stroke: color,\n      strokeWidth: scaledStroke,\n      fill: 'none',\n      className: cn(\n        'cursor-pointer transition-opacity',\n        isSelected && 'filter drop-shadow-sm'\n      ),\n    };\n\n    switch (shapeType) {\n      case 'rect':\n        return (\n          <rect\n            x={scaledX}\n            y={scaledY}\n            width={scaledWidth}\n            height={scaledHeight}\n            {...commonProps}\n          />\n        );\n\n      case 'circle':\n        return (\n          <ellipse\n            cx={scaledX + scaledWidth / 2}\n            cy={scaledY + scaledHeight / 2}\n            rx={scaledWidth / 2}\n            ry={scaledHeight / 2}\n            {...commonProps}\n          />\n        );\n\n      case 'line':\n        return (\n          <line\n            x1={scaledX}\n            y1={scaledY}\n            x2={scaledX + scaledWidth}\n            y2={scaledY + scaledHeight}\n            {...commonProps}\n          />\n        );\n\n      case 'arrow':\n        const endX = scaledX + scaledWidth;\n        const endY = scaledY + scaledHeight;\n        const angle = Math.atan2(scaledHeight, scaledWidth);\n        const arrowLength = Math.min(15, Math.sqrt(scaledWidth * scaledWidth + scaledHeight * scaledHeight) * 0.2);\n        const arrowAngle = Math.PI / 6;\n\n        const arrow1X = endX - arrowLength * Math.cos(angle - arrowAngle);\n        const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);\n        const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);\n        const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);\n\n        return (\n          <g>\n            <line x1={scaledX} y1={scaledY} x2={endX} y2={endY} {...commonProps} />\n            <line x1={endX} y1={endY} x2={arrow1X} y2={arrow1Y} {...commonProps} />\n            <line x1={endX} y1={endY} x2={arrow2X} y2={arrow2Y} {...commonProps} />\n          </g>\n        );\n\n      default:\n        return null;\n    }\n  }, [shapeType, scaledX, scaledY, scaledWidth, scaledHeight, color, scaledStroke, isSelected]);\n\n  return (\n    <g\n      className={cn('shape-renderer', className)}\n      onMouseDown={(e) => handleMouseDown(e)}\n    >\n      {/* Hit area for selection (invisible, larger) */}\n      <rect\n        x={scaledX - 5}\n        y={scaledY - 5}\n        width={scaledWidth + 10}\n        height={scaledHeight + 10}\n        fill=\"transparent\"\n        stroke=\"none\"\n        className=\"cursor-pointer\"\n      />\n\n      {/* The actual shape */}\n      {renderShape()}\n\n      {/* Selection outline */}\n      {isSelected && (\n        <rect\n          x={scaledX - 2}\n          y={scaledY - 2}\n          width={scaledWidth + 4}\n          height={scaledHeight + 4}\n          fill=\"none\"\n          stroke=\"#3b82f6\"\n          strokeWidth={1}\n          strokeDasharray=\"4 2\"\n        />\n      )}\n\n      {/* Resize handles when editing */}\n      {isSelected && isEditing && getResizeHandles().map((handle) => (\n        <rect\n          key={handle.position}\n          x={handle.x}\n          y={handle.y}\n          width={8}\n          height={8}\n          fill=\"white\"\n          stroke=\"#3b82f6\"\n          strokeWidth={1}\n          className={cn('cursor-pointer', activeHandle === handle.position && 'fill-blue-500')}\n          style={{ cursor: handle.cursor }}\n          onMouseDown={(e) => handleMouseDown(e, handle.position)}\n        />\n      ))}\n    </g>\n  );\n});\n\n// Shape preview component for drawing new shapes\nexport interface ShapePreviewProps {\n  shapeType: 'rect' | 'circle' | 'arrow' | 'line';\n  startPoint: { x: number; y: number };\n  endPoint: { x: number; y: number };\n  scale: number;\n  color: string;\n  strokeWidth: number;\n}\n\nexport const ShapePreview = memo(function ShapePreview({\n  shapeType,\n  startPoint,\n  endPoint,\n  scale,\n  color,\n  strokeWidth,\n}: ShapePreviewProps) {\n  const x = Math.min(startPoint.x, endPoint.x) * scale;\n  const y = Math.min(startPoint.y, endPoint.y) * scale;\n  const width = Math.abs(endPoint.x - startPoint.x) * scale;\n  const height = Math.abs(endPoint.y - startPoint.y) * scale;\n  const scaledStroke = strokeWidth * scale;\n\n  const commonProps = {\n    stroke: color,\n    strokeWidth: scaledStroke,\n    fill: 'none',\n    opacity: 0.7,\n  };\n\n  switch (shapeType) {\n    case 'rect':\n      return (\n        <rect x={x} y={y} width={width} height={height} {...commonProps} />\n      );\n\n    case 'circle':\n      return (\n        <ellipse\n          cx={x + width / 2}\n          cy={y + height / 2}\n          rx={width / 2}\n          ry={height / 2}\n          {...commonProps}\n        />\n      );\n\n    case 'line':\n      return (\n        <line\n          x1={startPoint.x * scale}\n          y1={startPoint.y * scale}\n          x2={endPoint.x * scale}\n          y2={endPoint.y * scale}\n          {...commonProps}\n        />\n      );\n\n    case 'arrow':\n      const endX = endPoint.x * scale;\n      const endY = endPoint.y * scale;\n      const dx = endPoint.x - startPoint.x;\n      const dy = endPoint.y - startPoint.y;\n      const angle = Math.atan2(dy, dx);\n      const arrowLength = Math.min(15, Math.sqrt(width * width + height * height) * 0.2);\n      const arrowAngle = Math.PI / 6;\n\n      const arrow1X = endX - arrowLength * Math.cos(angle - arrowAngle);\n      const arrow1Y = endY - arrowLength * Math.sin(angle - arrowAngle);\n      const arrow2X = endX - arrowLength * Math.cos(angle + arrowAngle);\n      const arrow2Y = endY - arrowLength * Math.sin(angle + arrowAngle);\n\n      return (\n        <g>\n          <line\n            x1={startPoint.x * scale}\n            y1={startPoint.y * scale}\n            x2={endX}\n            y2={endY}\n            {...commonProps}\n          />\n          <line x1={endX} y1={endY} x2={arrow1X} y2={arrow1Y} {...commonProps} />\n          <line x1={endX} y1={endY} x2={arrow2X} y2={arrow2Y} {...commonProps} />\n        </g>\n      );\n\n    default:\n      return null;\n  }\n});\n","import { memo, useCallback, useState } from 'react';\nimport { cn } from '../../utils';\n\nexport interface QuickNoteButtonProps {\n  /** Page number this button is for */\n  pageNumber: number;\n  /** Scale of the page */\n  scale: number;\n  /** Position of the button (relative to page) */\n  position?: 'top-right' | 'bottom-right';\n  /** Callback when button is clicked */\n  onClick: (pageNumber: number, x: number, y: number) => void;\n  /** Custom className */\n  className?: string;\n  /** Whether the button is visible */\n  visible?: boolean;\n}\n\n/**\n * Floating button on each page to quickly add a note.\n */\nexport const QuickNoteButton = memo(function QuickNoteButton({\n  pageNumber,\n  scale,\n  position = 'top-right',\n  onClick,\n  className,\n  visible = true,\n}: QuickNoteButtonProps) {\n  const [isHovered, setIsHovered] = useState(false);\n\n  const handleClick = useCallback(\n    (e: React.MouseEvent) => {\n      e.stopPropagation();\n      // Default position near button (based on button position)\n      const x = position === 'top-right' ? 80 : 80;\n      const y = position === 'top-right' ? 20 : 80;\n      onClick(pageNumber, x / scale, y / scale);\n    },\n    [pageNumber, onClick, position, scale]\n  );\n\n  if (!visible) {\n    return null;\n  }\n\n  return (\n    <button\n      onClick={handleClick}\n      onMouseEnter={() => setIsHovered(true)}\n      onMouseLeave={() => setIsHovered(false)}\n      className={cn(\n        'quick-note-button',\n        'absolute z-50',\n        'w-8 h-8 rounded-full',\n        'bg-yellow-400 hover:bg-yellow-500',\n        'shadow-md hover:shadow-lg',\n        'flex items-center justify-center',\n        'transition-all duration-200',\n        'focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:ring-offset-2',\n        isHovered && 'scale-110',\n        position === 'top-right' && 'top-3 right-3',\n        position === 'bottom-right' && 'bottom-3 right-3',\n        className\n      )}\n      title=\"Add quick note\"\n      aria-label=\"Add quick note\"\n    >\n      <svg\n        className=\"w-4 h-4 text-yellow-900\"\n        fill=\"none\"\n        viewBox=\"0 0 24 24\"\n        stroke=\"currentColor\"\n        strokeWidth={2}\n      >\n        <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 4v16m8-8H4\" />\n      </svg>\n    </button>\n  );\n});\n","import { memo, useCallback, useState, useRef, useEffect } from 'react';\nimport { cn } from '../../utils';\n\nexport interface QuickNotePopoverProps {\n  /** Whether the popover is visible */\n  visible: boolean;\n  /** Position of the popover */\n  position: { x: number; y: number };\n  /** Initial content */\n  initialContent?: string;\n  /** Agent's last statement to display */\n  agentLastStatement?: string;\n  /** Callback when note is saved */\n  onSave: (content: string) => void;\n  /** Callback when cancelled */\n  onCancel: () => void;\n  /** Custom className */\n  className?: string;\n}\n\n/**\n * Popover for entering quick note content.\n */\nexport const QuickNotePopover = memo(function QuickNotePopover({\n  visible,\n  position,\n  initialContent = '',\n  agentLastStatement,\n  onSave,\n  onCancel,\n  className,\n}: QuickNotePopoverProps) {\n  const [content, setContent] = useState(initialContent);\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n  const popoverRef = useRef<HTMLDivElement>(null);\n  const [adjustedPosition, setAdjustedPosition] = useState(position);\n\n  // Focus textarea when visible\n  useEffect(() => {\n    if (visible && textareaRef.current) {\n      textareaRef.current.focus();\n    }\n  }, [visible]);\n\n  // Reset content when opening\n  useEffect(() => {\n    if (visible) {\n      setContent(initialContent);\n    }\n  }, [visible, initialContent]);\n\n  // Adjust position to stay within viewport\n  useEffect(() => {\n    if (!visible || !popoverRef.current) return;\n\n    const rect = popoverRef.current.getBoundingClientRect();\n    const padding = 10;\n    let { x, y } = position;\n\n    // Adjust horizontal position\n    if (x + rect.width > window.innerWidth - padding) {\n      x = window.innerWidth - rect.width - padding;\n    }\n    if (x < padding) {\n      x = padding;\n    }\n\n    // Adjust vertical position\n    if (y + rect.height > window.innerHeight - padding) {\n      y = window.innerHeight - rect.height - padding;\n    }\n    if (y < padding) {\n      y = padding;\n    }\n\n    setAdjustedPosition({ x, y });\n  }, [position, visible]);\n\n  const handleSave = useCallback(() => {\n    if (content.trim()) {\n      onSave(content.trim());\n    } else {\n      onCancel();\n    }\n  }, [content, onSave, onCancel]);\n\n  const handleKeyDown = useCallback(\n    (e: React.KeyboardEvent) => {\n      if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n        e.preventDefault();\n        handleSave();\n      } else if (e.key === 'Escape') {\n        e.preventDefault();\n        onCancel();\n      }\n    },\n    [handleSave, onCancel]\n  );\n\n  if (!visible) {\n    return null;\n  }\n\n  return (\n    <div\n      ref={popoverRef}\n      className={cn(\n        'quick-note-popover',\n        'fixed z-[9999]',\n        'bg-yellow-50 dark:bg-yellow-900/90',\n        'rounded-lg shadow-xl',\n        'border border-yellow-200 dark:border-yellow-700',\n        'p-3 w-72',\n        'animate-in fade-in zoom-in-95 duration-150',\n        className\n      )}\n      style={{\n        left: adjustedPosition.x,\n        top: adjustedPosition.y,\n      }}\n    >\n      {/* Agent context hint */}\n      {agentLastStatement && (\n        <div className=\"mb-2 p-2 bg-blue-50 dark:bg-blue-900/50 rounded text-xs text-blue-600 dark:text-blue-300 border border-blue-100 dark:border-blue-800\">\n          <div className=\"flex items-start gap-1\">\n            <svg className=\"w-3 h-3 mt-0.5 flex-shrink-0\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n              <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\n            </svg>\n            <span className=\"line-clamp-2\">AI discussed: &ldquo;{agentLastStatement}&rdquo;</span>\n          </div>\n        </div>\n      )}\n\n      <textarea\n        ref={textareaRef}\n        value={content}\n        onChange={(e) => setContent(e.target.value)}\n        onKeyDown={handleKeyDown}\n        placeholder=\"Write your note...\"\n        className={cn(\n          'w-full h-24 px-2 py-1.5 rounded',\n          'bg-white dark:bg-gray-800',\n          'border border-yellow-200 dark:border-yellow-700',\n          'text-gray-900 dark:text-white text-sm',\n          'placeholder:text-gray-400',\n          'focus:outline-none focus:ring-2 focus:ring-yellow-500',\n          'resize-none'\n        )}\n      />\n\n      <div className=\"flex items-center justify-between mt-2\">\n        <span className=\"text-xs text-gray-500 dark:text-gray-400\">\n          {navigator.platform.includes('Mac') ? '⌘' : 'Ctrl'}+Enter to save\n        </span>\n        <div className=\"flex gap-2\">\n          <button\n            onClick={onCancel}\n            className={cn(\n              'px-3 py-1 rounded text-sm',\n              'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300',\n              'hover:bg-gray-200 dark:hover:bg-gray-600',\n              'focus:outline-none focus:ring-2 focus:ring-gray-500'\n            )}\n          >\n            Cancel\n          </button>\n          <button\n            onClick={handleSave}\n            disabled={!content.trim()}\n            className={cn(\n              'px-3 py-1 rounded text-sm font-medium',\n              'bg-yellow-500 text-yellow-900',\n              'hover:bg-yellow-600',\n              'focus:outline-none focus:ring-2 focus:ring-yellow-500',\n              'disabled:opacity-50 disabled:cursor-not-allowed'\n            )}\n          >\n            Save\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n});\n","import { memo } from 'react';\nimport { cn } from '../../utils';\n\nexport interface AskAboutOverlayProps {\n  /** Whether the overlay is visible */\n  visible: boolean;\n  /** Progress of the long press (0-1) */\n  progress: number;\n  /** Position of the overlay */\n  position: { x: number; y: number } | null;\n  /** Size of the progress indicator */\n  size?: number;\n  /** Custom className */\n  className?: string;\n}\n\n/**\n * Visual feedback overlay shown during long-press for \"Ask About This\" feature.\n * Displays a circular progress indicator.\n */\nexport const AskAboutOverlay = memo(function AskAboutOverlay({\n  visible,\n  progress,\n  position,\n  size = 60,\n  className,\n}: AskAboutOverlayProps) {\n  if (!visible || !position) {\n    return null;\n  }\n\n  const strokeWidth = 4;\n  const radius = (size - strokeWidth) / 2;\n  const circumference = 2 * Math.PI * radius;\n  const strokeDashoffset = circumference * (1 - progress);\n\n  return (\n    <div\n      className={cn(\n        'ask-about-overlay',\n        'fixed pointer-events-none z-[9999]',\n        className\n      )}\n      style={{\n        left: position.x - size / 2,\n        top: position.y - size / 2,\n      }}\n    >\n      <svg\n        width={size}\n        height={size}\n        viewBox={`0 0 ${size} ${size}`}\n        className=\"transform -rotate-90\"\n      >\n        {/* Background circle */}\n        <circle\n          cx={size / 2}\n          cy={size / 2}\n          r={radius}\n          fill=\"rgba(0, 0, 0, 0.3)\"\n          stroke=\"rgba(255, 255, 255, 0.3)\"\n          strokeWidth={strokeWidth}\n        />\n        {/* Progress circle */}\n        <circle\n          cx={size / 2}\n          cy={size / 2}\n          r={radius}\n          fill=\"none\"\n          stroke=\"#3b82f6\"\n          strokeWidth={strokeWidth}\n          strokeLinecap=\"round\"\n          strokeDasharray={circumference}\n          strokeDashoffset={strokeDashoffset}\n          className=\"transition-[stroke-dashoffset] duration-75 ease-linear\"\n        />\n      </svg>\n      {/* Center icon */}\n      <div\n        className=\"absolute inset-0 flex items-center justify-center\"\n        style={{ color: progress >= 1 ? '#22c55e' : 'white' }}\n      >\n        {progress >= 1 ? (\n          <svg\n            width=\"24\"\n            height=\"24\"\n            viewBox=\"0 0 24 24\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            strokeWidth=\"2\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n          >\n            <polyline points=\"20 6 9 17 4 12\" />\n          </svg>\n        ) : (\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          >\n            <circle cx=\"12\" cy=\"12\" r=\"10\" />\n            <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n            <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n          </svg>\n        )}\n      </div>\n    </div>\n  );\n});\n","import { memo, useCallback, useState, useRef, useEffect } from 'react';\nimport { cn } from '../../utils';\n\nexport interface AskAboutTriggerProps {\n  /** Position to display the trigger */\n  position: { x: number; y: number };\n  /** Callback when ask about is confirmed */\n  onConfirm: () => void;\n  /** Callback when cancelled */\n  onCancel: () => void;\n  /** Whether to show the trigger */\n  visible: boolean;\n  /** Auto-hide delay in ms (0 = no auto-hide) */\n  autoHideDelay?: number;\n  /** Custom className */\n  className?: string;\n}\n\n/**\n * Confirmation UI shown after long-press completes.\n * Provides buttons to confirm or cancel the \"Ask About This\" action.\n */\nexport const AskAboutTrigger = memo(function AskAboutTrigger({\n  position,\n  onConfirm,\n  onCancel,\n  visible,\n  autoHideDelay = 5000,\n  className,\n}: AskAboutTriggerProps) {\n  const [adjustedPosition, setAdjustedPosition] = useState(position);\n  const triggerRef = useRef<HTMLDivElement>(null);\n\n  // Adjust position to stay within viewport\n  useEffect(() => {\n    if (!visible || !triggerRef.current) return;\n\n    const rect = triggerRef.current.getBoundingClientRect();\n    const padding = 10;\n    let { x, y } = position;\n\n    // Adjust horizontal position\n    if (x + rect.width / 2 > window.innerWidth - padding) {\n      x = window.innerWidth - rect.width / 2 - padding;\n    }\n    if (x - rect.width / 2 < padding) {\n      x = rect.width / 2 + padding;\n    }\n\n    // Adjust vertical position (show above if too close to bottom)\n    if (y + rect.height > window.innerHeight - padding) {\n      y = position.y - rect.height - 20;\n    }\n\n    setAdjustedPosition({ x, y });\n  }, [position, visible]);\n\n  // Auto-hide after delay\n  useEffect(() => {\n    if (!visible || autoHideDelay === 0) return;\n\n    const timer = setTimeout(onCancel, autoHideDelay);\n    return () => clearTimeout(timer);\n  }, [visible, autoHideDelay, onCancel]);\n\n  const handleConfirm = useCallback(\n    (e: React.MouseEvent) => {\n      e.stopPropagation();\n      onConfirm();\n    },\n    [onConfirm]\n  );\n\n  const handleCancel = useCallback(\n    (e: React.MouseEvent) => {\n      e.stopPropagation();\n      onCancel();\n    },\n    [onCancel]\n  );\n\n  if (!visible) {\n    return null;\n  }\n\n  return (\n    <div\n      ref={triggerRef}\n      className={cn(\n        'ask-about-trigger',\n        'fixed z-[9999]',\n        'bg-white dark:bg-gray-800 rounded-lg shadow-lg',\n        'border border-gray-200 dark:border-gray-700',\n        'p-2 flex items-center gap-2',\n        'animate-in fade-in zoom-in-95 duration-150',\n        className\n      )}\n      style={{\n        left: adjustedPosition.x,\n        top: adjustedPosition.y,\n        transform: 'translate(-50%, 0)',\n      }}\n    >\n      <span className=\"text-sm text-gray-600 dark:text-gray-300 px-2\">\n        Ask about this?\n      </span>\n      <button\n        onClick={handleConfirm}\n        className={cn(\n          'px-3 py-1.5 rounded-md text-sm font-medium',\n          'bg-blue-500 text-white hover:bg-blue-600',\n          'focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2',\n          'transition-colors'\n        )}\n      >\n        Ask\n      </button>\n      <button\n        onClick={handleCancel}\n        className={cn(\n          'px-3 py-1.5 rounded-md text-sm font-medium',\n          'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300',\n          'hover:bg-gray-200 dark:hover:bg-gray-600',\n          'focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2',\n          'transition-colors'\n        )}\n      >\n        Cancel\n      </button>\n    </div>\n  );\n});\n","import { memo, useMemo, useCallback } from 'react';\nimport { useStudentStore, useViewerStore } from '../../hooks';\nimport { cn } from '../../utils';\n\nexport interface MinimapProps {\n  /** Display variant */\n  variant?: 'sidebar' | 'floating';\n  /** Position for floating variant */\n  floatingPosition?: 'left' | 'right';\n  /** Maximum height in pixels */\n  maxHeight?: number;\n  /** Whether to show page numbers */\n  showPageNumbers?: boolean;\n  /** Callback when a page is clicked */\n  onPageClick?: (pageNumber: number) => void;\n  /** Custom className */\n  className?: string;\n}\n\ntype PageStatus = 'current' | 'visited' | 'bookmarked' | 'unvisited';\n\ninterface PageIndicatorProps {\n  pageNumber: number;\n  status: PageStatus;\n  isBookmarked: boolean;\n  onClick: () => void;\n  showNumber: boolean;\n  compact: boolean;\n}\n\nconst PageIndicator = memo(function PageIndicator({\n  pageNumber,\n  status,\n  isBookmarked,\n  onClick,\n  showNumber,\n  compact,\n}: PageIndicatorProps) {\n  const getStatusColor = () => {\n    if (status === 'current') return 'bg-blue-500';\n    if (isBookmarked) return 'bg-yellow-400';\n    if (status === 'visited') return 'bg-green-400';\n    return 'bg-gray-200 dark:bg-gray-700';\n  };\n\n  return (\n    <button\n      onClick={onClick}\n      className={cn(\n        'minimap-page-indicator',\n        'relative rounded-sm transition-all duration-150',\n        'hover:ring-2 hover:ring-blue-300 hover:ring-offset-1',\n        'focus:outline-none focus:ring-2 focus:ring-blue-500',\n        compact ? 'w-2 h-3' : 'w-4 h-5',\n        getStatusColor(),\n        status === 'current' && 'ring-2 ring-blue-600 ring-offset-1'\n      )}\n      title={`Page ${pageNumber}${isBookmarked ? ' (bookmarked)' : ''}`}\n      aria-label={`Go to page ${pageNumber}`}\n    >\n      {isBookmarked && !compact && (\n        <div className=\"absolute -top-1 -right-1 w-2 h-2 bg-yellow-500 rounded-full border border-white\" />\n      )}\n      {showNumber && !compact && (\n        <span className=\"absolute inset-0 flex items-center justify-center text-[8px] font-medium text-white\">\n          {pageNumber}\n        </span>\n      )}\n    </button>\n  );\n});\n\n/**\n * Visual minimap showing reading progress and navigation.\n */\nexport const Minimap = memo(function Minimap({\n  variant = 'sidebar',\n  floatingPosition = 'right',\n  maxHeight = 300,\n  showPageNumbers = false,\n  onPageClick,\n  className,\n}: MinimapProps) {\n  // Store state\n  const visitedPages = useStudentStore((s) => s.visitedPages);\n  const bookmarks = useStudentStore((s) => s.bookmarks);\n  const currentPage = useViewerStore((s) => s.currentPage);\n  const numPages = useViewerStore((s) => s.numPages);\n  const goToPage = useViewerStore((s) => s.goToPage);\n\n  // Create set of bookmarked pages for quick lookup\n  const bookmarkedPages = useMemo(() => {\n    return new Set(bookmarks.map((b) => b.pageNumber));\n  }, [bookmarks]);\n\n  // Determine if we should use compact mode based on page count\n  const compact = numPages > 50;\n\n  const handlePageClick = useCallback(\n    (pageNumber: number) => {\n      goToPage(pageNumber);\n      onPageClick?.(pageNumber);\n    },\n    [goToPage, onPageClick]\n  );\n\n  const getPageStatus = useCallback(\n    (pageNumber: number): PageStatus => {\n      if (pageNumber === currentPage) return 'current';\n      if (bookmarkedPages.has(pageNumber)) return 'bookmarked';\n      if (visitedPages.has(pageNumber)) return 'visited';\n      return 'unvisited';\n    },\n    [currentPage, visitedPages, bookmarkedPages]\n  );\n\n  // Generate page indicators\n  const pageIndicators = useMemo(() => {\n    const pages = [];\n    for (let i = 1; i <= numPages; i++) {\n      pages.push(\n        <PageIndicator\n          key={i}\n          pageNumber={i}\n          status={getPageStatus(i)}\n          isBookmarked={bookmarkedPages.has(i)}\n          onClick={() => handlePageClick(i)}\n          showNumber={showPageNumbers}\n          compact={compact}\n        />\n      );\n    }\n    return pages;\n  }, [numPages, getPageStatus, bookmarkedPages, handlePageClick, showPageNumbers, compact]);\n\n  // Progress stats\n  const visitedCount = visitedPages.size;\n  const progressPercentage = numPages > 0 ? Math.round((visitedCount / numPages) * 100) : 0;\n\n  if (numPages === 0) {\n    return null;\n  }\n\n  const content = (\n    <>\n      {/* Progress bar */}\n      <div className=\"mb-3\">\n        <div className=\"flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 mb-1\">\n          <span>Progress</span>\n          <span>{progressPercentage}%</span>\n        </div>\n        <div className=\"h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden\">\n          <div\n            className=\"h-full bg-green-500 rounded-full transition-all duration-300\"\n            style={{ width: `${progressPercentage}%` }}\n          />\n        </div>\n      </div>\n\n      {/* Page indicators */}\n      <div\n        className={cn(\n          'flex flex-wrap gap-1 overflow-y-auto',\n          compact ? 'gap-0.5' : 'gap-1'\n        )}\n        style={{ maxHeight: maxHeight - 60 }}\n      >\n        {pageIndicators}\n      </div>\n\n      {/* Legend */}\n      <div className=\"mt-3 pt-2 border-t border-gray-200 dark:border-gray-700\">\n        <div className=\"flex flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400\">\n          <div className=\"flex items-center gap-1\">\n            <div className=\"w-2 h-2 rounded-sm bg-blue-500\" />\n            <span>Current</span>\n          </div>\n          <div className=\"flex items-center gap-1\">\n            <div className=\"w-2 h-2 rounded-sm bg-green-400\" />\n            <span>Visited</span>\n          </div>\n          <div className=\"flex items-center gap-1\">\n            <div className=\"w-2 h-2 rounded-sm bg-yellow-400\" />\n            <span>Bookmarked</span>\n          </div>\n        </div>\n      </div>\n\n      {/* Stats */}\n      <div className=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">\n        {visitedCount} of {numPages} pages visited\n      </div>\n    </>\n  );\n\n  if (variant === 'floating') {\n    return (\n      <div\n        className={cn(\n          'minimap minimap-floating',\n          'fixed z-40',\n          'bg-white dark:bg-gray-800',\n          'rounded-lg shadow-lg',\n          'border border-gray-200 dark:border-gray-700',\n          'p-3 w-48',\n          floatingPosition === 'right' ? 'right-4' : 'left-4',\n          'top-1/2 -translate-y-1/2',\n          className\n        )}\n        style={{ maxHeight }}\n      >\n        <h3 className=\"text-sm font-semibold text-gray-700 dark:text-gray-200 mb-2\">\n          Reading Progress\n        </h3>\n        {content}\n      </div>\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        'minimap minimap-sidebar',\n        'p-3',\n        className\n      )}\n      style={{ maxHeight }}\n    >\n      {content}\n    </div>\n  );\n});\n","import { memo, useEffect, useState, useRef, useCallback } from 'react';\nimport type { PDFPageProxy } from 'pdfjs-dist';\nimport { usePDFViewer, usePDFViewerStores } from '../../hooks';\nimport { cn } from '../../utils';\n\nexport interface PDFThumbnailNavProps {\n  /** Scale for thumbnails (default: 0.15) */\n  thumbnailScale?: number;\n  /** Orientation of the thumbnail strip */\n  orientation?: 'horizontal' | 'vertical';\n  /** Maximum number of thumbnails visible at once */\n  maxVisible?: number;\n  /** Custom class name */\n  className?: string;\n  /** Callback when a thumbnail is clicked */\n  onThumbnailClick?: (page: number) => void;\n  /** Gap between thumbnails in pixels (default: 8) */\n  gap?: number;\n  /** Show page numbers below thumbnails (default: true) */\n  showPageNumbers?: boolean;\n}\n\ninterface ThumbnailData {\n  pageNumber: number;\n  canvas: HTMLCanvasElement | null;\n  width: number;\n  height: number;\n}\n\n// Default page dimensions (US Letter)\nconst DEFAULT_WIDTH = 612;\nconst DEFAULT_HEIGHT = 792;\n\n/**\n * PDFThumbnailNav provides a navigable strip of PDF page thumbnails.\n * Syncs with the current PDF viewer via store subscription.\n *\n * Features:\n * - Virtualized rendering (only visible thumbnails are rendered)\n * - Auto-scrolls to keep current page visible\n * - Click to navigate to page\n * - Horizontal or vertical orientation\n */\nexport const PDFThumbnailNav = memo(function PDFThumbnailNav({\n  thumbnailScale = 0.15,\n  orientation = 'vertical',\n  maxVisible = 10,\n  className,\n  onThumbnailClick,\n  gap = 8,\n  showPageNumbers = true,\n}: PDFThumbnailNavProps) {\n  const { document, numPages, currentPage } = usePDFViewer();\n  const { viewerStore } = usePDFViewerStores();\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const [thumbnails, setThumbnails] = useState<Map<number, ThumbnailData>>(new Map());\n  const [visibleRange, setVisibleRange] = useState({ start: 1, end: maxVisible });\n  const renderQueueRef = useRef<Set<number>>(new Set());\n  const pageCache = useRef<Map<number, PDFPageProxy>>(new Map());\n\n  // Calculate thumbnail dimensions\n  const thumbnailWidth = Math.floor(DEFAULT_WIDTH * thumbnailScale);\n  const thumbnailHeight = Math.floor(DEFAULT_HEIGHT * thumbnailScale);\n\n  // Update visible range based on scroll position\n  const updateVisibleRange = useCallback(() => {\n    if (!containerRef.current || numPages === 0) return;\n\n    const container = containerRef.current;\n    const isHorizontal = orientation === 'horizontal';\n\n    const scrollPosition = isHorizontal ? container.scrollLeft : container.scrollTop;\n    const viewportSize = isHorizontal ? container.clientWidth : container.clientHeight;\n    const itemSize = (isHorizontal ? thumbnailWidth : thumbnailHeight) + gap;\n\n    const firstVisible = Math.max(1, Math.floor(scrollPosition / itemSize) + 1);\n    const visibleCount = Math.ceil(viewportSize / itemSize) + 2; // Buffer\n    const lastVisible = Math.min(numPages, firstVisible + visibleCount);\n\n    setVisibleRange({ start: firstVisible, end: lastVisible });\n  }, [numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);\n\n  // Set up scroll listener\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container) return;\n\n    const handleScroll = () => {\n      requestAnimationFrame(updateVisibleRange);\n    };\n\n    container.addEventListener('scroll', handleScroll, { passive: true });\n    updateVisibleRange();\n\n    return () => container.removeEventListener('scroll', handleScroll);\n  }, [updateVisibleRange]);\n\n  // Render thumbnails for visible pages\n  useEffect(() => {\n    if (!document) {\n      setThumbnails(new Map());\n      pageCache.current.clear();\n      return;\n    }\n\n    const renderThumbnails = async () => {\n      const newThumbnails = new Map(thumbnails);\n      const pagesToRender: number[] = [];\n\n      // Queue pages that need rendering\n      for (let i = visibleRange.start; i <= visibleRange.end; i++) {\n        if (!newThumbnails.has(i) && !renderQueueRef.current.has(i)) {\n          pagesToRender.push(i);\n          renderQueueRef.current.add(i);\n        }\n      }\n\n      // Render each page\n      for (const pageNum of pagesToRender) {\n        try {\n          let page = pageCache.current.get(pageNum);\n          if (!page) {\n            page = await document.getPage(pageNum);\n            pageCache.current.set(pageNum, page);\n          }\n\n          const viewport = page.getViewport({ scale: thumbnailScale });\n\n          // Create canvas for thumbnail\n          const canvas = window.document.createElement('canvas');\n          canvas.width = Math.floor(viewport.width);\n          canvas.height = Math.floor(viewport.height);\n\n          const ctx = canvas.getContext('2d');\n          if (ctx) {\n            await page.render({\n              canvasContext: ctx,\n              viewport,\n            }).promise;\n\n            newThumbnails.set(pageNum, {\n              pageNumber: pageNum,\n              canvas,\n              width: canvas.width,\n              height: canvas.height,\n            });\n          }\n        } catch (error) {\n          // Silently ignore errors from document switching/destruction\n          const errorMessage = error instanceof Error ? error.message : String(error);\n          const isDocumentDestroyed =\n            errorMessage.includes('destroyed') ||\n            errorMessage.includes('sendWithStream') ||\n            errorMessage.includes('sendWithPromise') ||\n            errorMessage.includes('Cannot read properties of null');\n          if (!isDocumentDestroyed) {\n            console.error(`Failed to render thumbnail for page ${pageNum}:`, error);\n          }\n        } finally {\n          renderQueueRef.current.delete(pageNum);\n        }\n      }\n\n      if (pagesToRender.length > 0) {\n        setThumbnails(newThumbnails);\n      }\n    };\n\n    renderThumbnails();\n  }, [document, visibleRange, thumbnailScale, thumbnails]);\n\n  // Auto-scroll to keep current page visible\n  useEffect(() => {\n    if (!containerRef.current || numPages === 0) return;\n\n    const container = containerRef.current;\n    const isHorizontal = orientation === 'horizontal';\n    const itemSize = (isHorizontal ? thumbnailWidth : thumbnailHeight) + gap;\n    const targetPosition = (currentPage - 1) * itemSize;\n\n    const scrollPosition = isHorizontal ? container.scrollLeft : container.scrollTop;\n    const viewportSize = isHorizontal ? container.clientWidth : container.clientHeight;\n\n    // Check if current page is visible\n    if (targetPosition < scrollPosition || targetPosition + itemSize > scrollPosition + viewportSize) {\n      // Center the current page in the viewport\n      const targetScroll = targetPosition - (viewportSize - itemSize) / 2;\n\n      container.scrollTo({\n        [isHorizontal ? 'left' : 'top']: Math.max(0, targetScroll),\n        behavior: 'smooth',\n      });\n    }\n  }, [currentPage, numPages, orientation, thumbnailWidth, thumbnailHeight, gap]);\n\n  // Handle thumbnail click\n  const handleThumbnailClick = useCallback((pageNum: number) => {\n    onThumbnailClick?.(pageNum);\n    viewerStore.getState().requestScrollToPage(pageNum, 'smooth');\n  }, [onThumbnailClick, viewerStore]);\n\n  if (!document || numPages === 0) {\n    return (\n      <div\n        className={cn(\n          'pdf-thumbnail-nav',\n          'flex items-center justify-center',\n          'bg-gray-100 dark:bg-gray-800',\n          'text-gray-500 dark:text-gray-400',\n          'text-sm',\n          className\n        )}\n        style={{\n          width: orientation === 'vertical' ? thumbnailWidth + 24 : '100%',\n          height: orientation === 'horizontal' ? thumbnailHeight + 40 : '100%',\n        }}\n      >\n        No document\n      </div>\n    );\n  }\n\n  const isHorizontal = orientation === 'horizontal';\n  const totalSize = numPages * ((isHorizontal ? thumbnailWidth : thumbnailHeight) + gap) - gap;\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        'pdf-thumbnail-nav',\n        'overflow-auto',\n        'bg-gray-100 dark:bg-gray-800',\n        isHorizontal ? 'flex-row' : 'flex-col',\n        className\n      )}\n      style={{\n        ...(isHorizontal\n          ? { overflowX: 'auto', overflowY: 'hidden' }\n          : { overflowX: 'hidden', overflowY: 'auto' }),\n      }}\n    >\n      {/* Scroll container */}\n      <div\n        className={cn(\n          'relative',\n          isHorizontal ? 'flex flex-row items-center' : 'flex flex-col items-center'\n        )}\n        style={{\n          [isHorizontal ? 'width' : 'height']: totalSize,\n          [isHorizontal ? 'minWidth' : 'minHeight']: totalSize,\n          padding: gap / 2,\n          gap,\n        }}\n      >\n        {/* Render visible thumbnails */}\n        {Array.from({ length: numPages }, (_, i) => i + 1).map((pageNum) => {\n          const thumbnail = thumbnails.get(pageNum);\n          const isActive = pageNum === currentPage;\n          const isVisible = pageNum >= visibleRange.start && pageNum <= visibleRange.end;\n\n          return (\n            <div\n              key={pageNum}\n              className={cn(\n                'pdf-thumbnail',\n                'flex-shrink-0 cursor-pointer transition-all duration-200',\n                'border-2 rounded shadow-sm hover:shadow-md',\n                isActive\n                  ? 'border-blue-500 ring-2 ring-blue-200 dark:ring-blue-800'\n                  : 'border-gray-300 dark:border-gray-600 hover:border-blue-400'\n              )}\n              style={{\n                width: thumbnailWidth,\n                height: thumbnailHeight + (showPageNumbers ? 24 : 0),\n              }}\n              onClick={() => handleThumbnailClick(pageNum)}\n              role=\"button\"\n              tabIndex={0}\n              aria-label={`Go to page ${pageNum}`}\n              aria-current={isActive ? 'page' : undefined}\n              onKeyDown={(e) => {\n                if (e.key === 'Enter' || e.key === ' ') {\n                  e.preventDefault();\n                  handleThumbnailClick(pageNum);\n                }\n              }}\n            >\n              {/* Thumbnail image */}\n              <div\n                className=\"relative bg-white dark:bg-gray-700\"\n                style={{\n                  width: thumbnailWidth,\n                  height: thumbnailHeight,\n                }}\n              >\n                {isVisible && thumbnail?.canvas ? (\n                  <img\n                    src={thumbnail.canvas.toDataURL()}\n                    alt={`Page ${pageNum}`}\n                    className=\"w-full h-full object-contain\"\n                    loading=\"lazy\"\n                  />\n                ) : (\n                  <div className=\"absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-xs\">\n                    {pageNum}\n                  </div>\n                )}\n              </div>\n\n              {/* Page number label */}\n              {showPageNumbers && (\n                <div\n                  className={cn(\n                    'text-center text-xs py-1',\n                    'bg-gray-50 dark:bg-gray-700',\n                    isActive\n                      ? 'text-blue-600 dark:text-blue-400 font-medium'\n                      : 'text-gray-600 dark:text-gray-400'\n                  )}\n                >\n                  {pageNum}\n                </div>\n              )}\n            </div>\n          );\n        })}\n      </div>\n    </div>\n  );\n});\n","import { Component, type ReactNode, type ErrorInfo } from 'react';\nimport { cn } from '../../utils';\n\nexport interface PDFErrorBoundaryProps {\n  /** Child components to render */\n  children: ReactNode;\n  /** Custom fallback UI */\n  fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n  /** Callback when an error is caught */\n  onError?: (error: Error, errorInfo: ErrorInfo) => void;\n  /** Whether to show the default error UI */\n  showDefaultUI?: boolean;\n  className?: string;\n}\n\ninterface PDFErrorBoundaryState {\n  hasError: boolean;\n  error: Error | null;\n}\n\nexport class PDFErrorBoundary extends Component<PDFErrorBoundaryProps, PDFErrorBoundaryState> {\n  constructor(props: PDFErrorBoundaryProps) {\n    super(props);\n    this.state = { hasError: false, error: null };\n  }\n\n  static getDerivedStateFromError(error: Error): PDFErrorBoundaryState {\n    return { hasError: true, error };\n  }\n\n  componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n    this.props.onError?.(error, errorInfo);\n\n    // Log to console for debugging\n    console.error('PDFErrorBoundary caught an error:', error);\n    console.error('Component stack:', errorInfo.componentStack);\n  }\n\n  handleReset = (): void => {\n    this.setState({ hasError: false, error: null });\n  };\n\n  render(): ReactNode {\n    const { hasError, error } = this.state;\n    const { children, fallback, showDefaultUI = true, className } = this.props;\n\n    if (hasError && error) {\n      // Custom fallback UI\n      if (fallback) {\n        if (typeof fallback === 'function') {\n          return fallback(error, this.handleReset);\n        }\n        return fallback;\n      }\n\n      // Default error UI\n      if (showDefaultUI) {\n        return (\n          <DefaultErrorUI\n            error={error}\n            onReset={this.handleReset}\n            className={className}\n          />\n        );\n      }\n\n      // No UI - return null\n      return null;\n    }\n\n    return children;\n  }\n}\n\ninterface DefaultErrorUIProps {\n  error: Error;\n  onReset: () => void;\n  className?: string;\n}\n\nfunction DefaultErrorUI({ error, onReset, className }: DefaultErrorUIProps) {\n  const isPDFError = error.message.includes('PDF') || error.message.includes('pdf');\n  const isNetworkError =\n    error.message.includes('fetch') ||\n    error.message.includes('network') ||\n    error.message.includes('Failed to load');\n\n  let title = 'Something went wrong';\n  let description = error.message;\n  let icon = (\n    <svg className=\"w-12 h-12 text-red-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth={2}\n        d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n      />\n    </svg>\n  );\n\n  if (isPDFError) {\n    title = 'Unable to load PDF';\n    description = 'The PDF file could not be loaded. It may be corrupted or in an unsupported format.';\n    icon = (\n      <svg className=\"w-12 h-12 text-red-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <path\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          strokeWidth={2}\n          d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n        />\n      </svg>\n    );\n  } else if (isNetworkError) {\n    title = 'Network error';\n    description = 'Unable to fetch the PDF file. Please check your internet connection and try again.';\n    icon = (\n      <svg className=\"w-12 h-12 text-red-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <path\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          strokeWidth={2}\n          d=\"M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414\"\n        />\n      </svg>\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        'pdf-error-boundary',\n        'flex flex-col items-center justify-center',\n        'min-h-[300px] p-8',\n        'bg-gray-50 dark:bg-gray-900',\n        'text-center',\n        className\n      )}\n    >\n      {icon}\n\n      <h2 className=\"mt-4 text-xl font-semibold text-gray-900 dark:text-gray-100\">\n        {title}\n      </h2>\n\n      <p className=\"mt-2 text-sm text-gray-600 dark:text-gray-400 max-w-md\">\n        {description}\n      </p>\n\n      <details className=\"mt-4 text-left max-w-md w-full\">\n        <summary className=\"cursor-pointer text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\">\n          Technical details\n        </summary>\n        <pre className=\"mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto\">\n          {error.stack || error.message}\n        </pre>\n      </details>\n\n      <div className=\"mt-6 flex gap-3\">\n        <button\n          onClick={onReset}\n          className={cn(\n            'px-4 py-2 rounded-lg font-medium',\n            'bg-blue-600 text-white',\n            'hover:bg-blue-700',\n            'focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2',\n            'transition-colors'\n          )}\n        >\n          Try again\n        </button>\n\n        <button\n          onClick={() => window.location.reload()}\n          className={cn(\n            'px-4 py-2 rounded-lg font-medium',\n            'bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-200',\n            'hover:bg-gray-300 dark:hover:bg-gray-600',\n            'focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2',\n            'transition-colors'\n          )}\n        >\n          Reload page\n        </button>\n      </div>\n    </div>\n  );\n}\n\n// Helper component for wrapping PDF viewers with error boundary\nexport interface WithErrorBoundaryProps extends Omit<PDFErrorBoundaryProps, 'children'> {\n  component: ReactNode;\n}\n\nexport function withErrorBoundary({ component, ...props }: WithErrorBoundaryProps): ReactNode {\n  return <PDFErrorBoundary {...props}>{component}</PDFErrorBoundary>;\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { useStore } from 'zustand';\nimport type { PDFPageProxy } from 'pdfjs-dist';\nimport { PDFPage } from '../PDFPage';\nimport type { PageBBoxData, BBoxIndex } from '../../types/bbox';\nimport type { NarrationStoreApi } from '../../store/narration-store';\nimport { usePDFViewer } from '../../hooks';\nimport { CameraView } from './CameraView';\nimport { CinemaLayer } from './CinemaLayer';\nimport { GhostReferenceOverlay } from './GhostReferenceOverlay';\nimport { LabelOverlay } from './LabelOverlay';\nimport { CalloutLabelOverlay } from './CalloutLabelOverlay';\nimport { SubtitleBar } from './SubtitleBar';\nimport { StoryboardEngine } from '../../director/storyboard-engine';\nimport {\n  directStoryboard,\n  type LlmConfig,\n} from '../../director/llm-director';\nimport {\n  matchChunkToBlock,\n  storyboardFromMatch,\n  type EmbeddingProvider,\n} from '../../director/embedding-fallback';\nimport { StoryboardSchema } from '../../director/storyboard-schema';\nimport type { Storyboard } from '../../types/storyboard';\n\n/**\n * Input passed to a consumer-supplied `storyboardProvider`. Gives the\n * provider everything the built-in director already has access to, so\n * the consumer can decide how much context to forward to their own\n * endpoint (typically: just `chunk` + `pageNumber`, since bbox is\n * usually cached server-side).\n */\nexport interface StoryboardProviderInput {\n  chunk: string;\n  pageNumber: number;\n  /** The current page's bbox data — included in case the provider wants\n   *  to forward it, though usually the provider's backend already has\n   *  this cached. */\n  page: PageBBoxData;\n  /** Last few chunks the tutor has spoken, for conversational context. */\n  history: ReadonlyArray<{\n    text: string;\n    pageNumber: number;\n    timestamp: number;\n  }>;\n  /** AbortSignal — if the consumer's fetch supports it, wire it up so\n   *  a newer chunk cancels a stale in-flight request. */\n  signal: AbortSignal;\n}\n\nexport interface TutorModeContainerProps {\n  pageNumber: number;\n  bboxData: PageBBoxData[];\n  narrationStore: NarrationStoreApi;\n  scale: number;\n  rotation?: number;\n  /** Reactive chunk from the tutor (updates as she speaks) */\n  currentChunk?: string | null;\n  /** LLM endpoint configuration used by the built-in director. */\n  llm?: LlmConfig;\n  /**\n   * Consumer-owned director. When provided, this is called per chunk\n   * INSTEAD OF `directStoryboard(llm, …)`. Return a storyboard matching\n   * `StoryboardSchema` (or `null` to skip the chunk). The library still\n   * validates the return value, runs salvage (range clamp, overlay-\n   * presence), and emits debug events, so DebugLog telemetry is\n   * identical to the built-in path.\n   *\n   * Use this when your backend owns the system prompt + bbox context\n   * (e.g. a fine-tuned director endpoint) and you want to iterate on\n   * prompt/model choices without a library upgrade.\n   *\n   * Priority: if BOTH `storyboardProvider` and `llm` are set, the\n   * provider wins and `llm` is ignored.\n   *\n   * Added in v0.5.0.\n   */\n  storyboardProvider?: (input: StoryboardProviderInput) => Promise<\n    Storyboard | null\n  >;\n  /** Milliseconds of no new chunks before the camera returns to fit-page */\n  idleTimeoutMs?: number;\n  /** LLM call timeout in ms. Default 30000 (Qwen3-32B and similar can take 5-15s). */\n  llmTimeoutMs?: number;\n  /** Optional embedding provider for fallback matching when the LLM fails */\n  embeddingProvider?: EmbeddingProvider;\n  /** Show subtitle bar with the current chunk text (default: true) */\n  showSubtitles?: boolean;\n  /**\n   * Show the \"Reset view\" button (default: true). Clicking it clears all\n   * overlays and returns the camera to fit-page. If `onExitTutorMode` is\n   * also provided, it runs after the reset — useful when the host app\n   * wants the same button to also leave tutor mode entirely.\n   */\n  showExitButton?: boolean;\n  /**\n   * Optional callback fired AFTER the engine's resetVisuals. Provide this\n   * only if the host wants the reset button to also leave tutor mode /\n   * navigate away. Omit it for a pure \"reset the visuals\" behaviour.\n   */\n  onExitTutorMode?: () => void;\n  /**\n   * Minimum hold time (ms) for every overlay, regardless of the\n   * `duration_ms` the LLM specifies. Short LLM-emitted durations (600-1200ms)\n   * flash past too quickly to read; bump this for narration-paired UX.\n   * Default: 3500ms.\n   */\n  minOverlayDurationMs?: number;\n  /**\n   * Background colour of the container surround (visible around the PDF when\n   * the viewport is larger than the page fit). Default: `#ffffff`. Pass a\n   * dark value for dark-themed hosts.\n   */\n  backgroundColor?: string;\n  /**\n   * Optional content to render while the PDF document/page is still loading.\n   * Receives the loading stage so the host can show a spinner, a skeleton,\n   * or a custom brand. If omitted, a minimal default spinner is rendered on\n   * the `backgroundColor` surround.\n   */\n  loadingComponent?: React.ReactNode;\n  /**\n   * Fired when the underlying viewer's page changes from any source — the\n   * agent API (`agentTools.goToPage / nextPage / previousPage`), the sidebar\n   * (bookmarks, thumbnails, search), or a programmatic\n   * `useViewerStore().goToPage` call. Use this to keep your own\n   * `pageNumber` state (the controlled prop you pass in) in lockstep with\n   * the viewer, so agent-driven navigation actually moves the rendered\n   * page and downstream concerns (progress save, recap, etc.) see the\n   * right value.\n   *\n   * ```tsx\n   * const [currentPage, setCurrentPage] = useState(1);\n   * <TutorModeContainer\n   *   pageNumber={currentPage}\n   *   onPageChange={setCurrentPage}   // ← bidirectional sync\n   * />\n   * ```\n   *\n   * Added in v0.4.2.\n   */\n  onPageChange?: (page: number) => void;\n  className?: string;\n}\n\n/** Build a cross-page/block index from the raw bbox list. */\nexport function buildBBoxIndex(bboxData: PageBBoxData[]): BBoxIndex {\n  const byPage = new Map<number, PageBBoxData>();\n  const blockById = new Map<\n    string,\n    { block: PageBBoxData['blocks'][number]; pageNumber: number }\n  >();\n  const crossPageFigures: BBoxIndex['crossPageFigures'] = [];\n\n  for (const page of bboxData) {\n    byPage.set(page.page_number, page);\n    for (const block of page.blocks) {\n      blockById.set(block.block_id, { block, pageNumber: page.page_number });\n      if (\n        (block.type === 'figure' ||\n          block.type === 'figure_region' ||\n          block.type === 'caption') &&\n        typeof block.text === 'string' &&\n        block.text.length > 0\n      ) {\n        crossPageFigures.push({\n          block_id: block.block_id,\n          page: page.page_number,\n          type: block.type,\n          text: block.text,\n        });\n      }\n    }\n  }\n  return { byPage, blockById, crossPageFigures };\n}\n\nexport function TutorModeContainer({\n  pageNumber,\n  bboxData,\n  narrationStore,\n  scale,\n  rotation = 0,\n  currentChunk,\n  llm,\n  idleTimeoutMs = 5000,\n  llmTimeoutMs = 30000,\n  embeddingProvider,\n  showSubtitles = false,\n  showExitButton = true,\n  onExitTutorMode,\n  minOverlayDurationMs,\n  backgroundColor = '#ffffff',\n  loadingComponent,\n  onPageChange,\n  storyboardProvider,\n  className,\n}: TutorModeContainerProps) {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const index = useMemo(() => buildBBoxIndex(bboxData), [bboxData]);\n\n  const {\n    document,\n    currentPage: viewerCurrentPage,\n    numPages,\n    goToPage: viewerGoToPage,\n  } = usePDFViewer();\n  const [pageProxy, setPageProxy] = useState<PDFPageProxy | null>(null);\n  const [viewport, setViewport] = useState({ width: 800, height: 1000 });\n\n  // Subscribe to store state for re-renders\n  const camera = useStore(narrationStore, (s) => s.camera);\n  const activeOverlays = useStore(narrationStore, (s) => s.activeOverlays);\n\n  // Bidirectional sync between the controlled `pageNumber` prop and the\n  // internal viewer store's currentPage. Without this, the agent API's\n  // `goToPage` / `nextPage` / `previousPage` calls write to viewerStore\n  // but never reach the consumer's controlled state — the rendered page\n  // stays stuck while the agent thinks it moved.\n\n  // prop → viewerStore: whenever the consumer updates pageNumber, mirror\n  // it into the viewer store so agent-api reads the correct current page.\n  useEffect(() => {\n    if (numPages <= 0) return;                     // doc not yet loaded\n    if (pageNumber < 1 || pageNumber > numPages) return;\n    if (viewerCurrentPage === pageNumber) return;  // already in sync\n    viewerGoToPage(pageNumber);\n  }, [pageNumber, numPages, viewerCurrentPage, viewerGoToPage]);\n\n  // viewerStore → prop: when something else (agent nav, thumbnail click,\n  // programmatic store update) moves the viewer's page, bubble it up so\n  // the consumer can update its own state and re-pass pageNumber.\n  useEffect(() => {\n    if (!onPageChange) return;\n    if (viewerCurrentPage === pageNumber) return;\n    if (viewerCurrentPage < 1) return;\n    onPageChange(viewerCurrentPage);\n  }, [viewerCurrentPage, pageNumber, onPageChange]);\n\n  // Track viewport size for camera math\n  useEffect(() => {\n    if (!containerRef.current) return;\n    const el = containerRef.current;\n    const update = () =>\n      setViewport({ width: el.clientWidth, height: el.clientHeight });\n    update();\n    const ro = new ResizeObserver(update);\n    ro.observe(el);\n    return () => ro.disconnect();\n  }, []);\n\n  // Load the current PDF page proxy\n  useEffect(() => {\n    if (!document) {\n      setPageProxy(null);\n      return;\n    }\n    let cancelled = false;\n    document\n      .getPage(pageNumber)\n      .then((p) => {\n        if (!cancelled) setPageProxy(p);\n      })\n      .catch(() => {\n        if (!cancelled) setPageProxy(null);\n      });\n    return () => {\n      cancelled = true;\n    };\n  }, [document, pageNumber]);\n\n  // Keep narrationStore.currentPage in sync with the rendered page so the\n  // engine's resetVisuals can read the right page for fit-scale math.\n  useEffect(() => {\n    narrationStore.getState().setCurrentPage(pageNumber);\n  }, [pageNumber, narrationStore]);\n\n  // Initial fit-to-viewport: PDF is rendered at native scale=1; the camera\n  // applies the scale that fits it. We pick the smaller of width-fit and\n  // height-fit, with a tiny padding factor for breathing room.\n  useEffect(() => {\n    const page = index.byPage.get(pageNumber);\n    if (!page) return;\n    if (viewport.width === 0 || viewport.height === 0) return;\n    if (narrationStore.getState().activeOverlays.length > 0) return;\n    const fit =\n      Math.min(\n        viewport.width / page.page_dimensions.width,\n        viewport.height / page.page_dimensions.height,\n      ) * 0.95;\n    narrationStore.getState().setCamera({ scale: fit, x: 0, y: 0 });\n  }, [pageNumber, viewport, index, narrationStore]);\n\n  // Engine instance tied to bbox index + viewport\n  const engineRef = useRef<StoryboardEngine | null>(null);\n  useEffect(() => {\n    engineRef.current = new StoryboardEngine({\n      narrationStore,\n      bboxIndex: index,\n      getViewport: () => viewport,\n      minOverlayDurationMs,\n    });\n    // destroy() cancels BOTH pending step timers AND overlay removal\n    // timers. On iOS Safari `viewport` can change frequently (address-bar\n    // scroll animation), forcing this effect's cleanup. The old\n    // `cancelPending()` left overlay-removal timers alive, retaining\n    // closures holding `bboxIndex` across each recreation.\n    return () => engineRef.current?.destroy();\n  }, [narrationStore, index, viewport, minOverlayDurationMs]);\n\n  // React to currentChunk: debounce → call LLM → engine.execute\n  const abortRef = useRef<AbortController | null>(null);\n  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const lastChunkRef = useRef<string | null>(null);\n\n  useEffect(() => {\n    // Need either a consumer-supplied provider OR an LLM config —\n    // otherwise there's no director to turn chunks into storyboards.\n    if (!storyboardProvider && !llm) return;\n    if (!currentChunk || currentChunk === lastChunkRef.current) return;\n\n    if (debounceRef.current) clearTimeout(debounceRef.current);\n    debounceRef.current = setTimeout(async () => {\n      const chunk = currentChunk;\n      if (chunk === lastChunkRef.current) return;\n      lastChunkRef.current = chunk;\n\n      const page = index.byPage.get(pageNumber);\n      if (!page) return;\n\n      narrationStore.getState().pushChunkHistory({\n        text: chunk,\n        pageNumber,\n        timestamp: Date.now(),\n      });\n      narrationStore.getState().appendDebugEvent({\n        kind: 'chunk',\n        summary: `chunk → ${chunk.slice(0, 80)}${chunk.length > 80 ? '…' : ''}`,\n        payload: { chunk, pageNumber },\n      });\n\n      abortRef.current?.abort();\n      abortRef.current = new AbortController();\n\n      // Path A — consumer-owned director (priority).\n      if (storyboardProvider) {\n        narrationStore.getState().setLlmStatus('in-flight');\n        narrationStore.getState().appendDebugEvent({\n          kind: 'llm-request',\n          summary: `provider (page ${pageNumber}, ${page.blocks.length} blocks)`,\n          payload: {\n            via: 'storyboardProvider',\n            pageNumber,\n            blockCount: page.blocks.length,\n          },\n        });\n\n        try {\n          const raw = await storyboardProvider({\n            chunk,\n            pageNumber,\n            page,\n            history: narrationStore.getState().chunkHistory,\n            signal: abortRef.current.signal,\n          });\n\n          if (!raw) {\n            narrationStore.getState().setLlmStatus('idle');\n            narrationStore.getState().appendDebugEvent({\n              kind: 'note',\n              summary: 'provider returned null — no storyboard for this chunk',\n            });\n            return;\n          }\n\n          // Validate with the same schema the built-in director uses, so\n          // the consumer can't slip through a malformed storyboard that\n          // would crash the engine.\n          const parsed = StoryboardSchema.safeParse(raw);\n          if (!parsed.success) {\n            narrationStore.getState().setLlmStatus(\n              'failed',\n              parsed.error.message,\n            );\n            narrationStore.getState().appendDebugEvent({\n              kind: 'llm-error',\n              summary: `provider storyboard rejected by schema: ${parsed.error.issues[0]?.message ?? 'unknown'}`,\n              payload: { raw, error: parsed.error.message },\n            });\n            return;\n          }\n\n          const storyboard = parsed.data as Storyboard;\n          narrationStore.getState().setLlmStatus('idle');\n          narrationStore.getState().appendDebugEvent({\n            kind: 'llm-response',\n            summary: summariseStoryboard(storyboard),\n            payload: { via: 'storyboardProvider', storyboard },\n          });\n          engineRef.current?.execute(storyboard);\n          narrationStore.getState().appendDebugEvent({\n            kind: 'storyboard-execute',\n            summary: `engine executing ${storyboard.steps.length} steps`,\n            payload: storyboard.steps.map((s) => ({\n              at_ms: s.at_ms,\n              type: s.action.type,\n              target:\n                'target_block' in s.action\n                  ? s.action.target_block\n                  : undefined,\n            })),\n          });\n        } catch (e) {\n          if ((e as Error).name === 'AbortError') return;\n          narrationStore\n            .getState()\n            .setLlmStatus('failed', (e as Error).message);\n          narrationStore.getState().appendDebugEvent({\n            kind: 'llm-error',\n            summary: `provider threw: ${(e as Error).message.slice(0, 80)}`,\n            payload: e,\n          });\n        }\n        return;\n      }\n\n      // Path B — built-in director using the LLM config (legacy path,\n      // still fully supported).\n      if (!llm) return;\n\n      narrationStore.getState().setLlmStatus('in-flight');\n      narrationStore.getState().appendDebugEvent({\n        kind: 'llm-request',\n        summary: `LLM ${llm.model} (page ${pageNumber}, ${page.blocks.length} blocks)`,\n        payload: { model: llm.model, pageNumber, blockCount: page.blocks.length },\n      });\n\n      const result = await directStoryboard(llm, {\n        chunk,\n        pageNumber,\n        page,\n        index,\n        history: narrationStore.getState().chunkHistory,\n        camera: narrationStore.getState().camera,\n        activeOverlays: narrationStore.getState().activeOverlays,\n        signal: abortRef.current.signal,\n        timeoutMs: llmTimeoutMs,\n      });\n\n      if (result.storyboard) {\n        narrationStore.getState().setLlmStatus('idle');\n        narrationStore.getState().appendDebugEvent({\n          kind: 'llm-response',\n          summary: summariseStoryboard(result.storyboard),\n          payload: { raw: result.raw, storyboard: result.storyboard },\n        });\n        engineRef.current?.execute(result.storyboard);\n        narrationStore.getState().appendDebugEvent({\n          kind: 'storyboard-execute',\n          summary: `engine executing ${result.storyboard.steps.length} steps`,\n          payload: result.storyboard.steps.map((s) => ({\n            at_ms: s.at_ms,\n            type: s.action.type,\n            target:\n              'target_block' in s.action\n                ? s.action.target_block\n                : 'target' in s.action\n                  ? (s.action as { target?: string }).target\n                  : undefined,\n          })),\n        });\n      } else {\n        narrationStore\n          .getState()\n          .setLlmStatus('failed', result.error ?? 'unknown');\n        narrationStore.getState().appendDebugEvent({\n          kind: 'llm-error',\n          summary: `LLM failed: ${(result.error ?? 'unknown').slice(0, 80)}`,\n          payload: { error: result.error, raw: result.raw },\n        });\n        if (embeddingProvider) {\n          try {\n            const match = await matchChunkToBlock(chunk, page, embeddingProvider);\n            const fallbackSb = storyboardFromMatch(match, page);\n            narrationStore.getState().appendDebugEvent({\n              kind: 'fallback-fired',\n              summary: `embedding fallback → ${match?.block.block_id ?? 'no match'}`,\n              payload: { match, storyboard: fallbackSb },\n            });\n            engineRef.current?.execute(fallbackSb);\n          } catch (e) {\n            narrationStore.getState().appendDebugEvent({\n              kind: 'llm-error',\n              summary: `fallback also failed: ${(e as Error).message}`,\n              payload: e,\n            });\n          }\n        }\n      }\n    }, 200);\n\n    return () => {\n      if (debounceRef.current) clearTimeout(debounceRef.current);\n    };\n  }, [\n    currentChunk,\n    llm,\n    storyboardProvider,\n    index,\n    pageNumber,\n    narrationStore,\n    embeddingProvider,\n    llmTimeoutMs,\n  ]);\n\n  // Idle recovery\n  useEffect(() => {\n    if (!currentChunk) return;\n    const t = setTimeout(() => {\n      if (!engineRef.current) return;\n      const hist = narrationStore.getState().chunkHistory;\n      const latest = hist.length > 0 ? hist[hist.length - 1] : null;\n      if (!latest) return;\n      if (Date.now() - latest.timestamp < idleTimeoutMs) return;\n      engineRef.current.resetVisuals();\n    }, idleTimeoutMs + 100);\n    return () => clearTimeout(t);\n  }, [currentChunk, idleTimeoutMs, narrationStore]);\n\n  const page = index.byPage.get(pageNumber);\n  // The bbox `page_dimensions` are at the source DPI (e.g., 200), while\n  // pdfjs-dist's `getViewport({scale:1})` returns the page in PDF POINTS\n  // (72 DPI). To align the rendered canvas with the bbox coordinate space,\n  // we render at `dpi/72`. The `scale` prop is a quality multiplier on top.\n  const dpiScale = page ? page.page_dimensions.dpi / 72 : 1;\n  const rasterScale = dpiScale * (scale || 1);\n  const baseW = page ? page.page_dimensions.width * (scale || 1) : 0;\n  const baseH = page ? page.page_dimensions.height * (scale || 1) : 0;\n\n  const isReady = !!page && !!pageProxy;\n\n  return (\n    <div\n      ref={containerRef}\n      className={className}\n      style={{\n        position: 'relative',\n        width: '100%',\n        height: '100%',\n        overflow: 'hidden',\n        background: backgroundColor,\n      }}\n      data-role=\"tutor-mode-container\"\n      data-page-loaded={isReady ? 'true' : 'false'}\n    >\n      {showExitButton && isReady ? (\n        <button\n          onClick={() => {\n            engineRef.current?.resetVisuals();\n            onExitTutorMode?.();\n          }}\n          style={{\n            position: 'absolute',\n            top: 12,\n            right: 12,\n            zIndex: 60,\n            minHeight: 40,\n            minWidth: 40,\n            padding: '8px 14px',\n            border: 'none',\n            borderRadius: 8,\n            // Dark translucent pill with white text reads cleanly on both\n            // light and dark container backgrounds.\n            background: 'rgba(17,24,39,0.72)',\n            color: 'white',\n            cursor: 'pointer',\n            fontFamily: 'system-ui, sans-serif',\n            fontSize: 14,\n            touchAction: 'manipulation',\n          }}\n          aria-label=\"Reset view — clear overlays and fit the page\"\n          data-role=\"exit-tutor\"\n        >\n          Reset view\n        </button>\n      ) : null}\n      {isReady ? (\n        <>\n          <CameraView camera={camera}>\n            <div\n              style={{\n                position: 'absolute',\n                top: '50%',\n                left: '50%',\n                width: baseW,\n                height: baseH,\n                transform: 'translate(-50%, -50%)',\n              }}\n            >\n              <PDFPage\n                pageNumber={pageNumber}\n                page={pageProxy}\n                scale={rasterScale}\n                rotation={rotation}\n                showTextLayer={false}\n                showHighlightLayer={false}\n                showAnnotationLayer={false}\n              />\n              <CinemaLayer\n                page={page}\n                index={index}\n                overlays={activeOverlays}\n                scale={scale || 1}\n              />\n            </div>\n          </CameraView>\n          {/* Viewport-space UI (outside the camera scale transform). */}\n          <LabelOverlay\n            overlays={activeOverlays}\n            index={index}\n            currentPage={pageNumber}\n            camera={camera}\n            viewport={viewport}\n          />\n          <CalloutLabelOverlay\n            overlays={activeOverlays}\n            index={index}\n            currentPage={pageNumber}\n            camera={camera}\n            viewport={viewport}\n          />\n          <GhostReferenceOverlay overlays={activeOverlays} index={index} />\n        </>\n      ) : (\n        <TutorLoadingState custom={loadingComponent} />\n      )}\n      {showSubtitles ? <SubtitleBar text={currentChunk ?? null} /> : null}\n    </div>\n  );\n}\n\n/**\n * Default loading state shown while the PDF document / page proxy is still\n * being fetched. Intentionally minimal — hosts with branding should pass\n * `loadingComponent` instead.\n */\nfunction TutorLoadingState({\n  custom,\n}: {\n  custom?: React.ReactNode;\n}): React.ReactElement {\n  if (custom) {\n    return (\n      <div\n        style={{\n          position: 'absolute',\n          inset: 0,\n          display: 'flex',\n          alignItems: 'center',\n          justifyContent: 'center',\n        }}\n        data-role=\"tutor-loading\"\n      >\n        {custom}\n      </div>\n    );\n  }\n  return (\n    <div\n      style={{\n        position: 'absolute',\n        inset: 0,\n        display: 'flex',\n        flexDirection: 'column',\n        alignItems: 'center',\n        justifyContent: 'center',\n        gap: 12,\n        color: 'rgba(0,0,0,0.55)',\n        fontFamily: 'system-ui, sans-serif',\n        fontSize: 13,\n      }}\n      data-role=\"tutor-loading\"\n    >\n      <div\n        aria-hidden\n        style={{\n          width: 36,\n          height: 36,\n          borderRadius: '50%',\n          border: '3px solid rgba(0,0,0,0.1)',\n          borderTopColor: 'rgba(0,0,0,0.45)',\n          animation: 'pdf-tutor-spin 0.9s linear infinite',\n        }}\n      />\n      <span>Loading document…</span>\n      <style>{`\n        @keyframes pdf-tutor-spin {\n          from { transform: rotate(0deg); }\n          to { transform: rotate(360deg); }\n        }\n      `}</style>\n    </div>\n  );\n}\n\n/**\n * Compact one-liner for the DebugLog \"storyboard ✓\" summary. Uses the\n * model's `reasoning` if the director emitted one; otherwise falls\n * back to the list of step types so the log entry still communicates\n * what the engine is about to execute. Since v0.5.1 reasoning is\n * optional to save output tokens.\n */\nfunction summariseStoryboard(\n  sb: Storyboard & { reasoning?: string },\n): string {\n  const stepCount = sb.steps.length;\n  const trimmedReasoning = (sb.reasoning ?? '').trim();\n  if (trimmedReasoning) {\n    return `storyboard ✓ ${stepCount} steps — ${trimmedReasoning.slice(0, 60)}`;\n  }\n  const kinds = sb.steps.map((s) => s.action.type).join(' → ');\n  return `storyboard ✓ ${stepCount} steps — ${kinds}`;\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { CameraState } from '../../types/storyboard';\nimport { getDeviceCapabilities } from '../../utils';\n\nexport interface CameraViewProps {\n  camera: CameraState;\n  children: React.ReactNode;\n  /** total duration for the tween, in ms */\n  durationMs?: number;\n  className?: string;\n}\n\n/**\n * Wraps page content in a Framer Motion container that animates scale+translate.\n * The origin is the center of the container.\n */\nexport function CameraView({\n  camera,\n  children,\n  durationMs = 700,\n  className,\n}: CameraViewProps) {\n  // will-change: transform pre-allocates a compositor backing store sized\n  // by the transformed output. On iOS Safari, combined with a high-DPR\n  // PDF canvas inside, this eats the per-tab memory budget and the tab\n  // is reaped. On desktop the backing store is free-ish. Gate on mobile.\n  const isMobile = getDeviceCapabilities().isMobile;\n  return (\n    <motion.div\n      className={className}\n      style={{\n        transformOrigin: '50% 50%',\n        ...(isMobile ? {} : { willChange: 'transform' }),\n        width: '100%',\n        height: '100%',\n        position: 'relative',\n      }}\n      animate={{\n        scale: camera.scale,\n        x: camera.x,\n        y: camera.y,\n      }}\n      transition={{\n        duration: durationMs / 1000,\n        ease:\n          camera.easing === 'linear'\n            ? 'linear'\n            : camera.easing === 'ease-in'\n              ? [0.42, 0, 1, 1]\n              : camera.easing === 'ease-out'\n                ? [0, 0, 0.58, 1]\n                : [0.42, 0, 0.58, 1],\n      }}\n    >\n      {children}\n    </motion.div>\n  );\n}\n","'use client';\n\nimport React from 'react';\nimport { AnimatePresence } from 'framer-motion';\nimport type {\n  ActiveOverlay,\n  ActionSpotlight,\n  ActionUnderline,\n  ActionHighlight,\n  ActionPulse,\n  ActionCallout,\n  ActionBox,\n} from '../../types/storyboard';\nimport type { PageBBoxData, BBoxIndex, BBoxCoords } from '../../types/bbox';\nimport { SpotlightMask } from './SpotlightMask';\nimport { AnimatedUnderline } from './AnimatedUnderline';\nimport { AnimatedHighlight } from './AnimatedHighlight';\nimport { PulseOverlay } from './PulseOverlay';\nimport { CalloutArrow } from './CalloutArrow';\nimport { BoxOverlay } from './BoxOverlay';\n\nexport interface CinemaLayerProps {\n  page: PageBBoxData;\n  index: BBoxIndex;\n  overlays: ActiveOverlay[];\n  scale: number;\n}\n\nfunction blockBbox(index: BBoxIndex, block_id: string): BBoxCoords | undefined {\n  return index.blockById.get(block_id)?.block.bbox;\n}\n\nexport function CinemaLayer({\n  page,\n  index,\n  overlays,\n  scale,\n}: CinemaLayerProps) {\n  return (\n    <div\n      data-role=\"cinema-layer\"\n      style={{\n        position: 'absolute',\n        inset: 0,\n        transformOrigin: '0 0',\n        transform: `scale(${scale})`,\n        width: page.page_dimensions.width,\n        height: page.page_dimensions.height,\n        pointerEvents: 'none',\n        // PDFPage renders internal layers at z-index 10/20/40/45/50\n        // (canvas / text / highlight / focus / annotation). Without an\n        // explicit z-index here, every tutor overlay stacks UNDER the\n        // AnnotationLayer and becomes invisible. 100 puts us above all of\n        // them while still letting the Exit button (z-index 60) remain\n        // reachable because it sits OUTSIDE this stacking context.\n        zIndex: 100,\n      }}\n    >\n      <AnimatePresence>\n        {overlays.map((overlay) => {\n          switch (overlay.kind) {\n            case 'spotlight': {\n              const a = overlay.action as ActionSpotlight;\n              const b = blockBbox(index, a.target_block);\n              if (!b) return null;\n              return (\n                <SpotlightMask\n                  key={overlay.id}\n                  page={page.page_dimensions}\n                  bbox={b}\n                  action={a}\n                />\n              );\n            }\n            case 'underline': {\n              const a = overlay.action as ActionUnderline;\n              const b = blockBbox(index, a.target_block);\n              if (!b) return null;\n              return <AnimatedUnderline key={overlay.id} bbox={b} action={a} />;\n            }\n            case 'highlight': {\n              const a = overlay.action as ActionHighlight;\n              const b = blockBbox(index, a.target_block);\n              if (!b) return null;\n              return <AnimatedHighlight key={overlay.id} bbox={b} action={a} />;\n            }\n            case 'pulse': {\n              const a = overlay.action as ActionPulse;\n              const b = blockBbox(index, a.target_block);\n              if (!b) return null;\n              return <PulseOverlay key={overlay.id} bbox={b} action={a} />;\n            }\n            case 'callout': {\n              const a = overlay.action as ActionCallout;\n              const from = blockBbox(index, a.from_block);\n              const to = blockBbox(index, a.to_block);\n              if (!from || !to) return null;\n              return (\n                <CalloutArrow\n                  key={overlay.id}\n                  fromBbox={from}\n                  toBbox={to}\n                  action={a}\n                />\n              );\n            }\n            case 'ghost_reference':\n              // Ghost references are viewport-space UI chrome, not page-space\n              // overlays — they must render OUTSIDE the camera scale\n              // transform or they shrink with the PDF. Handled by\n              // GhostReferenceOverlay at the TutorModeContainer root.\n              return null;\n            case 'box': {\n              const a = overlay.action as ActionBox;\n              const b = blockBbox(index, a.target_block);\n              if (!b) return null;\n              return <BoxOverlay key={overlay.id} bbox={b} action={a} />;\n            }\n            case 'label':\n              // Labels are viewport-space UI with block-derived anchors —\n              // handled by LabelOverlay at the TutorModeContainer root so\n              // typography doesn't shrink with the camera scale.\n              return null;\n            case 'clear':\n            case 'camera':\n              return null; // handled by engine, not rendered as overlays\n          }\n        })}\n      </AnimatePresence>\n    </div>\n  );\n}\n","import React, { useId } from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionSpotlight } from '../../types/storyboard';\nimport type { BBoxCoords, PageDimensionsDpi } from '../../types/bbox';\nimport { getDeviceCapabilities } from '../../utils';\nimport { ACCENT, ACCENT_GLOW, EASE_OUT_EXPO, INK } from './tokens';\n\nexport interface SpotlightMaskProps {\n  page: PageDimensionsDpi;\n  bbox: BBoxCoords;\n  action: ActionSpotlight;\n  durationMs?: number;\n}\n\n/**\n * Design: **Theatrical spotlight.** A warm-ink dim (not pure black)\n * closes over the whole page, then a feathered cutout reveals the\n * target block. A thin terracotta accent ring follows the cutout shape\n * — the same colour used by every other overlay so the spotlit region\n * is clearly part of the same annotation system.\n *\n * The dim colour is warm INK (`#2a2420`) rather than `#000` so the\n * dimmed area looks like the PDF pushed into shadow rather than\n * blacked out. On light textbook pages this reads as \"atmosphere\"\n * instead of \"censorship\".\n *\n * The accent ring animates with a slight stagger after the dim, so the\n * reveal has a subtle two-beat cadence: darken → point.\n */\nexport function SpotlightMask({\n  page,\n  bbox,\n  action,\n  durationMs = 500,\n}: SpotlightMaskProps) {\n  const maskId = useId();\n  const filterId = `${maskId}-blur`;\n  const [rawX1, rawY1, rawX2, rawY2] = bbox;\n  const rawW = Math.max(0, rawX2 - rawX1);\n  const rawH = Math.max(0, rawY2 - rawY1);\n  // Breathing room: expand the cutout past the block edges so text isn't\n  // clipped flush against the accent ring. 6% of the shorter side, clamped\n  // to a readable range — scales with block size without becoming absurd\n  // on huge figures or invisible on tiny captions.\n  const pad = Math.min(28, Math.max(10, Math.min(rawW, rawH) * 0.06));\n  const x1 = rawX1 - pad;\n  const y1 = rawY1 - pad;\n  const x2 = rawX2 + pad;\n  const y2 = rawY2 + pad;\n  const w = x2 - x1;\n  const h = y2 - y1;\n  const rx =\n    action.shape === 'rounded' ? 14 : action.shape === 'ellipse' ? w / 2 : 0;\n  const ry =\n    action.shape === 'rounded' ? 14 : action.shape === 'ellipse' ? h / 2 : 0;\n  // SVG feGaussianBlur with a large stdDeviation over a full-page mask is\n  // a known iOS Safari memory hog; the filter allocates a rasterized\n  // intermediate buffer sized by the filter region. Clamp the blur hard\n  // on mobile so the spotlight still reads as soft-edged without burning\n  // through the tab's compositor budget.\n  const isMobile = getDeviceCapabilities().isMobile;\n  const requestedFeather = Math.max(16, action.feather_px);\n  const feather = isMobile ? Math.min(12, requestedFeather) : requestedFeather;\n  const cx = (x1 + x2) / 2;\n  const cy = (y1 + y2) / 2;\n\n  return (\n    <svg\n      viewBox={`0 0 ${page.width} ${page.height}`}\n      width={page.width}\n      height={page.height}\n      preserveAspectRatio=\"none\"\n      style={{\n        position: 'absolute',\n        inset: 0,\n        pointerEvents: 'none',\n        width: page.width,\n        height: page.height,\n        overflow: 'visible',\n      }}\n      data-role=\"spotlight-mask\"\n    >\n      <defs>\n        <filter id={filterId} x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n          <feGaussianBlur in=\"SourceGraphic\" stdDeviation={feather / 4} />\n        </filter>\n        <mask id={maskId}>\n          <rect x={0} y={0} width={page.width} height={page.height} fill=\"white\" />\n          {action.shape === 'ellipse' ? (\n            <ellipse\n              cx={cx}\n              cy={cy}\n              rx={w / 2}\n              ry={h / 2}\n              fill=\"black\"\n              filter={`url(#${filterId})`}\n            />\n          ) : (\n            <rect\n              x={x1}\n              y={y1}\n              width={w}\n              height={h}\n              rx={rx}\n              ry={ry}\n              fill=\"black\"\n              filter={`url(#${filterId})`}\n            />\n          )}\n        </mask>\n      </defs>\n\n      {/* Warm ink dim — slides in first. */}\n      <motion.rect\n        x={0}\n        y={0}\n        width={page.width}\n        height={page.height}\n        fill={INK}\n        mask={`url(#${maskId})`}\n        initial={{ fillOpacity: 0 }}\n        animate={{ fillOpacity: action.dim_opacity }}\n        exit={{ fillOpacity: 0 }}\n        transition={{ duration: durationMs / 1000, ease: EASE_OUT_EXPO }}\n      />\n\n      {/* Terracotta accent ring — points to the spotlit region. */}\n      {action.shape === 'ellipse' ? (\n        <motion.ellipse\n          cx={cx}\n          cy={cy}\n          rx={w / 2}\n          ry={h / 2}\n          fill=\"none\"\n          stroke={ACCENT}\n          strokeWidth={3}\n          initial={{ opacity: 0, scale: 1.08 }}\n          animate={{ opacity: 0.9, scale: 1 }}\n          exit={{ opacity: 0 }}\n          style={{ transformOrigin: `${cx}px ${cy}px`, transformBox: 'fill-box' }}\n          transition={{\n            duration: durationMs / 1000,\n            delay: 0.15,\n            ease: EASE_OUT_EXPO,\n          }}\n        />\n      ) : (\n        <motion.rect\n          x={x1}\n          y={y1}\n          width={w}\n          height={h}\n          rx={rx}\n          ry={ry}\n          fill=\"none\"\n          stroke={ACCENT}\n          strokeWidth={3}\n          initial={{ opacity: 0, scale: 1.04 }}\n          animate={{ opacity: 0.9, scale: 1 }}\n          exit={{ opacity: 0 }}\n          style={{\n            transformOrigin: `${cx}px ${cy}px`,\n            transformBox: 'fill-box',\n          }}\n          transition={{\n            duration: durationMs / 1000,\n            delay: 0.15,\n            ease: EASE_OUT_EXPO,\n          }}\n        />\n      )}\n\n      {/* Outer glow — very soft accent halo bleeding outward. */}\n      {action.shape !== 'ellipse' ? (\n        <motion.rect\n          x={x1 - 2}\n          y={y1 - 2}\n          width={w + 4}\n          height={h + 4}\n          rx={rx + 2}\n          ry={ry + 2}\n          fill=\"none\"\n          stroke={ACCENT_GLOW}\n          strokeWidth={8}\n          initial={{ opacity: 0 }}\n          animate={{ opacity: 0.6 }}\n          exit={{ opacity: 0 }}\n          transition={{\n            duration: durationMs / 1000,\n            delay: 0.2,\n            ease: EASE_OUT_EXPO,\n          }}\n        />\n      ) : null}\n    </svg>\n  );\n}\n","/**\n * Shared design tokens for the tutor overlay primitives. Ensures the\n * spotlight / underline / highlight / callout / pulse / label / ghost\n * card all read as a single editorial system — cream paper, terracotta\n * accent, warm ink shadows, classical serif type.\n *\n * Changing a value here updates every overlay at once. Aria (or any\n * consumer) can swap the palette by shadowing this module via bundler\n * aliases if they need to rebrand.\n */\n\nexport const INK = '#2a2420';\nexport const INK_SOFT = 'rgba(42, 36, 32, 0.72)';\nexport const INK_DIM = 'rgba(42, 36, 32, 0.38)';\n\nexport const PAPER = '#faf6ec';\nexport const PAPER_DEEP = '#f3ece0';\n\n/** Terracotta / book-red — the primary annotation colour. */\nexport const ACCENT = '#b04a1a';\nexport const ACCENT_SOFT = 'rgba(176, 74, 26, 0.18)';\nexport const ACCENT_GLOW = 'rgba(176, 74, 26, 0.35)';\n\n/** Highlighter amber — warmed-down, less neon than default yellow. */\nexport const MARKER = '#e6b422';\nexport const MARKER_SOFT = 'rgba(230, 180, 34, 0.38)';\n\n/** Classical serif stack — no web fonts required, bookish on every OS. */\nexport const SERIF =\n  \"'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', 'EB Garamond', 'Hoefler Text', Georgia, serif\";\n\n/** Custom out-expo cubic-bezier — unhurried settle, not a bouncy easeOut. */\nexport const EASE_OUT_EXPO = [0.22, 1, 0.36, 1] as const;\n\n/*\n * Viewport-responsive typography for tutor-overlay pills. The pill system\n * (callout labels, sticky labels, ghost references) lives in VIEWPORT space\n * — outside the CameraView transform — so it can't inherit `camera.scale`.\n * Without a clamp, a font size tuned for a ~375 px phone reads as too small\n * on a 1440 px desktop AND the fixed maxWidth truncates labels that have\n * ample room. These tokens express \"same annotation character, proportional\n * to the viewport\" in one place.\n *\n * Curves were tuned against: iPhone 12 (375), iPad (768), standard desktop\n * (1440), wide desktop (1920). The min/max clamps guarantee readable\n * typography on extreme viewports.\n */\n\n/** All-caps callout annotation — tight, editorial marginalia vocabulary.\n *  Clamp curve shifted down 1.5px across the board in v0.5.x follow-up so\n *  wrapped labels fit more comfortably in narrow pill widths on mobile. */\nexport const PILL_FONT_CAPS = 'clamp(9px, 0.55vw + 7px, 13px)';\n/** Sentence-case pin body — slightly larger, the standard overlay label.\n *  Also shifted down 1.5px to match PILL_FONT_CAPS. */\nexport const PILL_FONT_BODY = 'clamp(10.5px, 0.6vw + 8.5px, 15px)';\n/** Display/marginalia card body — the ghost-reference text block. */\nexport const PILL_FONT_DISPLAY = 'clamp(14px, 0.75vw + 12px, 19px)';\n\n/** Max pill width for all-caps callout labels. Expands with viewport so\n *  longer phrases (\"PRIMARY CARTILAGINOUS JOINTS\") don't truncate on\n *  desktop where there's clearly room. */\nexport const PILL_MAX_W_CAPS = 'clamp(180px, 26vw, 380px)';\nexport const PILL_MAX_W_BODY = 'clamp(200px, 28vw, 440px)';\n\n/**\n * Runtime resolvers mirroring the CSS clamps above. Callout geometry\n * (auto-flip side selection, viewport bound clamping) runs in JS and\n * needs the SAME numeric value that the clamp CSS will evaluate to —\n * otherwise the pill's position calculation disagrees with its rendered\n * size. Kept in sync with the strings by construction: if you edit a\n * clamp curve above, update its resolver pair.\n */\nexport function resolvePillOffset(viewportWidthPx: number): number {\n  return clamp(0.022 * viewportWidthPx + 12, 20, 44);\n}\nexport function resolveMaxPillW(viewportWidthPx: number): number {\n  return clamp(0.26 * viewportWidthPx, 180, 380);\n}\nexport function resolveMaxPillH(viewportWidthPx: number): number {\n  // Pill height is mostly font-driven; ~2.6× the font size accounts for\n  // line-height + padding. Tracks PILL_FONT_CAPS (shifted down 1.5px).\n  const font = clamp(0.0055 * viewportWidthPx + 7, 9, 13);\n  return clamp(font * 2.6, 24, 36);\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n  return Math.min(hi, Math.max(lo, v));\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionUnderline } from '../../types/storyboard';\nimport type { BBoxCoords } from '../../types/bbox';\nimport { ACCENT, EASE_OUT_EXPO } from './tokens';\n\nexport interface AnimatedUnderlineProps {\n  bbox: BBoxCoords;\n  action: ActionUnderline;\n}\n\n/**\n * Design: **Scholar's pen stroke.** Four distinct pen styles render as\n * a real reader's ink annotation would — confident stroke, subtle\n * ink-blot pen-lift at the tail, slight over-stroke past the target\n * so the mark feels handmade rather than auto-generated.\n *\n * `sketch` gets a deterministic low-frequency jitter (not `Math.random`,\n * which would re-roll on every render) + a faint ghost stroke offset\n * below for ink-on-paper feel.\n *\n * `wavy` uses a proper sine curve instead of quadratic-bezier humps,\n * which tended to kink at steeper wavelengths.\n */\n\n/** Deterministic hashed-jitter so the sketch path is stable across\n *  re-renders. Same segment index ⇒ same offset. */\nfunction jitterAt(i: number): number {\n  const h = Math.sin(i * 12.9898) * 43758.5453;\n  return (h - Math.floor(h) - 0.5) * 4; // ±2 px\n}\n\nfunction pathForStyle(\n  x1: number,\n  x2: number,\n  y: number,\n  style: ActionUnderline['style'],\n): { primary: string; ghost?: string } {\n  // Slight over-stroke so the mark feels hand-extended.\n  const x1e = x1 - 4;\n  const x2e = x2 + 4;\n\n  if (style === 'straight') {\n    return { primary: `M ${x1e} ${y} L ${x2e} ${y}` };\n  }\n\n  if (style === 'double') {\n    return {\n      primary: `M ${x1e} ${y - 3} L ${x2e} ${y - 3}`,\n      ghost: `M ${x1e} ${y + 3} L ${x2e} ${y + 3}`,\n    };\n  }\n\n  if (style === 'wavy') {\n    const len = x2e - x1e;\n    const steps = Math.max(12, Math.floor(len / 10));\n    const amp = 3.2;\n    let d = `M ${x1e} ${y}`;\n    for (let i = 1; i <= steps; i++) {\n      const t = i / steps;\n      const px = x1e + len * t;\n      const py = y + Math.sin(t * Math.PI * 4) * amp;\n      // Smooth with quadratic control between each sampled point.\n      const prevT = (i - 1) / steps;\n      const cpx = x1e + len * (prevT + (t - prevT) / 2);\n      const cpy = y + Math.sin((prevT + (t - prevT) / 2) * Math.PI * 4) * amp;\n      d += ` Q ${cpx} ${cpy} ${px} ${py}`;\n    }\n    return { primary: d };\n  }\n\n  // sketch: deterministic jitter along the stroke + a faint ghost below\n  // for an ink-on-textured-paper feel.\n  const segs = 8;\n  let primary = `M ${x1e} ${y + jitterAt(0)}`;\n  let ghost = `M ${x1e} ${y + jitterAt(100) + 1.5}`;\n  for (let i = 1; i <= segs; i++) {\n    const px = x1e + ((x2e - x1e) * i) / segs;\n    primary += ` L ${px} ${y + jitterAt(i)}`;\n    ghost += ` L ${px} ${y + jitterAt(i + 100) + 1.5}`;\n  }\n  return { primary, ghost };\n}\n\nexport function AnimatedUnderline({ bbox, action }: AnimatedUnderlineProps) {\n  const [x1, , x2, y2] = bbox;\n  const y = y2 + 6;\n  const { primary, ghost } = pathForStyle(x1, x2, y, action.style);\n  const duration = action.draw_duration_ms / 1000;\n  // Use the action.color if the LLM supplied a non-default value;\n  // otherwise fall back to our accent so underlines match the system.\n  const stroke =\n    action.color && action.color !== '#FBBF24' ? action.color : ACCENT;\n\n  // Pen-lift blot at the trailing end — a small disc that appears once\n  // the stroke has fully drawn, suggesting the pen paused there.\n  const blotX = x2 + 4;\n  const blotY = y;\n  const strokeWeight = action.style === 'wavy' ? 3 : 4;\n\n  // Tight CSS box around the stroke so iOS Safari's compositor doesn't\n  // allocate a full-page layer per underline. Covers stroke width (≤4),\n  // wavy amplitude (~±3.2), ghost stroke (+1.5 below), blot radius (~2.5),\n  // and the horizontal over-stroke (±4). Path coords stay absolute via\n  // viewBox; visuals unchanged.\n  const uxPad = 8;\n  const uAbove = 8;\n  const uBelow = 24;\n  const svgX = x1 - uxPad;\n  const svgY = y - uAbove;\n  const svgW = x2 - x1 + 2 * uxPad;\n  const svgH = uAbove + uBelow;\n\n  return (\n    <svg\n      width={svgW}\n      height={svgH}\n      viewBox={`${svgX} ${svgY} ${svgW} ${svgH}`}\n      style={{\n        position: 'absolute',\n        left: svgX,\n        top: svgY,\n        pointerEvents: 'none',\n        overflow: 'visible',\n      }}\n      data-role=\"underline\"\n    >\n      {/* Faint ghost stroke — gives sketch/double a paper-bleed feel. */}\n      {ghost ? (\n        <motion.path\n          d={ghost}\n          fill=\"none\"\n          stroke={stroke}\n          strokeWidth={strokeWeight - 1.5}\n          strokeLinecap=\"round\"\n          strokeOpacity={0.35}\n          initial={{ pathLength: 0, opacity: 0 }}\n          animate={{ pathLength: 1, opacity: 0.55 }}\n          exit={{ opacity: 0 }}\n          transition={{ duration, ease: EASE_OUT_EXPO }}\n        />\n      ) : null}\n\n      {/* Primary stroke — the confident mark. */}\n      <motion.path\n        d={primary}\n        fill=\"none\"\n        stroke={stroke}\n        strokeWidth={strokeWeight}\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        initial={{ pathLength: 0, opacity: 0 }}\n        animate={{ pathLength: 1, opacity: 1 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration, ease: EASE_OUT_EXPO }}\n      />\n\n      {/* Pen-lift ink blot — lands right at the end of the stroke. */}\n      <motion.circle\n        cx={blotX}\n        cy={blotY}\n        r={strokeWeight / 2 + 0.5}\n        fill={stroke}\n        initial={{ scale: 0, opacity: 0 }}\n        animate={{ scale: 1, opacity: 0.9 }}\n        exit={{ opacity: 0 }}\n        style={{\n          transformOrigin: `${blotX}px ${blotY}px`,\n          transformBox: 'fill-box',\n        }}\n        transition={{\n          duration: 0.25,\n          delay: duration - 0.1,\n          ease: EASE_OUT_EXPO,\n        }}\n      />\n    </svg>\n  );\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionHighlight } from '../../types/storyboard';\nimport type { BBoxCoords } from '../../types/bbox';\nimport { EASE_OUT_EXPO } from './tokens';\n\nexport interface AnimatedHighlightProps {\n  bbox: BBoxCoords;\n  action: ActionHighlight;\n}\n\n/**\n * Design: **Light highlighter wash.** A real highlighter on textbook\n * paper is surprisingly transparent — the text must remain legible\n * through the wash.\n *\n * The previous implementation relied on `mixBlendMode: multiply` to\n * darken text through a semi-opaque fill. That works in isolation but\n * breaks when the SVG sits inside a transformed ancestor (CinemaLayer\n * applies `transform: scale(...)` which creates its own stacking\n * context). `mixBlendMode: multiply` then multiplies against the\n * stacking-context background (transparent), not the PDF canvas, so\n * the fill silently degrades to ordinary alpha painting — and if the\n * LLM emitted an opaque `action.color` (e.g. `#FBBF24`), the highlight\n * appeared as a solid yellow bar obscuring the text.\n *\n * Fix:\n * - No `mixBlendMode`. We always paint with partial opacity.\n * - `fillOpacity` is controlled by us, not by the colour string. We\n *   strip any alpha the consumer/LLM supplied and apply a fixed\n *   `fill-opacity` so the wash is guaranteed translucent regardless\n *   of what colour comes in.\n * - No SVG filter stack. `feTurbulence` + `feDisplacementMap` added\n *   a subtle fibre texture that's invisible at reading distance and\n *   was one of the most expensive paint primitives in mobile WebKit.\n */\n\n/** Default hue, used when the LLM emits the schema default amber. */\nconst DEFAULT_HUE = 'rgb(230, 180, 34)';\n\n/** Fraction of the amber that shows through on top of the PDF. 0.28\n *  matches the apparent darkness of the old `rgba(230,180,34,0.22)`\n *  painted through `mixBlendMode: multiply` on a white page, so\n *  regression is minimal where multiply was actually working. */\nconst WASH_OPACITY = 0.28;\n\n/** Strip alpha from an rgba(...) string, leaving rgb(...). Leaves hex\n *  and named colours untouched — we treat those as solid hues to be\n *  washed by our own `fillOpacity`. */\nfunction stripAlpha(color: string): string {\n  const m = color.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i);\n  return m ? `rgb(${m[1]}, ${m[2]}, ${m[3]})` : color;\n}\n\nexport function AnimatedHighlight({ bbox, action }: AnimatedHighlightProps) {\n  const [x1, y1, x2, y2] = bbox;\n  const h = Math.max(1, y2 - y1);\n  const bleed = Math.min(4, h * 0.12);\n  const yTop = y1 - bleed;\n  const yBot = y2 + bleed;\n  const duration = action.draw_duration_ms / 1000;\n\n  // Honour an explicit `action.color` override only when it deviates from\n  // the schema default the LLM emits for \"amber highlight\" variants.\n  const isDefaultColour =\n    !action.color ||\n    action.color === 'rgba(250, 204, 21, 0.35)' ||\n    action.color === 'rgba(250,204,21,0.35)';\n  const fill = stripAlpha(isDefaultColour ? DEFAULT_HUE : action.color);\n\n  // Tapered path: moves up slightly at the start/end so the highlight has\n  // the uneven pen-hit look instead of a clean edge.\n  const taper = Math.min(6, h * 0.2);\n  const pathD = `\n    M ${x1 - 2} ${yTop + taper}\n    L ${x1 + 2} ${yTop}\n    L ${x2 - 2} ${yTop}\n    L ${x2 + 2} ${yTop + taper}\n    L ${x2 + 2} ${yBot - taper}\n    L ${x2 - 2} ${yBot}\n    L ${x1 + 2} ${yBot}\n    L ${x1 - 2} ${yBot - taper}\n    Z\n  `;\n\n  // Tight CSS box around the path so iOS Safari's compositor doesn't\n  // allocate a full-page-sized backing layer for every concurrent overlay.\n  // Path coordinates stay in source-DPI space (the coord space CinemaLayer's\n  // transform operates in); `viewBox` preserves them.\n  const svgPad = 8;\n  const svgX = x1 - svgPad;\n  const svgY = yTop - svgPad;\n  const svgW = x2 - x1 + 2 * svgPad;\n  const svgH = yBot - yTop + 2 * svgPad;\n\n  return (\n    <svg\n      width={svgW}\n      height={svgH}\n      viewBox={`${svgX} ${svgY} ${svgW} ${svgH}`}\n      style={{\n        position: 'absolute',\n        left: svgX,\n        top: svgY,\n        pointerEvents: 'none',\n        overflow: 'visible',\n      }}\n      data-role=\"highlight\"\n    >\n      <motion.path\n        d={pathD}\n        fill={fill}\n        fillOpacity={WASH_OPACITY}\n        initial={{ clipPath: `inset(0 100% 0 0)` }}\n        animate={{ clipPath: `inset(0 0% 0 0)` }}\n        exit={{ opacity: 0 }}\n        transition={{ duration, ease: EASE_OUT_EXPO }}\n      />\n    </svg>\n  );\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionPulse } from '../../types/storyboard';\nimport type { BBoxCoords } from '../../types/bbox';\nimport { ACCENT, ACCENT_GLOW, EASE_OUT_EXPO } from './tokens';\n\nexport interface PulseOverlayProps {\n  bbox: BBoxCoords;\n  action: ActionPulse;\n}\n\ntype IntensitySpec = {\n  bracketLen: number;\n  strokeWeight: number;\n  coreOpacity: number;\n  ringScale: number;\n};\n\nconst INTENSITY: Record<ActionPulse['intensity'], IntensitySpec> = {\n  subtle: { bracketLen: 14, strokeWeight: 2, coreOpacity: 0.5, ringScale: 1.08 },\n  normal: { bracketLen: 20, strokeWeight: 2.5, coreOpacity: 0.75, ringScale: 1.14 },\n  strong: { bracketLen: 26, strokeWeight: 3, coreOpacity: 1, ringScale: 1.22 },\n};\n\n/**\n * Design: **Camera viewfinder brackets.** Four L-shapes slide in from\n * each corner of the target block, like framing crosshairs on a camera.\n * Behind them, a soft radial glow pulses in sync with the bracket\n * emphasis — a \"look here\" cue that points without blocking content.\n *\n * Intensity controls bracket length + stroke weight + glow strength.\n * `count` controls how many emphasis pulses happen before the overlay\n * settles.\n *\n * Brackets slide in from OUTSIDE the block then snap to the corners,\n * which reads as \"framing\" rather than the usual bordered box.\n */\nexport function PulseOverlay({ bbox, action }: PulseOverlayProps) {\n  const [x1, y1, x2, y2] = bbox;\n  const w = Math.max(1, x2 - x1);\n  const h = Math.max(1, y2 - y1);\n  const cx = (x1 + x2) / 2;\n  const cy = (y1 + y2) / 2;\n\n  const spec = INTENSITY[action.intensity] ?? INTENSITY.normal;\n  // Cap bracket length to at most a third of the shorter side so tiny\n  // blocks don't get brackets that exceed their own geometry.\n  const L = Math.min(spec.bracketLen, Math.min(w, h) / 2.5);\n  const PAD = 6;\n\n  // Tight CSS box so the compositor doesn't allocate a full-page layer\n  // per pulse. Three drawn extents matter, in roughly descending size:\n  //   - Emphasis ring scaled up to ringScale (1.22 at peak)\n  //   - Glow ellipse at rx = w/2 + 10, scaled up to ringScale, plus a\n  //     CSS `filter: blur(16px)` which spreads outside the ellipse bbox\n  //   - Brackets slide in from PAD + L + 8 px outside the block corners\n  const ringExtentX = (w / 2 + PAD) * spec.ringScale - w / 2;\n  const ringExtentY = (h / 2 + PAD) * spec.ringScale - h / 2;\n  const glowExtentX = (w / 2 + 10) * spec.ringScale - w / 2 + 24; // +24 covers blur(16) spread\n  const glowExtentY = (h / 2 + 10) * spec.ringScale - h / 2 + 24;\n  const bracketExtent = PAD + L + 8;\n  const svgPadX = Math.ceil(Math.max(40, ringExtentX, glowExtentX, bracketExtent));\n  const svgPadY = Math.ceil(Math.max(40, ringExtentY, glowExtentY, bracketExtent));\n  const svgX = x1 - svgPadX;\n  const svgY = y1 - svgPadY;\n  const svgW = w + 2 * svgPadX;\n  const svgH = h + 2 * svgPadY;\n  // Both the outer glow and the emphasis ring play ONCE. The schema\n  // still accepts an `action.count`, but playing it as a repeated loop\n  // reads as \"ambient warning\" rather than \"look here\" and becomes\n  // distracting over a whole narration session. One well-shaped pulse\n  // is enough — intensity is expressed via bracket weight and ring\n  // size (see INTENSITY spec), not repetition.\n\n  return (\n    <svg\n      width={svgW}\n      height={svgH}\n      viewBox={`${svgX} ${svgY} ${svgW} ${svgH}`}\n      style={{\n        position: 'absolute',\n        left: svgX,\n        top: svgY,\n        pointerEvents: 'none',\n        overflow: 'visible',\n      }}\n      data-role=\"pulse\"\n    >\n      {/* Soft glow behind the block — pulses in sync with brackets. */}\n      <motion.ellipse\n        cx={cx}\n        cy={cy}\n        rx={w / 2 + 10}\n        ry={h / 2 + 10}\n        fill={ACCENT_GLOW}\n        style={{\n          transformOrigin: `${cx}px ${cy}px`,\n          transformBox: 'fill-box',\n          filter: 'blur(16px)',\n        }}\n        initial={{ opacity: 0, scale: 0.95 }}\n        animate={{\n          opacity: [0, spec.coreOpacity * 0.45, 0.15],\n          scale: [0.95, spec.ringScale, 1],\n        }}\n        exit={{ opacity: 0 }}\n        transition={{\n          duration: 1.3,\n          times: [0, 0.5, 1],\n          ease: EASE_OUT_EXPO,\n        }}\n      />\n\n      {/* Four viewfinder brackets — each L-shape is two segments. */}\n      {/* Top-left */}\n      <Bracket\n        originX={x1 - PAD}\n        originY={y1 - PAD}\n        direction=\"tl\"\n        length={L}\n        weight={spec.strokeWeight}\n        delay={0}\n      />\n      {/* Top-right */}\n      <Bracket\n        originX={x2 + PAD}\n        originY={y1 - PAD}\n        direction=\"tr\"\n        length={L}\n        weight={spec.strokeWeight}\n        delay={0.04}\n      />\n      {/* Bottom-left */}\n      <Bracket\n        originX={x1 - PAD}\n        originY={y2 + PAD}\n        direction=\"bl\"\n        length={L}\n        weight={spec.strokeWeight}\n        delay={0.08}\n      />\n      {/* Bottom-right */}\n      <Bracket\n        originX={x2 + PAD}\n        originY={y2 + PAD}\n        direction=\"br\"\n        length={L}\n        weight={spec.strokeWeight}\n        delay={0.12}\n      />\n\n      {/* Emphasis ring — expands and fades for each pulse count. */}\n      <motion.rect\n        x={x1 - PAD}\n        y={y1 - PAD}\n        width={w + PAD * 2}\n        height={h + PAD * 2}\n        fill=\"none\"\n        stroke={ACCENT}\n        strokeWidth={1}\n        rx={4}\n        style={{\n          transformOrigin: `${cx}px ${cy}px`,\n          transformBox: 'fill-box',\n        }}\n        initial={{ scale: 1, opacity: 0 }}\n        animate={{\n          scale: [1, spec.ringScale, 1],\n          opacity: [0, spec.coreOpacity * 0.5, 0],\n        }}\n        exit={{ opacity: 0 }}\n        transition={{\n          duration: 1.3,\n          times: [0, 0.5, 1],\n          ease: EASE_OUT_EXPO,\n          delay: 0.2,\n        }}\n      />\n    </svg>\n  );\n}\n\n/**\n * A single L-shaped corner bracket. Rendered as two line segments in\n * one SVG path so the animation applies uniformly.\n */\nfunction Bracket({\n  originX,\n  originY,\n  direction,\n  length,\n  weight,\n  delay,\n}: {\n  originX: number;\n  originY: number;\n  direction: 'tl' | 'tr' | 'bl' | 'br';\n  length: number;\n  weight: number;\n  delay: number;\n}) {\n  // Each corner's two arms extend from the origin inward along x and y.\n  const xSign = direction === 'tl' || direction === 'bl' ? 1 : -1;\n  const ySign = direction === 'tl' || direction === 'tr' ? 1 : -1;\n\n  const d = `\n    M ${originX + xSign * length} ${originY}\n    L ${originX} ${originY}\n    L ${originX} ${originY + ySign * length}\n  `;\n\n  // Slide-in offset — each bracket enters from its outer corner.\n  const slideX = -xSign * 8;\n  const slideY = -ySign * 8;\n\n  return (\n    <motion.path\n      d={d}\n      fill=\"none\"\n      stroke={ACCENT}\n      strokeWidth={weight}\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      initial={{ opacity: 0, x: slideX, y: slideY }}\n      animate={{ opacity: 1, x: 0, y: 0 }}\n      exit={{ opacity: 0 }}\n      transition={{\n        duration: 0.4,\n        delay,\n        ease: EASE_OUT_EXPO,\n      }}\n    />\n  );\n}\n","import React, { useId } from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionCallout } from '../../types/storyboard';\nimport type { BBoxCoords } from '../../types/bbox';\nimport { ACCENT, EASE_OUT_EXPO } from './tokens';\n\nexport interface CalloutArrowProps {\n  fromBbox: BBoxCoords;\n  toBbox: BBoxCoords;\n  action: ActionCallout;\n}\n\nfunction centerOf(b: BBoxCoords) {\n  return { x: (b[0] + b[2]) / 2, y: (b[1] + b[3]) / 2 };\n}\n\n/**\n * Offset the start/end points slightly away from each block's centre so\n * the arrow emerges from the edge rather than plunging into the block.\n */\nfunction edgePoints(\n  fromBbox: BBoxCoords,\n  toBbox: BBoxCoords,\n): { from: { x: number; y: number }; to: { x: number; y: number } } {\n  const a = centerOf(fromBbox);\n  const b = centerOf(toBbox);\n  const dx = b.x - a.x;\n  const dy = b.y - a.y;\n  const len = Math.hypot(dx, dy) || 1;\n  const ux = dx / len;\n  const uy = dy / len;\n\n  // Move start/end toward the edge of each block along the line between them.\n  const aHalfW = (fromBbox[2] - fromBbox[0]) / 2;\n  const aHalfH = (fromBbox[3] - fromBbox[1]) / 2;\n  const bHalfW = (toBbox[2] - toBbox[0]) / 2;\n  const bHalfH = (toBbox[3] - toBbox[1]) / 2;\n\n  // Clamp edge distance so tiny blocks don't produce zero-length offsets.\n  const aOff = Math.min(Math.max(aHalfW, aHalfH), 60);\n  const bOff = Math.min(Math.max(bHalfW, bHalfH), 60);\n\n  return {\n    from: { x: a.x + ux * aOff, y: a.y + uy * aOff },\n    to: { x: b.x - ux * bOff, y: b.y - uy * bOff },\n  };\n}\n\nfunction arrowPath(\n  from: { x: number; y: number },\n  to: { x: number; y: number },\n  curve: ActionCallout['curve'],\n): string {\n  if (curve === 'straight') return `M ${from.x} ${from.y} L ${to.x} ${to.y}`;\n  if (curve === 'zigzag') {\n    const mx = (from.x + to.x) / 2;\n    return `M ${from.x} ${from.y} L ${mx} ${from.y} L ${mx} ${to.y} L ${to.x} ${to.y}`;\n  }\n  // Curved: arc perpendicular-offset from the midpoint for a gentle sweep.\n  const dx = to.x - from.x;\n  const dy = to.y - from.y;\n  const cx = (from.x + to.x) / 2 - dy * 0.22;\n  const cy = (from.y + to.y) / 2 + dx * 0.22;\n  return `M ${from.x} ${from.y} Q ${cx} ${cy} ${to.x} ${to.y}`;\n}\n\n/**\n * Design: **Editorial connector.** Hand-drawn feel via a refined stroke\n * + a small origin dot at the \"from\" end (like a teacher's pen planted\n * on the page before they draw the arrow). The arrowhead is a slender\n * open caret rather than a heavy filled triangle — reads as annotation,\n * not direction-signage.\n *\n * An optional label pill rides the arrow's trailing end using the same\n * editorial pin language as StickyLabel (cream paper, terracotta rule,\n * serif small-caps). Everything uses ACCENT for colour consistency.\n */\nexport function CalloutArrow({ fromBbox, toBbox, action }: CalloutArrowProps) {\n  const markerId = useId();\n  const glowId = `${markerId}-glow`;\n  const { from, to } = edgePoints(fromBbox, toBbox);\n  const d = arrowPath(from, to, action.curve);\n\n  // Tight CSS box around both endpoints + arc deviation for curved\n  // arrows. A curved arrow perpendicular-offsets its midpoint by\n  // ~0.22 × distance, so the arc can bulge that far from the straight\n  // line; zigzag stays within the endpoint box. Includes origin circle\n  // (r=7 + stroke), arrow stroke (2.4), and glow stroke with\n  // feGaussianBlur spread (~8 px).\n  const rawMinX = Math.min(from.x, to.x);\n  const rawMinY = Math.min(from.y, to.y);\n  const rawMaxX = Math.max(from.x, to.x);\n  const rawMaxY = Math.max(from.y, to.y);\n  const dist = Math.hypot(to.x - from.x, to.y - from.y);\n  const arcDev = action.curve === 'curved' ? dist * 0.12 : 0;\n  const basePad = 16;\n  const svgX = rawMinX - basePad - arcDev;\n  const svgY = rawMinY - basePad - arcDev;\n  const svgW = rawMaxX - rawMinX + 2 * (basePad + arcDev);\n  const svgH = rawMaxY - rawMinY + 2 * (basePad + arcDev);\n\n  return (\n    <svg\n      width={svgW}\n      height={svgH}\n      viewBox={`${svgX} ${svgY} ${svgW} ${svgH}`}\n      style={{\n        position: 'absolute',\n        left: svgX,\n        top: svgY,\n        pointerEvents: 'none',\n        overflow: 'visible',\n      }}\n      data-role=\"callout\"\n    >\n      <defs>\n        {/* Slender open-caret arrowhead — editorial, not directional signage. */}\n        <marker\n          id={markerId}\n          viewBox=\"0 0 12 10\"\n          refX={10}\n          refY={5}\n          markerWidth={10}\n          markerHeight={10}\n          orient=\"auto\"\n        >\n          <path\n            d=\"M 1 1 L 10 5 L 1 9\"\n            fill=\"none\"\n            stroke={ACCENT}\n            strokeWidth={1.8}\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n          />\n        </marker>\n        {/* Soft glow behind the stroke for depth on light pages. */}\n        <filter id={glowId} x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n          <feGaussianBlur stdDeviation=\"2.5\" />\n        </filter>\n      </defs>\n\n      {/* Origin dot — pen planted on the \"from\" side. */}\n      <motion.circle\n        cx={from.x}\n        cy={from.y}\n        r={4}\n        fill={ACCENT}\n        initial={{ scale: 0, opacity: 0 }}\n        animate={{ scale: 1, opacity: 1 }}\n        exit={{ opacity: 0 }}\n        style={{\n          transformOrigin: `${from.x}px ${from.y}px`,\n          transformBox: 'fill-box',\n        }}\n        transition={{ duration: 0.3, ease: EASE_OUT_EXPO }}\n      />\n      <motion.circle\n        cx={from.x}\n        cy={from.y}\n        r={7}\n        fill=\"none\"\n        stroke={ACCENT}\n        strokeWidth={1.2}\n        strokeOpacity={0.4}\n        initial={{ scale: 0, opacity: 0 }}\n        animate={{ scale: 1, opacity: 0.5 }}\n        exit={{ opacity: 0 }}\n        style={{\n          transformOrigin: `${from.x}px ${from.y}px`,\n          transformBox: 'fill-box',\n        }}\n        transition={{ duration: 0.4, delay: 0.08, ease: EASE_OUT_EXPO }}\n      />\n\n      {/* Soft glow trail behind the arrow for depth. */}\n      <motion.path\n        d={d}\n        fill=\"none\"\n        stroke={ACCENT}\n        strokeWidth={6}\n        strokeOpacity={0.18}\n        strokeLinecap=\"round\"\n        filter={`url(#${glowId})`}\n        initial={{ pathLength: 0, opacity: 0 }}\n        animate={{ pathLength: 1, opacity: 0.8 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration: 0.7, delay: 0.12, ease: EASE_OUT_EXPO }}\n      />\n\n      {/* Primary stroke — the inked arrow. */}\n      <motion.path\n        d={d}\n        fill=\"none\"\n        stroke={ACCENT}\n        strokeWidth={2.4}\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        markerEnd={`url(#${markerId})`}\n        initial={{ pathLength: 0, opacity: 0 }}\n        animate={{ pathLength: 1, opacity: 1 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration: 0.7, delay: 0.15, ease: EASE_OUT_EXPO }}\n      />\n\n      {/* Label is rendered by CalloutLabelOverlay at viewport space —\n         the SVG here sits inside the CameraView scale transform, which\n         would crush label typography at fit-scale. */}\n    </svg>\n  );\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionBox } from '../../types/storyboard';\nimport type { BBoxCoords } from '../../types/bbox';\nimport { ACCENT, ACCENT_SOFT, EASE_OUT_EXPO } from './tokens';\n\nexport interface BoxOverlayProps {\n  bbox: BBoxCoords;\n  action: ActionBox;\n}\n\n/**\n * Design: **Framed region.** A structural region marker — thinner and\n * more refined than the previous generic 3px coloured border. A subtle\n * accent-tinted wash fills the interior so the framed region reads as\n * \"selected\" even without a thick border. Dashed style uses a custom\n * dash pattern that matches the editorial vocabulary.\n *\n * Honours `action.color` when the LLM specifies something non-default,\n * otherwise falls through to the terracotta accent so boxes fit the\n * system.\n */\nexport function BoxOverlay({ bbox, action }: BoxOverlayProps) {\n  const [x1, y1, x2, y2] = bbox;\n  const useSystem =\n    !action.color ||\n    action.color === '#3B82F6' ||\n    action.color === '#3b82f6';\n  const borderColor = useSystem ? ACCENT : action.color;\n  const washColor = useSystem ? ACCENT_SOFT : undefined;\n\n  return (\n    <motion.div\n      initial={{ opacity: 0, scale: 0.98 }}\n      animate={{ opacity: 1, scale: 1 }}\n      exit={{ opacity: 0 }}\n      transition={{ duration: 0.45, ease: EASE_OUT_EXPO }}\n      style={{\n        position: 'absolute',\n        left: x1 - 3,\n        top: y1 - 3,\n        width: x2 - x1 + 6,\n        height: y2 - y1 + 6,\n        border: `${\n          action.style === 'dashed' ? '2px dashed' : '2px solid'\n        } ${borderColor}`,\n        borderRadius: 4,\n        background: washColor,\n        pointerEvents: 'none',\n        boxSizing: 'border-box',\n        // Subtle outer glow for the accent version, tinted to match.\n        boxShadow: useSystem\n          ? `0 0 0 1px rgba(176, 74, 26, 0.10), 0 8px 24px -10px rgba(176, 74, 26, 0.35)`\n          : undefined,\n      }}\n      data-role=\"box\"\n    />\n  );\n}\n","'use client';\n\nimport React from 'react';\nimport { AnimatePresence } from 'framer-motion';\nimport { GhostReference } from './GhostReference';\nimport type {\n  ActiveOverlay,\n  ActionGhostReference,\n} from '../../types/storyboard';\nimport type { BBoxIndex } from '../../types/bbox';\n\nexport interface GhostReferenceOverlayProps {\n  overlays: ActiveOverlay[];\n  index: BBoxIndex;\n}\n\n/**\n * Hosts ghost_reference cards at viewport space — OUTSIDE the CameraView\n * scale transform. Rendered as a sibling of CameraView inside\n * TutorModeContainer so the cards stay at natural size even when the\n * camera is zoomed to fit-page (which otherwise shrinks everything\n * inside the transform tree).\n */\nexport function GhostReferenceOverlay({\n  overlays,\n  index,\n}: GhostReferenceOverlayProps): React.ReactElement {\n  const ghosts = overlays.filter((o) => o.kind === 'ghost_reference');\n\n  return (\n    <div\n      data-role=\"ghost-reference-overlay\"\n      style={{\n        position: 'absolute',\n        inset: 0,\n        pointerEvents: 'none',\n        // Sits above the Reset view button (z-60) so a ghost card doesn't\n        // disappear behind it if the host also renders the Reset button.\n        zIndex: 70,\n      }}\n    >\n      <AnimatePresence>\n        {ghosts.map((overlay) => {\n          const a = overlay.action as ActionGhostReference;\n          const hit = index.blockById.get(a.target_block);\n          if (!hit) return null;\n          const targetPage = index.byPage.get(a.target_page);\n          if (!targetPage) return null;\n          return (\n            <GhostReference\n              key={overlay.id}\n              page={targetPage.page_dimensions}\n              sourceBbox={hit.block.bbox}\n              sourceBlockText={hit.block.text}\n              sourcePageNumber={hit.pageNumber}\n              action={a}\n            />\n          );\n        })}\n      </AnimatePresence>\n    </div>\n  );\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionGhostReference } from '../../types/storyboard';\nimport type { BBoxCoords, PageDimensionsDpi } from '../../types/bbox';\nimport { PILL_FONT_DISPLAY } from './tokens';\n\nexport interface GhostReferenceProps {\n  page: PageDimensionsDpi;\n  sourceBbox: BBoxCoords;\n  sourceBlockText: string | null;\n  sourcePageNumber: number;\n  action: ActionGhostReference;\n}\n\n/**\n * Design: **Editorial marginalia.** The card channels the aesthetic of a\n * well-designed textbook footnote — cream paper stock, a terracotta\n * footnote rule, classical serif body, a refined locator thumbnail drawn\n * with simulated text lines. This is an anatomy / medical-education\n * context; the design language should match the object students are\n * already reading (a book) rather than feel like a notification card.\n *\n * Anchor offsets scale with viewport so the card never pins off-screen.\n */\nconst POSITIONS: Record<\n  ActionGhostReference['position'],\n  React.CSSProperties\n> = {\n  'top-right': {\n    top: 'clamp(12px, 4vw, 40px)',\n    right: 'clamp(12px, 4vw, 40px)',\n  },\n  'top-left': {\n    top: 'clamp(12px, 4vw, 40px)',\n    left: 'clamp(12px, 4vw, 40px)',\n  },\n  'bottom-right': {\n    bottom: 'clamp(12px, 4vw, 40px)',\n    right: 'clamp(12px, 4vw, 40px)',\n  },\n  'bottom-left': {\n    bottom: 'clamp(12px, 4vw, 40px)',\n    left: 'clamp(12px, 4vw, 40px)',\n  },\n};\n\n// Editorial palette — warm paper + book-red accent.\nconst INK = '#2a2420';\nconst PAPER = '#faf6ec';\nconst PAPER_DEEP = '#f3ece0';\nconst ACCENT = '#b04a1a'; // terracotta / book-red\nconst RULE = 'rgba(42, 36, 32, 0.10)';\n\n/**\n * Classical serif stack. No web fonts required — relies on platform\n * classics (Iowan / Palatino / Garamond / Book Antiqua) so the card\n * inherits bookish type on macOS, iOS, and Windows, with a graceful\n * fallback to Georgia, then generic serif.\n */\nconst SERIF =\n  \"'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', 'EB Garamond', 'Hoefler Text', Georgia, serif\";\n\nexport function GhostReference({\n  page,\n  sourceBbox,\n  sourceBlockText,\n  action,\n}: GhostReferenceProps) {\n  const [x1, y1, x2, y2] = sourceBbox;\n  const text = sourceBlockText ?? '(figure)';\n\n  return (\n    <motion.div\n      initial={{ opacity: 0, y: 24, scale: 0.97 }}\n      animate={{ opacity: 1, y: 0, scale: 1 }}\n      exit={{ opacity: 0, y: 20, scale: 0.97 }}\n      transition={{\n        duration: 0.55,\n        ease: [0.22, 1, 0.36, 1], // custom out-expo for an unhurried settle\n      }}\n      style={{\n        position: 'absolute',\n        width: 'min(420px, calc(100vw - clamp(24px, 8vw, 80px)))',\n        background: PAPER,\n        color: INK,\n        border: `1px solid ${RULE}`,\n        // Barely-there corner radius — square-ish corners feel editorial,\n        // 12px+ radius feels SaaS-notification. 3px is the sweet spot.\n        borderRadius: 3,\n        overflow: 'hidden',\n        // Warm, two-layer shadow: a tight contact shadow for definition,\n        // a wider diffuse one tinted toward ink rather than pure grey.\n        boxShadow:\n          '0 1px 2px rgba(42, 36, 32, 0.10), 0 20px 44px -14px rgba(42, 36, 32, 0.22), 0 8px 20px -10px rgba(42, 36, 32, 0.14)',\n        pointerEvents: 'none',\n        ...POSITIONS[action.position],\n      }}\n      data-role=\"ghost-reference\"\n    >\n      {/* Vertical footnote rule — classical book-design accent. Draws\n         downward from the top on entry like a typesetter's ruler. */}\n      <motion.span\n        aria-hidden\n        initial={{ scaleY: 0 }}\n        animate={{ scaleY: 1 }}\n        exit={{ scaleY: 0 }}\n        transition={{ duration: 0.55, delay: 0.06, ease: [0.22, 1, 0.36, 1] }}\n        style={{\n          position: 'absolute',\n          left: 0,\n          top: 0,\n          bottom: 0,\n          width: 3,\n          background: ACCENT,\n          transformOrigin: 'top',\n        }}\n      />\n\n      {/* Paper texture: a whisper of warm gradient + noise simulated with\n         overlapping radial highlights for subtle \"laid paper\" depth. */}\n      <span\n        aria-hidden\n        style={{\n          position: 'absolute',\n          inset: 0,\n          pointerEvents: 'none',\n          background: `\n            radial-gradient(120% 80% at 0% 0%, rgba(255, 244, 220, 0.5) 0%, transparent 55%),\n            radial-gradient(100% 80% at 100% 100%, rgba(243, 229, 200, 0.35) 0%, transparent 60%)\n          `,\n        }}\n      />\n\n      <div\n        style={{\n          position: 'relative',\n          // Padding scales with viewport: compact on phones, breathing on\n          // desktop. Extra 4px on the left preserves the footnote-rule gap.\n          padding:\n            'clamp(14px, 1.4vw + 10px, 26px) clamp(14px, 1.4vw + 10px, 26px) clamp(14px, 1.4vw + 10px, 26px) clamp(18px, 1.4vw + 14px, 30px)',\n          display: 'flex',\n          gap: 'clamp(12px, 1.1vw + 8px, 20px)',\n          alignItems: 'flex-start',\n        }}\n      >\n        {/* Locator — a stylised page thumbnail with simulated text lines\n           so the miniature feels like a page rather than an abstract\n           rectangle. Target region highlighted in the accent colour. */}\n        <motion.div\n          aria-hidden\n          initial={{ opacity: 0, scale: 0.92 }}\n          animate={{ opacity: 1, scale: 1 }}\n          exit={{ opacity: 0, scale: 0.92 }}\n          transition={{ duration: 0.45, delay: 0.18, ease: [0.22, 1, 0.36, 1] }}\n          style={{\n            flexShrink: 0,\n            width: 'clamp(40px, 4vw + 20px, 64px)',\n            aspectRatio: `${page.width} / ${page.height}`,\n            background: PAPER_DEEP,\n            borderRadius: 2,\n            overflow: 'hidden',\n            boxShadow:\n              'inset 0 0 0 1px rgba(42, 36, 32, 0.12), 0 1px 3px rgba(42, 36, 32, 0.10)',\n          }}\n        >\n          <svg\n            width=\"100%\"\n            height=\"100%\"\n            viewBox={`0 0 ${page.width} ${page.height}`}\n            preserveAspectRatio=\"xMidYMid meet\"\n            style={{ display: 'block' }}\n          >\n            <rect\n              x={0}\n              y={0}\n              width={page.width}\n              height={page.height}\n              fill={PAPER_DEEP}\n            />\n            {/* Faux text lines — vary widths for natural typographic\n               rhythm. They're all grey; the accent is reserved for the\n               target region so the eye tracks to it first. */}\n            {TEXT_LINES.map((ln, i) => (\n              <rect\n                key={i}\n                x={page.width * ln.x}\n                y={page.height * ln.y}\n                width={page.width * ln.w}\n                height={page.height * 0.012}\n                fill=\"rgba(42, 36, 32, 0.18)\"\n              />\n            ))}\n            {/* Target region — pill of accent colour, stroked. */}\n            <rect\n              x={x1}\n              y={y1}\n              width={x2 - x1}\n              height={y2 - y1}\n              fill=\"rgba(176, 74, 26, 0.28)\"\n              stroke={ACCENT}\n              strokeWidth={18}\n            />\n          </svg>\n        </motion.div>\n\n        {/* Referenced text — classical serif, generous leading, hanging\n           glyph. A single terracotta glyph pulls the eye into the quote\n           and ties the text back to the rule and target region. */}\n        <motion.div\n          initial={{ opacity: 0, y: 6 }}\n          animate={{ opacity: 1, y: 0 }}\n          exit={{ opacity: 0 }}\n          transition={{ duration: 0.5, delay: 0.26, ease: [0.22, 1, 0.36, 1] }}\n          style={{\n            flex: 1,\n            minWidth: 0,\n            fontFamily: SERIF,\n            fontSize: PILL_FONT_DISPLAY,\n            lineHeight: 1.55,\n            color: INK,\n            fontFeatureSettings: \"'liga' 1, 'kern' 1, 'onum' 1\",\n            textRendering: 'optimizeLegibility',\n            letterSpacing: 0.05,\n            // Hang an ornamental opening glyph outside the text column\n            // so the reader's eye falls into the paragraph as if into a\n            // well-set pull quote.\n            position: 'relative',\n            paddingLeft: 2,\n          }}\n        >\n          <span\n            aria-hidden\n            style={{\n              position: 'absolute',\n              left: -14,\n              top: -2,\n              color: ACCENT,\n              fontSize: 'clamp(18px, 1vw + 14px, 28px)',\n              lineHeight: 1,\n              fontWeight: 500,\n              // ornamental flourish anchoring the paragraph\n            }}\n          >\n            ❧\n          </span>\n          <span\n            style={{\n              display: '-webkit-box',\n              WebkitLineClamp: 8,\n              WebkitBoxOrient: 'vertical',\n              overflow: 'hidden',\n            }}\n          >\n            {text}\n          </span>\n        </motion.div>\n      </div>\n\n      {/* Foot ornament: a short hairline rule at the bottom-right, the\n         signature of a well-typeset aside. */}\n      <motion.span\n        aria-hidden\n        initial={{ scaleX: 0, opacity: 0 }}\n        animate={{ scaleX: 1, opacity: 0.6 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration: 0.5, delay: 0.42, ease: [0.22, 1, 0.36, 1] }}\n        style={{\n          position: 'absolute',\n          right: 22,\n          bottom: 10,\n          height: 1,\n          width: 28,\n          background: ACCENT,\n          transformOrigin: 'right',\n        }}\n      />\n    </motion.div>\n  );\n}\n\n/**\n * Pre-computed faux text lines for the locator thumbnail. Positions are\n * fractions of page dimensions so the lines scale with any aspect ratio.\n * Mild width variation mimics real paragraph ragging.\n */\nconst TEXT_LINES: ReadonlyArray<{ x: number; y: number; w: number }> = [\n  { x: 0.10, y: 0.12, w: 0.54 },\n  { x: 0.10, y: 0.18, w: 0.68 },\n  { x: 0.10, y: 0.24, w: 0.48 },\n  { x: 0.10, y: 0.34, w: 0.72 },\n  { x: 0.10, y: 0.40, w: 0.62 },\n  { x: 0.10, y: 0.46, w: 0.66 },\n  { x: 0.10, y: 0.56, w: 0.56 },\n  { x: 0.10, y: 0.62, w: 0.70 },\n  { x: 0.10, y: 0.68, w: 0.44 },\n  { x: 0.10, y: 0.78, w: 0.64 },\n  { x: 0.10, y: 0.84, w: 0.58 },\n];\n","'use client';\n\nimport React from 'react';\nimport { AnimatePresence } from 'framer-motion';\nimport { StickyLabel } from './StickyLabel';\nimport type { ActiveOverlay, ActionLabel, CameraState } from '../../types/storyboard';\nimport type { BBoxIndex, PageBBoxData, BBoxCoords } from '../../types/bbox';\n\nexport interface LabelOverlayProps {\n  overlays: ActiveOverlay[];\n  index: BBoxIndex;\n  currentPage: number;\n  camera: CameraState;\n  viewport: { width: number; height: number };\n}\n\n/**\n * Hosts `label` overlays at viewport space, OUTSIDE the CameraView scale\n * transform — so the pin body always renders at natural size (readable\n * at fit-page zoom) and its typography is never crushed.\n *\n * To keep the pin tethered to its block we compute the screen-space\n * anchor ourselves using the current camera state. The outer container\n * centres the page and applies `transform: scale(camera.scale)\n * translate(camera.x, camera.y)` — the exact math of CameraView. We\n * then project the block's bbox centre (in PDF units) onto the\n * viewport and place the pin there.\n *\n * When the camera animates (CameraView uses framer-motion), the store's\n * `camera.scale` / `x` / `y` update only at the boundary of each step.\n * Storyboards typically fire the label AFTER the camera move (100–300 ms\n * later), so by the time the label mounts the camera has settled at its\n * new values. Any mid-animation drift is imperceptible.\n */\nexport function LabelOverlay({\n  overlays,\n  index,\n  currentPage,\n  camera,\n  viewport,\n}: LabelOverlayProps): React.ReactElement {\n  const labels = overlays.filter((o) => o.kind === 'label');\n  const page = index.byPage.get(currentPage);\n\n  return (\n    <div\n      data-role=\"label-overlay\"\n      style={{\n        position: 'absolute',\n        inset: 0,\n        pointerEvents: 'none',\n        overflow: 'hidden',\n        // Above CameraView and the Reset button but not above\n        // GhostReferenceOverlay (z:70) — labels are block-attached and\n        // should not cover a cross-page reference card.\n        zIndex: 65,\n      }}\n    >\n      <AnimatePresence>\n        {page\n          ? labels.map((overlay) => {\n              const a = overlay.action as ActionLabel;\n              const hit = index.blockById.get(a.target_block);\n              if (!hit) return null;\n              const anchor = computeScreenAnchor(\n                hit.block.bbox,\n                a.position,\n                page,\n                camera,\n                viewport,\n              );\n              return (\n                <StickyLabel\n                  key={overlay.id}\n                  screenAnchor={anchor}\n                  action={a}\n                />\n              );\n            })\n          : null}\n      </AnimatePresence>\n    </div>\n  );\n}\n\n/**\n * Map a block's bbox edge midpoint (the logical anchor for the chosen\n * side) to viewport pixels, using the same geometry the PDF + CameraView\n * apply to the rendered page:\n *\n *   screenX = viewportCX + cameraX + (bboxPt.x − pageCX) × cameraScale\n *   screenY = viewportCY + cameraY + (bboxPt.y − pageCY) × cameraScale\n *\n * `viewportCX/Y` are the viewport's centre, matched to the\n * `top: 50%; left: 50%; translate(-50%,-50%)` wrapper in\n * TutorModeContainer. `cameraX/Y` are the CameraView translate; they\n * are already in viewport pixels (applied post-scale by CameraView, so\n * we add them directly).\n */\nfunction computeScreenAnchor(\n  bbox: BBoxCoords,\n  where: ActionLabel['position'],\n  page: PageBBoxData,\n  camera: CameraState,\n  viewport: { width: number; height: number },\n): { x: number; y: number } {\n  const [x1, y1, x2, y2] = bbox;\n  const pageCX = page.page_dimensions.width / 2;\n  const pageCY = page.page_dimensions.height / 2;\n\n  // Block anchor point in PDF units — midpoint of the chosen edge.\n  let px: number, py: number;\n  switch (where) {\n    case 'top':\n      px = (x1 + x2) / 2;\n      py = y1;\n      break;\n    case 'bottom':\n      px = (x1 + x2) / 2;\n      py = y2;\n      break;\n    case 'left':\n      px = x1;\n      py = (y1 + y2) / 2;\n      break;\n    case 'right':\n      px = x2;\n      py = (y1 + y2) / 2;\n      break;\n    default:\n      px = (x1 + x2) / 2;\n      py = y1;\n  }\n\n  const screenX =\n    viewport.width / 2 + camera.x + (px - pageCX) * camera.scale;\n  const screenY =\n    viewport.height / 2 + camera.y + (py - pageCY) * camera.scale;\n\n  return { x: screenX, y: screenY };\n}\n","import React from 'react';\nimport { motion } from 'framer-motion';\nimport type { ActionLabel } from '../../types/storyboard';\nimport {\n  ACCENT,\n  INK,\n  PAPER,\n  PILL_FONT_BODY,\n  PILL_MAX_W_BODY,\n  SERIF,\n} from './tokens';\n\nexport interface StickyLabelProps {\n  /**\n   * Pre-computed anchor point in viewport pixels — the label will be\n   * placed at this point and positioned relative to it via\n   * `action.position`. See `LabelOverlay` for the coordinate math that\n   * maps a block's bbox + camera state to this value.\n   */\n  screenAnchor: { x: number; y: number };\n  action: ActionLabel;\n}\n\n/**\n * Gap between the label body and its anchor block edge, in viewport\n * pixels. Large enough that the connecting stem is readable as\n * connective tissue between tag and target.\n */\nconst STEM = 18;\n\n/**\n * Editorial annotation pin. The label body sits a short distance from\n * the target block, connected by a hairline stem and a small marker\n * disc at the anchor point. Body uses a classical serif at small-caps\n * sizing — feels like a scholar's tag, not a browser toast.\n *\n * Positioning math: caller pre-computes the `screenAnchor` (usually the\n * midpoint of the block edge the label is attached to), and this\n * component lays out the pin on the appropriate side via CSS translate\n * offsets.\n */\nexport function StickyLabel({ screenAnchor, action }: StickyLabelProps) {\n  const { x, y } = screenAnchor;\n  const layout = LAYOUTS[action.position] ?? LAYOUTS.top;\n\n  return (\n    <motion.div\n      initial={{ opacity: 0, scale: 0.88 }}\n      animate={{ opacity: 1, scale: 1 }}\n      exit={{ opacity: 0, scale: 0.92 }}\n      transition={{\n        duration: 0.4,\n        ease: [0.22, 1, 0.36, 1],\n      }}\n      style={{\n        position: 'absolute',\n        left: x,\n        top: y,\n        // Wrapper positions at the anchor; the body's transform places\n        // it on the correct side via `layout.containerTransform`.\n        transform: layout.containerTransform,\n        pointerEvents: 'none',\n        // Compose transform-origin toward the anchor so scale-in feels\n        // tethered to the block rather than free-floating.\n        transformOrigin: layout.origin,\n      }}\n      data-role=\"label\"\n    >\n      {/* Hairline stem — the visible link between label body and anchor. */}\n      <motion.span\n        aria-hidden\n        initial={{ scaleX: 0, scaleY: 0, opacity: 0 }}\n        animate={{ scaleX: 1, scaleY: 1, opacity: 1 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration: 0.35, ease: [0.22, 1, 0.36, 1] }}\n        style={{\n          position: 'absolute',\n          background: ACCENT,\n          transformOrigin: layout.stemOrigin,\n          ...layout.stem,\n        }}\n      />\n      {/* Anchor dot — a small marker disc planted on the block edge. */}\n      <motion.span\n        aria-hidden\n        initial={{ scale: 0 }}\n        animate={{ scale: 1 }}\n        exit={{ scale: 0 }}\n        transition={{ duration: 0.3, delay: 0.15, ease: [0.22, 1, 0.36, 1] }}\n        style={{\n          position: 'absolute',\n          width: 6,\n          height: 6,\n          borderRadius: '50%',\n          background: ACCENT,\n          boxShadow: `0 0 0 2px ${PAPER}, 0 0 0 3px rgba(176, 74, 26, 0.25)`,\n          ...layout.dot,\n        }}\n      />\n      {/* Label body — paper pill with a left accent rule and eyebrow text. */}\n      <motion.div\n        initial={{ y: layout.bodyIn.y, x: layout.bodyIn.x, opacity: 0 }}\n        animate={{ y: 0, x: 0, opacity: 1 }}\n        exit={{ opacity: 0 }}\n        transition={{ duration: 0.4, delay: 0.08, ease: [0.22, 1, 0.36, 1] }}\n        style={{\n          position: 'absolute',\n          ...layout.bodyAnchor,\n          background: PAPER,\n          color: INK,\n          border: '1px solid rgba(42, 36, 32, 0.10)',\n          borderRadius: 3,\n          padding: '6px 12px 6px 14px',\n          fontFamily: SERIF,\n          fontSize: PILL_FONT_BODY,\n          lineHeight: 1.25,\n          letterSpacing: 0.6,\n          textTransform: 'uppercase',\n          fontWeight: 500,\n          // Wrap instead of truncating with an ellipsis. Short labels stay\n          // single-line; longer ones grow in height rather than losing\n          // their tail. `overflowWrap: 'break-word'` respects min-content\n          // sizing so a single overflowing word mid-breaks at a safe\n          // boundary — unlike `anywhere`, which would collapse the pill\n          // to 1-char min width and stack every letter on its own line.\n          maxWidth: PILL_MAX_W_BODY,\n          whiteSpace: 'normal',\n          overflowWrap: 'break-word',\n          // Warm two-layer shadow (matches GhostReference's palette).\n          boxShadow:\n            '0 1px 2px rgba(42, 36, 32, 0.12), 0 8px 18px -6px rgba(42, 36, 32, 0.22)',\n          // Internal left accent rule — a 2px terracotta stripe.\n          backgroundImage: `linear-gradient(to right, ${ACCENT} 0, ${ACCENT} 2px, transparent 2px)`,\n          backgroundRepeat: 'no-repeat',\n          backgroundSize: '2px 100%',\n          backgroundPosition: 'left top',\n        }}\n      >\n        {action.text}\n      </motion.div>\n    </motion.div>\n  );\n}\n\n/**\n * Per-side geometry for the pin. Each entry encodes:\n * - `containerTransform`   — how to offset the wrapper from the anchor point\n * - `origin`               — transform-origin for the scale-in (points at anchor)\n * - `stem`                 — absolute-positioned rule connecting body ↔ dot\n * - `stemOrigin`           — scale-in origin for the stem (grows from the anchor)\n * - `dot`                  — offset for the anchor dot\n * - `bodyAnchor`           — absolute offsets for the body pill\n * - `bodyIn`               — initial translate for the body's entrance animation\n */\ntype LayoutSpec = {\n  containerTransform: string;\n  origin: string;\n  stem: React.CSSProperties;\n  stemOrigin: string;\n  dot: React.CSSProperties;\n  bodyAnchor: React.CSSProperties;\n  bodyIn: { x: number; y: number };\n};\n\nconst LAYOUTS: Record<ActionLabel['position'], LayoutSpec> = {\n  top: {\n    containerTransform: 'translate(-50%, -100%)',\n    origin: '50% 100%',\n    stem: {\n      left: '50%',\n      bottom: -STEM,\n      width: 1,\n      height: STEM - 4,\n      transform: 'translateX(-50%)',\n    },\n    stemOrigin: 'bottom',\n    dot: {\n      left: '50%',\n      bottom: -STEM + 1,\n      transform: 'translate(-50%, 100%)',\n    },\n    bodyAnchor: { bottom: 0, left: '50%', transform: 'translateX(-50%)' },\n    bodyIn: { x: 0, y: -4 },\n  },\n  bottom: {\n    containerTransform: 'translate(-50%, 0%)',\n    origin: '50% 0%',\n    stem: {\n      left: '50%',\n      top: STEM - (STEM - 4),\n      width: 1,\n      height: STEM - 4,\n      transform: 'translateX(-50%)',\n    },\n    stemOrigin: 'top',\n    dot: {\n      left: '50%',\n      top: -1,\n      transform: 'translate(-50%, -100%)',\n    },\n    bodyAnchor: { top: STEM, left: '50%', transform: 'translateX(-50%)' },\n    bodyIn: { x: 0, y: 4 },\n  },\n  left: {\n    containerTransform: 'translate(-100%, -50%)',\n    origin: '100% 50%',\n    stem: {\n      top: '50%',\n      right: -STEM,\n      width: STEM - 4,\n      height: 1,\n      transform: 'translateY(-50%)',\n    },\n    stemOrigin: 'right',\n    dot: {\n      right: -STEM + 1,\n      top: '50%',\n      transform: 'translate(100%, -50%)',\n    },\n    bodyAnchor: { right: 0, top: '50%', transform: 'translateY(-50%)' },\n    bodyIn: { x: -4, y: 0 },\n  },\n  right: {\n    containerTransform: 'translate(0%, -50%)',\n    origin: '0% 50%',\n    stem: {\n      top: '50%',\n      left: STEM - (STEM - 4),\n      width: STEM - 4,\n      height: 1,\n      transform: 'translateY(-50%)',\n    },\n    stemOrigin: 'left',\n    dot: {\n      left: -1,\n      top: '50%',\n      transform: 'translate(-100%, -50%)',\n    },\n    bodyAnchor: { left: STEM, top: '50%', transform: 'translateY(-50%)' },\n    bodyIn: { x: 4, y: 0 },\n  },\n};\n","'use client';\n\nimport React from 'react';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport type {\n  ActiveOverlay,\n  ActionCallout,\n  CameraState,\n} from '../../types/storyboard';\nimport type { BBoxIndex, PageBBoxData, BBoxCoords } from '../../types/bbox';\nimport {\n  ACCENT,\n  EASE_OUT_EXPO,\n  INK,\n  PAPER,\n  PILL_FONT_CAPS,\n  PILL_MAX_W_CAPS,\n  resolveMaxPillH,\n  resolveMaxPillW,\n  resolvePillOffset,\n  SERIF,\n} from './tokens';\n\nexport interface CalloutLabelOverlayProps {\n  overlays: ActiveOverlay[];\n  index: BBoxIndex;\n  currentPage: number;\n  camera: CameraState;\n  viewport: { width: number; height: number };\n}\n\n/**\n * Hosts callout label pills at viewport space. The arrow stroke and\n * arrowhead still live inside CameraView (drawn by `CalloutArrow`)\n * because strokes scale readably with the camera; the LABEL alone is\n * lifted out because small-caps text at fit-scale (~0.22×) becomes\n * unreadable pixel dust.\n *\n * The pill is anchored near the arrow's endpoint, shifted\n * perpendicular to the arrow direction so it never sits under the\n * caret. Screen position is computed from the two bboxes + camera\n * state using the same projection math as LabelOverlay.\n */\nexport function CalloutLabelOverlay({\n  overlays,\n  index,\n  currentPage,\n  camera,\n  viewport,\n}: CalloutLabelOverlayProps): React.ReactElement {\n  const callouts = overlays.filter(\n    (o) => o.kind === 'callout' && (o.action as ActionCallout).label,\n  );\n  const page = index.byPage.get(currentPage);\n\n  return (\n    <div\n      data-role=\"callout-label-overlay\"\n      style={{\n        position: 'absolute',\n        inset: 0,\n        pointerEvents: 'none',\n        overflow: 'hidden',\n        // Above the arrow stroke (which is inside CameraView) and the\n        // reset button, below the ghost card.\n        zIndex: 68,\n      }}\n    >\n      <AnimatePresence>\n        {page\n          ? callouts.map((overlay) => {\n              const a = overlay.action as ActionCallout;\n              const fromHit = index.blockById.get(a.from_block);\n              const toHit = index.blockById.get(a.to_block);\n              if (!fromHit || !toHit || !a.label) return null;\n              const pos = computePillAnchor(\n                fromHit.block.bbox,\n                toHit.block.bbox,\n                page,\n                camera,\n                viewport,\n              );\n              return (\n                <CalloutLabelPill\n                  key={overlay.id}\n                  label={a.label}\n                  anchor={pos}\n                  side={pos.side}\n                />\n              );\n            })\n          : null}\n      </AnimatePresence>\n    </div>\n  );\n}\n\ntype Side = 'right' | 'left' | 'below' | 'above';\n\n/**\n * Anchor the pill NEAR the arrow's destination tip, offset perpendicular\n * to the arrow's dominant orientation. Two anchors were considered:\n *\n *   - midpoint: centres the pill along the arrow's length, but for long\n *     arrows (e.g., a caption pointing down to a figure across half the\n *     page) the midpoint lands in no-man's-land far from either endpoint,\n *     so the reader can't tell where the arrow is actually pointing.\n *   - tip: keeps the pill near the destination (\"this is what the arrow\n *     points to\"), and with a perpendicular offset the pill sits\n *     alongside the tip rather than on top of it.\n *\n * Tip wins. Tested on vertical arrows (caption → figure), horizontal\n * arrows (compare A ↔ B), and diagonal callouts.\n *\n * Side selection:\n *   - Vertical-ish arrow (|dy| ≥ |dx|) → pill to the right (flip to left\n *     if no room in the viewport).\n *   - Horizontal-ish arrow            → pill below (flip to above).\n */\nfunction computePillAnchor(\n  fromBbox: BBoxCoords,\n  toBbox: BBoxCoords,\n  page: PageBBoxData,\n  camera: CameraState,\n  viewport: { width: number; height: number },\n): { x: number; y: number; side: Side } {\n  const aCX = (fromBbox[0] + fromBbox[2]) / 2;\n  const aCY = (fromBbox[1] + fromBbox[3]) / 2;\n  const bCX = (toBbox[0] + toBbox[2]) / 2;\n  const bCY = (toBbox[1] + toBbox[3]) / 2;\n  const dx = bCX - aCX;\n  const dy = bCY - aCY;\n  const len = Math.hypot(dx, dy) || 1;\n  const ux = dx / len;\n  const uy = dy / len;\n\n  // Arrow tip in PDF space (matches CalloutArrow.edgePoints).\n  const bHalfW = (toBbox[2] - toBbox[0]) / 2;\n  const bHalfH = (toBbox[3] - toBbox[1]) / 2;\n  const bOff = Math.min(Math.max(bHalfW, bHalfH), 60);\n  const toX = bCX - ux * bOff;\n  const toY = bCY - uy * bOff;\n\n  // Project tip to viewport pixels.\n  const pageCX = page.page_dimensions.width / 2;\n  const pageCY = page.page_dimensions.height / 2;\n  const tipScreenX =\n    viewport.width / 2 + camera.x + (toX - pageCX) * camera.scale;\n  const tipScreenY =\n    viewport.height / 2 + camera.y + (toY - pageCY) * camera.scale;\n\n  const isVertical = Math.abs(dy) >= Math.abs(dx);\n\n  // Viewport-aware geometry — tracks the same clamp curves as the pill's\n  // CSS font/max-width so the JS auto-flip decision agrees with the\n  // rendered size. On a 1440 px desktop OFFSET ~= 44 px; on a 375 px phone\n  // OFFSET ~= 20 px.\n  const OFFSET = resolvePillOffset(viewport.width);\n  const MAX_PILL_W = resolveMaxPillW(viewport.width);\n  const MAX_PILL_H = resolveMaxPillH(viewport.width);\n  const SAFE = 16;\n\n  if (isVertical) {\n    const canFitRight =\n      tipScreenX + OFFSET + MAX_PILL_W < viewport.width - SAFE;\n    const side: Side = canFitRight ? 'right' : 'left';\n    return {\n      x: tipScreenX + (side === 'right' ? OFFSET : -OFFSET),\n      y: tipScreenY,\n      side,\n    };\n  }\n\n  const canFitBelow =\n    tipScreenY + OFFSET + MAX_PILL_H < viewport.height - SAFE;\n  const side: Side = canFitBelow ? 'below' : 'above';\n  return {\n    x: tipScreenX,\n    y: tipScreenY + (side === 'below' ? OFFSET : -OFFSET),\n    side,\n  };\n}\n\n/**\n * Editorial label pill — matches StickyLabel's vocabulary: cream paper,\n * terracotta accent rule, classical serif small-caps.\n *\n * The edge of the pill closest to the arrow is anchored at the offset\n * point, and the accent rule sits on that same \"inward\" edge so the\n * pill visually points back at the arrow regardless of side.\n */\nfunction CalloutLabelPill({\n  label,\n  anchor,\n  side,\n}: {\n  label: string;\n  anchor: { x: number; y: number };\n  side: Side;\n}) {\n  // Per-side geometry: how to position the pill relative to the anchor,\n  // where to put the accent rule, and which direction to slide in from.\n  const spec = PILL_SIDE_SPECS[side];\n  return (\n    <motion.div\n      initial={{ opacity: 0, scale: 0.92, ...spec.slideIn }}\n      animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}\n      exit={{ opacity: 0, scale: 0.94 }}\n      transition={{ duration: 0.45, delay: 0.5, ease: EASE_OUT_EXPO }}\n      style={{\n        position: 'absolute',\n        left: anchor.x,\n        top: anchor.y,\n        transform: spec.transform,\n        pointerEvents: 'none',\n        background: PAPER,\n        color: INK,\n        border: '1px solid rgba(42, 36, 32, 0.10)',\n        borderRadius: 3,\n        padding: spec.padding,\n        fontFamily: SERIF,\n        fontSize: PILL_FONT_CAPS,\n        lineHeight: 1.2,\n        letterSpacing: 0.6,\n        textTransform: 'uppercase',\n        fontWeight: 500,\n        // Wrap instead of truncating. Short labels stay single-line;\n        // longer ones grow taller rather than losing their tail to an\n        // ellipsis. `overflowWrap: 'break-word'` respects min-content\n        // sizing — `anywhere` here caused the pill to collapse to 1-char\n        // width and stack each letter on its own line when the clamped\n        // maxWidth was narrow.\n        maxWidth: PILL_MAX_W_CAPS,\n        whiteSpace: 'normal',\n        overflowWrap: 'break-word',\n        boxShadow:\n          '0 1px 2px rgba(42, 36, 32, 0.12), 0 8px 18px -6px rgba(42, 36, 32, 0.22)',\n        // Accent rule on the \"inward\" edge (the one closest to the arrow).\n        backgroundImage: spec.accentGradient,\n        backgroundRepeat: 'no-repeat',\n        backgroundSize: spec.accentSize,\n        backgroundPosition: spec.accentPosition,\n      }}\n      data-role=\"callout-label\"\n    >\n      {label}\n    </motion.div>\n  );\n}\n\ntype SideSpec = {\n  /** Which edge of the pill sits at (anchor.x, anchor.y). */\n  transform: string;\n  /** Slight slide-in direction that reads as \"emerging from the arrow\". */\n  slideIn: { x?: number; y?: number };\n  padding: string;\n  /** Linear gradient producing a 2 px accent rule on the inward edge. */\n  accentGradient: string;\n  accentSize: string;\n  accentPosition: string;\n};\n\nconst PILL_SIDE_SPECS: Record<Side, SideSpec> = {\n  // Pill sits to the RIGHT of a vertical arrow → left edge anchors at\n  // offset point, accent rule on the left (pointing back toward arrow).\n  right: {\n    transform: 'translate(0, -50%)',\n    slideIn: { x: -6 },\n    padding: '5px 12px 5px 14px',\n    accentGradient: `linear-gradient(to right, ${ACCENT} 0, ${ACCENT} 2px, transparent 2px)`,\n    accentSize: '2px 100%',\n    accentPosition: 'left top',\n  },\n  left: {\n    transform: 'translate(-100%, -50%)',\n    slideIn: { x: 6 },\n    padding: '5px 14px 5px 12px',\n    accentGradient: `linear-gradient(to left, ${ACCENT} 0, ${ACCENT} 2px, transparent 2px)`,\n    accentSize: '2px 100%',\n    accentPosition: 'right top',\n  },\n  // Pill sits BELOW a horizontal arrow → top edge anchors at offset\n  // point, accent rule on the top (pointing back up toward arrow).\n  below: {\n    transform: 'translate(-50%, 0)',\n    slideIn: { y: -6 },\n    padding: '7px 12px 5px 12px',\n    accentGradient: `linear-gradient(to bottom, ${ACCENT} 0, ${ACCENT} 2px, transparent 2px)`,\n    accentSize: '100% 2px',\n    accentPosition: 'left top',\n  },\n  above: {\n    transform: 'translate(-50%, -100%)',\n    slideIn: { y: 6 },\n    padding: '5px 12px 7px 12px',\n    accentGradient: `linear-gradient(to top, ${ACCENT} 0, ${ACCENT} 2px, transparent 2px)`,\n    accentSize: '100% 2px',\n    accentPosition: 'left bottom',\n  },\n};\n","'use client';\n\nimport React from 'react';\nimport { AnimatePresence, motion } from 'framer-motion';\n\nexport interface SubtitleBarProps {\n  text: string | null;\n}\n\nexport function SubtitleBar({ text }: SubtitleBarProps) {\n  return (\n    <AnimatePresence>\n      {text ? (\n        <motion.div\n          key={text}\n          initial={{ opacity: 0, y: 20 }}\n          animate={{ opacity: 1, y: 0 }}\n          exit={{ opacity: 0, y: 20 }}\n          transition={{ duration: 0.3 }}\n          style={{\n            position: 'absolute',\n            left: '50%',\n            bottom: 32,\n            transform: 'translateX(-50%)',\n            background: 'rgba(0,0,0,0.75)',\n            color: 'white',\n            padding: '10px 18px',\n            borderRadius: 8,\n            maxWidth: '80%',\n            fontSize: 16,\n            lineHeight: 1.4,\n            fontFamily: 'system-ui, sans-serif',\n            pointerEvents: 'none',\n            zIndex: 50,\n            textAlign: 'center',\n          }}\n          data-role=\"subtitle-bar\"\n        >\n          {text}\n        </motion.div>\n      ) : null}\n    </AnimatePresence>\n  );\n}\n","import type {\n  Storyboard,\n  StoryboardStep,\n  StoryboardAction,\n  ActiveOverlay,\n  CameraState,\n} from '../types/storyboard';\nimport type { BBoxIndex } from '../types/bbox';\nimport type { NarrationStoreApi } from '../store/narration-store';\nimport { makeOverlayId } from '../store/narration-store';\nimport {\n  computeCameraForBlock,\n  fitPageScale,\n  clampCamera,\n  type ViewportSize,\n} from '../utils/camera-math';\nimport { isIOSMobile } from '../utils/mobile-config';\n\nexport interface EngineDeps {\n  narrationStore: NarrationStoreApi;\n  bboxIndex: BBoxIndex;\n  /** Callback to read current viewport size (pixels). */\n  getViewport: () => ViewportSize;\n  /**\n   * Minimum time (ms) an overlay stays on screen regardless of what\n   * `step.duration_ms` the LLM emitted. The schema caps duration at 5000ms\n   * and recipes typically suggest 600-1200ms — too short to register\n   * visually in a narration context. Default: 3500ms.\n   */\n  minOverlayDurationMs?: number;\n  /**\n   * When true, only ONE annotation overlay is on-screen at any time: every\n   * new overlay-emitting step first clears all prior overlays and their\n   * auto-removal timers.\n   *\n   * Defaults to `isIOSMobile()` — on iOS Safari/WebKit, stacking 2-3 overlays\n   * (e.g. highlight + box + underline + callout) on the same anchor is the\n   * single biggest remaining crash vector we've measured. The GPU\n   * compositor rejects the layer combination long before the canvas cap\n   * kicks in. Dropping to one overlay at a time sacrifices overlay chaining\n   * on iOS for a hard stability guarantee.\n   *\n   * Pass `false` explicitly to force multi-overlay mode even on iOS (e.g.\n   * for tests or a deliberate opt-out in the consumer).\n   */\n  singleActiveOverlay?: boolean;\n}\n\nconst DEFAULT_MIN_OVERLAY_MS = 3500;\n\nexport class StoryboardEngine {\n  private deps: EngineDeps;\n  /**\n   * Timers that schedule the START of a step (via `setTimeout(runStep, at_ms)`).\n   * These are storyboard-scoped: when a new storyboard arrives, anything still\n   * pending should be abandoned.\n   */\n  private pendingStepTimers = new Set<ReturnType<typeof setTimeout>>();\n  /**\n   * Timers that auto-REMOVE an already-placed overlay after its visible\n   * duration. Keyed by overlay id so we can cancel one specifically. These are\n   * NOT cancelled when a new storyboard starts — otherwise the still-visible\n   * overlay from the previous beat would get stranded in the store forever\n   * (the \"stuck spotlight\" bug).\n   */\n  private overlayRemovalTimers = new Map<\n    string,\n    ReturnType<typeof setTimeout>\n  >();\n  private currentStoryboardId = 0;\n  /**\n   * Resolved value of `deps.singleActiveOverlay`. Cached at construction so\n   * each step dispatch is a single branch rather than a per-call\n   * userAgent sniff, and so the policy stays stable for the engine's\n   * lifetime (a viewport flip that recreates the engine will re-evaluate).\n   */\n  private readonly singleActiveOverlay: boolean;\n\n  constructor(deps: EngineDeps) {\n    this.deps = deps;\n    this.singleActiveOverlay =\n      deps.singleActiveOverlay ?? isIOSMobile();\n  }\n\n  /**\n   * Execute a new storyboard. Cancels in-flight steps from the previous storyboard\n   * and smoothly transitions the camera/overlays from the current state.\n   */\n  execute(storyboard: Storyboard): void {\n    this.cancelPending();\n    this.currentStoryboardId += 1;\n    const storyboardId = this.currentStoryboardId;\n\n    const { narrationStore } = this.deps;\n    narrationStore.getState().setEngineStatus('transitioning');\n    narrationStore.getState().setLastStoryboard(storyboard);\n\n    // Sort steps by at_ms (LLM is not required to order them).\n    let steps = [...storyboard.steps].sort((a, b) => a.at_ms - b.at_ms);\n\n    // Camera auto-synthesis — re-centre safety net, NOT a creative choice.\n    // The prompt is now allowed to omit a camera step when the target is\n    // already on-screen (see prompts.ts \"When to use each action\"). When it\n    // does omit one, we still inject a scale:1.0 camera so the viewport\n    // re-centres on the focused block, but the lack of zoom keeps the beat\n    // visually neutral — overlay kinds (highlight/underline/pulse/etc.) stay\n    // the primary motion.\n    const hasCamera = steps.some((s) => s.action.type === 'camera');\n    if (!hasCamera) {\n      const focus = steps.find(\n        (s) =>\n          s.action.type !== 'clear' &&\n          'target_block' in s.action &&\n          s.action.target_block,\n      );\n      if (focus && focus.action.type !== 'clear' && 'target_block' in focus.action) {\n        steps = [\n          {\n            at_ms: 0,\n            duration_ms: 700,\n            action: {\n              type: 'camera',\n              target_block: focus.action.target_block as string,\n              scale: 1.0,\n              padding: 60,\n              easing: 'ease-out',\n            },\n          },\n          ...steps,\n        ];\n      }\n    }\n\n    for (const step of steps) {\n      const timer = setTimeout(() => {\n        if (storyboardId !== this.currentStoryboardId) return;\n        this.runStep(step);\n      }, step.at_ms);\n      this.pendingStepTimers.add(timer);\n    }\n\n    // Mark executing once the first step is scheduled.\n    const markExecuting = setTimeout(() => {\n      if (storyboardId !== this.currentStoryboardId) return;\n      narrationStore.getState().setEngineStatus('executing');\n    }, 0);\n    this.pendingStepTimers.add(markExecuting);\n\n    // Return to idle after the last step completes.\n    const last = steps[steps.length - 1];\n    if (last) {\n      const totalMs = last.at_ms + last.duration_ms;\n      const markIdle = setTimeout(() => {\n        if (storyboardId !== this.currentStoryboardId) return;\n        narrationStore.getState().setEngineStatus('idle');\n      }, totalMs + 50);\n      this.pendingStepTimers.add(markIdle);\n    }\n  }\n\n  /**\n   * Abort pending STEP dispatches from the current storyboard. Overlay\n   * removal timers are left alone so already-visible overlays still auto-\n   * expire on their own schedule. To force-clear every overlay, call\n   * `resetVisuals()` instead.\n   */\n  cancelPending(): void {\n    for (const t of this.pendingStepTimers) clearTimeout(t);\n    this.pendingStepTimers.clear();\n    this.deps.narrationStore.getState().setEngineStatus('idle');\n  }\n\n  /** Cancel every removal timer (used by resetVisuals and destroy). */\n  private cancelAllRemovalTimers(): void {\n    for (const t of this.overlayRemovalTimers.values()) clearTimeout(t);\n    this.overlayRemovalTimers.clear();\n  }\n\n  /**\n   * Full destructor — cancels BOTH pending step timers AND overlay\n   * removal timers. Use this in component unmount / cleanup.\n   *\n   * The per-storyboard `cancelPending()` deliberately leaves overlay\n   * removal timers alone so a mid-flight overlay doesn't get stranded\n   * when a new storyboard arrives (see `overlayRemovalTimers` doc).\n   * That invariant is correct inside a session, but at teardown we\n   * must release every timer — otherwise their setTimeout closures\n   * keep `deps` (narrationStore, the full bboxIndex) alive beyond the\n   * lifetime of this engine. Over many component recreations on iOS\n   * Safari (viewport state churns during address-bar scroll\n   * animation), that cumulative retention contributes to tab reloads.\n   */\n  destroy(): void {\n    this.cancelPending();\n    this.cancelAllRemovalTimers();\n  }\n\n  /** Test-only — exposes internal queue sizes for regression tests. */\n  _queueSizesForTest(): { pending: number; removals: number } {\n    return {\n      pending: this.pendingStepTimers.size,\n      removals: this.overlayRemovalTimers.size,\n    };\n  }\n\n  /** Reset visuals: clear overlays, cancel every removal timer, fit camera. */\n  resetVisuals(): void {\n    this.cancelPending();\n    this.cancelAllRemovalTimers();\n    const { narrationStore, bboxIndex, getViewport } = this.deps;\n    narrationStore.getState().clearOverlays();\n\n    const viewport = getViewport();\n    const currentPage = narrationStore.getState().currentPage;\n    const pageDims = bboxIndex.byPage.get(currentPage);\n    const fit =\n      pageDims && viewport.width > 0 && viewport.height > 0\n        ? fitPageScale(pageDims.page_dimensions, viewport) * 0.95\n        : 1;\n\n    narrationStore\n      .getState()\n      .setCamera({ scale: fit, x: 0, y: 0, easing: 'ease-in-out' });\n  }\n\n  /** Execute one step — dispatch to narrationStore. Returns true if applied. */\n  private runStep(step: StoryboardStep): boolean {\n    const action = step.action;\n    const { narrationStore, bboxIndex } = this.deps;\n\n    // Validate target_block references. Unknown ids mean the LLM picked a\n    // block_id that doesn't exist on the current page — surface it in the\n    // debug log so the user can see why nothing animated.\n    if ('target_block' in action && action.target_block) {\n      if (!bboxIndex.blockById.has(action.target_block)) {\n        narrationStore.getState().appendDebugEvent({\n          kind: 'llm-error',\n          summary: `dropped ${action.type} step → unknown target_block \"${action.target_block}\"`,\n          payload: { action, validIds: [...bboxIndex.blockById.keys()] },\n        });\n        return false;\n      }\n    }\n    if ('from_block' in action && action.from_block) {\n      if (!bboxIndex.blockById.has(action.from_block)) {\n        narrationStore.getState().appendDebugEvent({\n          kind: 'llm-error',\n          summary: `dropped ${action.type} step → unknown from_block \"${action.from_block}\"`,\n          payload: { action },\n        });\n        return false;\n      }\n    }\n    if ('to_block' in action && action.to_block) {\n      if (!bboxIndex.blockById.has(action.to_block)) {\n        narrationStore.getState().appendDebugEvent({\n          kind: 'llm-error',\n          summary: `dropped ${action.type} step → unknown to_block \"${action.to_block}\"`,\n          payload: { action },\n        });\n        return false;\n      }\n    }\n\n    if (action.type === 'camera') {\n      this.applyCamera(action, step.duration_ms);\n      return true;\n    }\n\n    if (action.type === 'clear') {\n      const targets = action.targets;\n      if (targets === 'all' || targets === 'overlays') {\n        narrationStore.getState().clearOverlays();\n      } else if (targets === 'spotlights') {\n        narrationStore\n          .getState()\n          .clearOverlays((o) => o.kind === 'spotlight');\n      } else if (Array.isArray(targets)) {\n        const ids = new Set(targets);\n        narrationStore.getState().clearOverlays((o) => ids.has(o.id));\n      }\n      return true;\n    }\n\n    // Overlay-emitting actions. Floor the visible duration so overlays don't\n    // flash past too quickly to register. LLM recipes emit ~600-1200ms; for\n    // a narration-paired experience we want each beat to breathe for several\n    // seconds so the student can track it.\n    const minMs = this.deps.minOverlayDurationMs ?? DEFAULT_MIN_OVERLAY_MS;\n    const visibleMs = Math.max(step.duration_ms, minMs);\n    const overlay: ActiveOverlay = {\n      id: makeOverlayId(action),\n      kind: action.type,\n      action,\n      createdAt: Date.now(),\n      expiresAt: Date.now() + visibleMs,\n    };\n\n    // iOS-mobile safety rail: enforce at most ONE annotation overlay on\n    // screen. Crashes we traced in Sentry on iPhone Safari cluster hard\n    // around the moment a second/third overlay composites on top of an\n    // existing one (highlight + box + underline on the same anchor).\n    // Clearing prior overlays + their auto-removal timers before adding\n    // the new one keeps the compositor working with exactly one SVG layer\n    // plus the base canvas at any instant. The next storyboard can still\n    // paint fresh overlays — only same-moment stacking is prevented.\n    if (this.singleActiveOverlay) {\n      this.cancelAllRemovalTimers();\n      narrationStore.getState().clearOverlays();\n    }\n\n    narrationStore.getState().addOverlay(overlay);\n\n    // Auto-remove when expired. This timer lives OUTSIDE pendingStepTimers so\n    // the next incoming storyboard (which cancels step dispatches) doesn't\n    // strand this overlay on screen forever.\n    const timer = setTimeout(() => {\n      narrationStore.getState().removeOverlay(overlay.id);\n      this.overlayRemovalTimers.delete(overlay.id);\n    }, visibleMs);\n    this.overlayRemovalTimers.set(overlay.id, timer);\n    return true;\n  }\n\n  private applyCamera(\n    action: Extract<StoryboardAction, { type: 'camera' }>,\n    durationMs: number,\n  ): void {\n    const { narrationStore, bboxIndex, getViewport } = this.deps;\n    const viewport = getViewport();\n\n    let bbox = action.target_bbox;\n    let pageDims: ReturnType<typeof bboxIndex.byPage.get> = undefined;\n\n    if (!bbox && action.target_block) {\n      const hit = bboxIndex.blockById.get(action.target_block);\n      if (!hit) return;\n      bbox = hit.block.bbox;\n      pageDims = bboxIndex.byPage.get(hit.pageNumber);\n    } else if (bbox) {\n      pageDims = bboxIndex.byPage.get(narrationStore.getState().currentPage);\n    }\n\n    if (!bbox || !pageDims) return;\n\n    // Camera math: interpret action.scale as \"N× fit-page\" (1 = fit-page,\n    // 1.5 = 50% closer, 2 = 2× fit-page). Hard cap at 3× to avoid the\n    // unreadably-zoomed-in pathology.\n    const fit = fitPageScale(pageDims.page_dimensions, viewport);\n    const requested = Math.max(0.5, Math.min(3, action.scale ?? 1));\n    const finalScale = fit * requested;\n\n    // Center the target block at the viewport center.\n    const [x1, y1, x2, y2] = bbox;\n    const blockCX = (x1 + x2) / 2;\n    const blockCY = (y1 + y2) / 2;\n    const pageCX = pageDims.page_dimensions.width / 2;\n    const pageCY = pageDims.page_dimensions.height / 2;\n    const rawX = (pageCX - blockCX) * finalScale;\n    const rawY = (pageCY - blockCY) * finalScale;\n\n    // Clamp the pan so the rendered page never pulls past the viewport edge.\n    // Without this, a block near the top/bottom of the page translates the\n    // whole sheet so far that the camera ends up staring at empty surround\n    // on one side. clampCamera caps |x|/|y| at (pageSize*scale - viewport)/2,\n    // which — for a page that doesn't even fill the viewport (scale ≤ fit) —\n    // snaps the offset to 0 (keep centred, don't pan). At higher zooms the\n    // target block still lands as close to centre as geometrically possible.\n    const clamped = clampCamera(\n      { scale: finalScale, x: rawX, y: rawY },\n      pageDims.page_dimensions,\n      viewport,\n    );\n\n    const camera: CameraState = {\n      scale: clamped.scale,\n      x: clamped.x,\n      y: clamped.y,\n      easing: action.easing,\n    };\n    narrationStore.getState().setCamera(camera);\n    void durationMs;\n    void computeCameraForBlock;\n  }\n}\n","import { z } from 'zod';\n\nconst BBoxCoordsSchema = z.tuple([z.number(), z.number(), z.number(), z.number()]);\n\nconst CameraSchema = z\n  .object({\n    type: z.literal('camera'),\n    target_block: z.string().optional(),\n    target_bbox: BBoxCoordsSchema.optional(),\n    scale: z.number().min(0.5).max(4).default(1),\n    padding: z.number().min(0).max(400).default(80),\n    easing: z\n      .enum(['linear', 'ease-in', 'ease-out', 'ease-in-out'])\n      .default('ease-in-out'),\n  })\n  .refine((a) => !!a.target_block || !!a.target_bbox, {\n    message: 'camera requires target_block or target_bbox',\n  });\n\nconst SpotlightSchema = z.object({\n  type: z.literal('spotlight'),\n  target_block: z.string(),\n  dim_opacity: z.number().min(0).max(1).default(0.65),\n  feather_px: z.number().min(0).max(200).default(40),\n  shape: z.enum(['rect', 'rounded', 'ellipse']).default('rounded'),\n});\n\nconst UnderlineSchema = z.object({\n  type: z.literal('underline'),\n  target_block: z.string(),\n  color: z.string().default('#FBBF24'),\n  style: z.enum(['straight', 'sketch', 'double', 'wavy']).default('sketch'),\n  draw_duration_ms: z.number().min(100).max(3000).default(600),\n});\n\nconst HighlightSchema = z.object({\n  type: z.literal('highlight'),\n  target_block: z.string(),\n  color: z.string().default('rgba(250, 204, 21, 0.35)'),\n  draw_duration_ms: z.number().min(100).max(3000).default(500),\n});\n\nconst PulseSchema = z.object({\n  type: z.literal('pulse'),\n  target_block: z.string(),\n  count: z.number().int().min(1).max(5).default(2),\n  intensity: z.enum(['subtle', 'normal', 'strong']).default('normal'),\n});\n\nconst CalloutSchema = z.object({\n  type: z.literal('callout'),\n  from_block: z.string(),\n  to_block: z.string(),\n  label: z.string().max(120).optional(),\n  curve: z.enum(['straight', 'curved', 'zigzag']).default('curved'),\n});\n\nconst GhostReferenceSchema = z.object({\n  type: z.literal('ghost_reference'),\n  target_page: z.number().int().min(1),\n  target_block: z.string(),\n  position: z\n    .enum(['top-right', 'top-left', 'bottom-right', 'bottom-left'])\n    .default('top-right'),\n});\n\nconst BoxSchema = z.object({\n  type: z.literal('box'),\n  target_block: z.string(),\n  color: z.string().default('#3B82F6'),\n  style: z.enum(['solid', 'dashed']).default('solid'),\n});\n\nconst LabelSchema = z.object({\n  type: z.literal('label'),\n  target_block: z.string(),\n  text: z.string().min(1).max(120),\n  position: z.enum(['top', 'bottom', 'left', 'right']).default('top'),\n});\n\nconst ClearSchema = z.object({\n  type: z.literal('clear'),\n  targets: z\n    .union([z.enum(['all', 'spotlights', 'overlays']), z.array(z.string())])\n    .default('overlays'),\n});\n\n// Note: CameraSchema uses .refine() so it isn't directly usable in\n// discriminatedUnion. Use z.union for the full action set; performance\n// impact is negligible for storyboards of up to 4 steps.\nexport const StoryboardActionSchema = z.union([\n  CameraSchema,\n  SpotlightSchema,\n  UnderlineSchema,\n  HighlightSchema,\n  PulseSchema,\n  CalloutSchema,\n  GhostReferenceSchema,\n  BoxSchema,\n  LabelSchema,\n  ClearSchema,\n]);\n\nexport const StoryboardStepSchema = z.object({\n  at_ms: z.number().min(0).max(5000).default(0),\n  duration_ms: z.number().min(100).max(5000).default(800),\n  action: StoryboardActionSchema,\n});\n\nexport const StoryboardSchema = z.object({\n  version: z.literal(1),\n  // `reasoning` was required in 0.4.x as a model-generated explanation used\n  // by DebugLog. It carries no visual effect and costs 50–150 output tokens\n  // per call, so from 0.5.1 it's optional (default empty). Consumers who\n  // still send it (from cached prompts or older directors) keep working —\n  // the field is still accepted, just not required.\n  reasoning: z.string().max(500).optional().default(''),\n  steps: z.array(StoryboardStepSchema).min(1).max(4),\n});\n\nexport type StoryboardParsed = z.infer<typeof StoryboardSchema>;\n\n/** Converts the zod schema to JSON Schema for use with OpenAI structured outputs.\n *\n * OpenAI's structured outputs validator requires:\n * - Every property has a `type` (no bare `const`/`enum` without `type`)\n * - All properties listed in `required`\n * - `additionalProperties: false` on every object\n *\n * We model the action union as a single object with all possible fields optional\n * at the schema level (validated strictly later by zod). This keeps the schema\n * compatible across providers; field-level required-ness is enforced post-parse.\n */\nexport interface StoryboardJsonSchemaOptions {\n  /** Block IDs valid for the CURRENT page. Constrains target_block / from_block / to_block. */\n  validBlockIds?: string[];\n  /** Block IDs valid for cross-page references (e.g., figures on other pages). */\n  validCrossPageBlockIds?: string[];\n}\n\nexport function storyboardJsonSchema(\n  opts: StoryboardJsonSchemaOptions = {},\n): Record<string, unknown> {\n  const { validBlockIds, validCrossPageBlockIds } = opts;\n\n  // When we have a concrete set of IDs, constrain the target to that enum so\n  // the LLM can't hallucinate IDs that don't exist on the page. Include null\n  // because OpenAI strict mode requires every declared field to be settable.\n  const blockIdSchema: Record<string, unknown> =\n    validBlockIds && validBlockIds.length > 0\n      ? { type: ['string', 'null'], enum: [...validBlockIds, null] }\n      : { type: ['string', 'null'] };\n\n  const crossPageBlockIdSchema: Record<string, unknown> =\n    validCrossPageBlockIds && validCrossPageBlockIds.length > 0\n      ? {\n          type: ['string', 'null'],\n          enum: [...validCrossPageBlockIds, ...(validBlockIds ?? []), null],\n        }\n      : blockIdSchema;\n\n  const actionSchema = {\n    type: 'object',\n    additionalProperties: false,\n    required: [\n      'type',\n      'target_block',\n      'target_bbox',\n      'scale',\n      'padding',\n      'easing',\n      'dim_opacity',\n      'feather_px',\n      'shape',\n      'color',\n      'style',\n      'draw_duration_ms',\n      'count',\n      'intensity',\n      'from_block',\n      'to_block',\n      'label',\n      'curve',\n      'target_page',\n      'position',\n      'text',\n      'targets',\n    ],\n    properties: {\n      type: {\n        type: 'string',\n        enum: [\n          'camera',\n          'spotlight',\n          'underline',\n          'highlight',\n          'pulse',\n          'callout',\n          'ghost_reference',\n          'box',\n          'label',\n          'clear',\n        ],\n      },\n      target_block: blockIdSchema,\n      target_bbox: {\n        type: ['array', 'null'],\n        items: { type: 'number' },\n        minItems: 4,\n        maxItems: 4,\n      },\n      scale: { type: ['number', 'null'] },\n      padding: { type: ['number', 'null'] },\n      easing: {\n        type: ['string', 'null'],\n        enum: ['linear', 'ease-in', 'ease-out', 'ease-in-out', null],\n      },\n      dim_opacity: { type: ['number', 'null'] },\n      feather_px: { type: ['number', 'null'] },\n      shape: {\n        type: ['string', 'null'],\n        enum: ['rect', 'rounded', 'ellipse', null],\n      },\n      color: { type: ['string', 'null'] },\n      style: {\n        type: ['string', 'null'],\n        enum: ['straight', 'sketch', 'double', 'wavy', 'solid', 'dashed', null],\n      },\n      draw_duration_ms: { type: ['number', 'null'] },\n      count: { type: ['integer', 'null'] },\n      intensity: {\n        type: ['string', 'null'],\n        enum: ['subtle', 'normal', 'strong', null],\n      },\n      from_block: blockIdSchema,\n      to_block: crossPageBlockIdSchema,\n      label: { type: ['string', 'null'] },\n      curve: {\n        type: ['string', 'null'],\n        enum: ['straight', 'curved', 'zigzag', null],\n      },\n      target_page: { type: ['integer', 'null'] },\n      position: {\n        type: ['string', 'null'],\n        enum: [\n          'top',\n          'bottom',\n          'left',\n          'right',\n          'top-right',\n          'top-left',\n          'bottom-right',\n          'bottom-left',\n          null,\n        ],\n      },\n      text: { type: ['string', 'null'] },\n      targets: {\n        type: ['string', 'null'],\n        enum: ['all', 'spotlights', 'overlays', null],\n      },\n    },\n  };\n\n  return {\n    type: 'object',\n    additionalProperties: false,\n    // `reasoning` intentionally omitted from `required` — the field is still\n    // accepted when present but the model doesn't need to generate it,\n    // which saves 50–150 output tokens per call. See zod schema above.\n    required: ['version', 'steps'],\n    properties: {\n      version: { type: 'integer', enum: [1] },\n      reasoning: { type: 'string' },\n      steps: {\n        type: 'array',\n        minItems: 1,\n        maxItems: 4,\n        items: {\n          type: 'object',\n          additionalProperties: false,\n          required: ['at_ms', 'duration_ms', 'action'],\n          properties: {\n            at_ms: { type: 'number' },\n            duration_ms: { type: 'number' },\n            action: actionSchema,\n          },\n        },\n      },\n    },\n  };\n}\n","import type { BBoxIndex, PageBBoxData } from '../types/bbox';\nimport type { CameraState, ActiveOverlay } from '../types/storyboard';\nimport type { ChunkHistoryEntry } from '../store/narration-store';\n\nexport const SYSTEM_PROMPT = `You are the cinematic director of an AI tutor's PDF visualization. The tutor speaks one \"chunk\" at a time; for each chunk you anchor the visuals onto the EXACT blocks on the page the tutor is talking about, so the reader sees the page react like a produced teaching video. Think of yourself as a motion designer layering effects on top of a document — zoom is only one tool in the kit, and often not the right one.\n\n# Your primary task\nYou are given a list of blocks for the current page under \"Page blocks\", each with a \\`block_id\\`, \\`text\\`, \\`type\\`, \\`bbox\\`, and \\`default_action\\`. Your #1 job is to decide WHICH block(s) the current chunk is referring to, and then pick the right visual action(s) to anchor there.\n\nAnchoring rules:\n- EVERY action that references a block MUST set \\`target_block\\` (or \\`from_block\\`/\\`to_block\\` for callouts) to an EXISTING \\`block_id\\` from \"Page blocks\" (or \"Cross-page figures index\" for cross-page refs). Never invent an id. Never emit a step whose target can't be found in the provided lists.\n- Match the chunk to blocks by semantic overlap with the block's \\`text\\`: quoted phrases, named entities, keywords, figure references (\"Fig 3.2\", \"the suture\"), list enumerations.\n- If no block clearly matches, emit a single \\`camera\\` step that fits the page (no overlays) and explain in \\`reasoning\\`. Do NOT spray overlays onto random blocks.\n- If multiple blocks match, pick the most specific one, or use a \\`callout\\` from one to the other.\n\n# Output shape\nOutput ONLY this JSON, nothing else:\n{\n  \"version\": 1,\n  \"steps\": [ { \"at_ms\": <int>, \"duration_ms\": <int>, \"action\": <action> }, ... ]\n}\n\n# Action shapes — ALL fields shown are REQUIRED per action type\n- camera:          { \"type\":\"camera\", \"target_block\":\"<id>\", \"scale\":1.1, \"padding\":80, \"easing\":\"ease-out\" }\n- spotlight:       { \"type\":\"spotlight\", \"target_block\":\"<id>\", \"dim_opacity\":0.65, \"feather_px\":40, \"shape\":\"rounded\" }\n- underline:       { \"type\":\"underline\", \"target_block\":\"<id>\", \"color\":\"#FBBF24\", \"style\":\"sketch\", \"draw_duration_ms\":600 }\n- highlight:       { \"type\":\"highlight\", \"target_block\":\"<id>\", \"color\":\"rgba(250,204,21,0.35)\", \"draw_duration_ms\":500 }\n- pulse:           { \"type\":\"pulse\", \"target_block\":\"<id>\", \"count\":2, \"intensity\":\"normal\" }\n- callout:         { \"type\":\"callout\", \"from_block\":\"<id>\", \"to_block\":\"<id>\", \"label\":\"<text>\", \"curve\":\"curved\" }\n- ghost_reference: { \"type\":\"ghost_reference\", \"target_page\":<int>, \"target_block\":\"<id>\", \"position\":\"top-right\" }\n- box:             { \"type\":\"box\", \"target_block\":\"<id>\", \"color\":\"#3B82F6\", \"style\":\"solid\" }\n- label:           { \"type\":\"label\", \"target_block\":\"<id>\", \"text\":\"<text>\", \"position\":\"top\" }\n- clear:           { \"type\":\"clear\", \"targets\":\"overlays\" }\n\n# When to use each action (match the effect to the narration's intent, not just the block type)\n- camera          — when focus SHIFTS to a new region. If the primary block is already on-screen and roughly centered, you may skip camera entirely and start with an overlay. When you do use camera, prefer scale 1.1–1.4 for gentle re-centering; reserve 1.5+ for dense figures you need to inspect closely.\n- spotlight       — when narration ISOLATES one idea, term, or sentence. Great for definitions, principles, and \"the key insight is…\" moments.\n- underline       — when narration QUOTES a phrase or reads a line word-by-word. Use style \"sketch\" for handwritten feel, \"straight\" for formal, \"wavy\" for emphasis. Pairs well with spotlight.\n- highlight       — when narration FLAGS a keyword inline without full focus. Cheap, fast, great for list items, definitions-in-context, callback references.\n- pulse           — when narration says \"notice this\" / \"see here\" / \"look at the diagram\". Use with figures, icons, and anchor blocks that should catch the eye without blocking surrounding content.\n- callout         — when narration CONNECTS two things on the page: a caption to its figure, a label to a region, one list item to another. Arrow implies directional meaning.\n- ghost_reference — when narration REFERS to a block on a DIFFERENT page (\"as we saw on page 2…\"). Never use for same-page references.\n- box             — when narration FRAMES a structural region: a table, a sidebar, a group of related items, a diagram subpart. Use dashed style for \"in-progress\" / \"under discussion\" regions.\n- label           — when narration attaches a NAMED TAG to a block: \"this is the definition\", \"this is an example\", \"step 3\". Keep text ≤40 chars for readability.\n- clear           — rarely needed; the engine auto-expires overlays. Use only when you explicitly want to wipe prior state before a new beat.\n\nRespect each block's \\`default_action\\` as a soft hint, but override it freely when narration intent calls for a different effect. A paragraph labeled \\`default_action: spotlight\\` can absolutely take a highlight or underline if that's what the narration asks for.\n\n# Intent Taxonomy — canonical \"recipes\" you should use as your default vocabulary\nWhen narration fits one of these patterns, emit the corresponding storyboard shape (fill in real block_ids from the page). You may also COMPOSE freely beyond these — they are a floor, not a ceiling.\n\n## define — the narration introduces or defines a term\nShape: spotlight the term + underline it + drop a label tag. No camera move if the block is already on-screen.\n{\n  \"version\": 1,\n  \"steps\": [\n    { \"at_ms\":0,   \"duration_ms\":700, \"action\": { \"type\":\"spotlight\", \"target_block\":\"p1_para0\", \"dim_opacity\":0.6, \"feather_px\":40, \"shape\":\"rounded\" } },\n    { \"at_ms\":200, \"duration_ms\":800, \"action\": { \"type\":\"underline\", \"target_block\":\"p1_para0\", \"color\":\"#FBBF24\", \"style\":\"sketch\", \"draw_duration_ms\":700 } },\n    { \"at_ms\":900, \"duration_ms\":1200, \"action\": { \"type\":\"label\", \"target_block\":\"p1_para0\", \"text\":\"definition\", \"position\":\"top\" } }\n  ]\n}\n\n## point_out — the narration directs the viewer's eye to a figure, diagram, or specific region\nShape: gentle camera move + callout arrow from caption to figure + pulse the figure.\n{\n  \"version\": 1,\n  \"steps\": [\n    { \"at_ms\":0,   \"duration_ms\":600, \"action\": { \"type\":\"camera\", \"target_block\":\"p1_fig0\", \"scale\":1.3, \"padding\":80, \"easing\":\"ease-out\" } },\n    { \"at_ms\":400, \"duration_ms\":900, \"action\": { \"type\":\"callout\", \"from_block\":\"p1_cap1\", \"to_block\":\"p1_fig0\", \"label\":\"see here\", \"curve\":\"curved\" } },\n    { \"at_ms\":900, \"duration_ms\":1200, \"action\": { \"type\":\"pulse\", \"target_block\":\"p1_fig0\", \"count\":2, \"intensity\":\"normal\" } }\n  ]\n}\n\n## compare — the narration contrasts two things on the page\nShape: box A + box B + callout between them with a relational label.\n{\n  \"version\": 1,\n  \"steps\": [\n    { \"at_ms\":0,   \"duration_ms\":600, \"action\": { \"type\":\"box\", \"target_block\":\"p1_list5\", \"color\":\"#3B82F6\", \"style\":\"solid\" } },\n    { \"at_ms\":300, \"duration_ms\":600, \"action\": { \"type\":\"box\", \"target_block\":\"p1_list12\", \"color\":\"#F472B6\", \"style\":\"solid\" } },\n    { \"at_ms\":800, \"duration_ms\":1000, \"action\": { \"type\":\"callout\", \"from_block\":\"p1_list5\", \"to_block\":\"p1_list12\", \"label\":\"vs\", \"curve\":\"curved\" } }\n  ]\n}\n\n## emphasize — the narration stresses a keyword, warning, or takeaway\nShape: highlight + pulse. Fast, punchy, no camera.\n{\n  \"version\": 1,\n  \"steps\": [\n    { \"at_ms\":0,   \"duration_ms\":500, \"action\": { \"type\":\"highlight\", \"target_block\":\"p1_list0\", \"color\":\"rgba(250,204,21,0.35)\", \"draw_duration_ms\":450 } },\n    { \"at_ms\":350, \"duration_ms\":800, \"action\": { \"type\":\"pulse\", \"target_block\":\"p1_list0\", \"count\":2, \"intensity\":\"strong\" } }\n  ]\n}\n\n# Choreography rules\n- HARD REQUIREMENT: every storyboard MUST contain at least ONE non-camera step. A lone camera step is NEVER a valid output — the viewer needs an overlay to know WHY the camera moved. If you cannot find a good overlay target, emit a \\`highlight\\` or \\`pulse\\` on your primary block as the second step.\n- Favor VARIETY that matches narration texture — a definition earns different visuals than a comparison. Don't send every chunk through the same zoom+box motion.\n- Include a camera step only when focus genuinely shifts to a new region. If the primary target is already on-screen and roughly centred, SKIP the camera entirely and start directly with an overlay.\n- Camera scale: default to **1.1** (gentle re-centre). Use **1.2–1.3** for normal reading distance. Use **1.4–1.6** ONLY for dense figures or small inline details. NEVER use a scale below 0.5 or above 4.0 — the engine rejects those. When in doubt, use 1.1.\n- Prefer overlays that OVERLAP the camera move. A camera that takes 700ms to finish while overlays fire at 200ms feels cinematic; overlays waiting until after the camera settles feel sluggish. Stagger \\`at_ms\\`: camera at 0, first overlay at 150–300ms, second overlay at 600–900ms.\n- 2–4 steps is typical; single-step overlays (no camera) are PREFERRED when the target is already visible.\n- When narration compares two things, USE the compare recipe (box + box + callout), not a single camera step. When narration says \"key takeaway\", USE emphasize (highlight + pulse).\n- Never target a block_id not present in the provided lists. If no block matches, emit a single camera step at scale 1.0 + a subtle pulse on the nearest heading; explain in \\`reasoning\\`.\n- Output ONLY valid JSON. No markdown, no code fences, no commentary, no trailing whitespace inside property values.\n\n# Forbidden outputs — these will be rejected:\n- A storyboard with only a camera step.\n- A camera step with scale < 0.5 or > 4.0.\n- target_block values not listed in \"Page blocks\" or \"Cross-page figures index\".\n- Tab characters, newlines, or explanatory text inside JSON string values.`;\n\nexport interface BuildUserPromptInput {\n  chunk: string;\n  pageNumber: number;\n  page: PageBBoxData;\n  index: BBoxIndex;\n  history: ChunkHistoryEntry[];\n  camera: CameraState;\n  activeOverlays: ActiveOverlay[];\n  maxSteps?: number;\n}\n\n/** Truncate text to ~max chars, word-aware. */\nexport function truncate(text: string | null, max = 200): string {\n  if (!text) return '';\n  if (text.length <= max) return text;\n  const slice = text.slice(0, max);\n  const last = slice.lastIndexOf(' ');\n  return (last > 40 ? slice.slice(0, last) : slice) + '…';\n}\n\nexport function buildUserPrompt(input: BuildUserPromptInput): string {\n  const {\n    chunk,\n    pageNumber,\n    page,\n    index,\n    history,\n    camera,\n    activeOverlays,\n    maxSteps = 4,\n  } = input;\n\n  const pageBlocks = page.blocks.map((b) => ({\n    block_id: b.block_id,\n    type: b.type,\n    text: truncate(b.text, 200),\n    bbox: b.bbox,\n    default_action: b.default_action,\n  }));\n\n  const xPageFigures = index.crossPageFigures\n    .filter((f) => f.page !== pageNumber)\n    .slice(0, 20)\n    .map((f) => ({\n      block_id: f.block_id,\n      page: f.page,\n      type: f.type,\n      text: truncate(f.text, 200),\n    }));\n\n  const recent = history.slice(-3).map((h) => h.text);\n  const overlaySummary = activeOverlays.map((o) => ({ id: o.id, kind: o.kind }));\n\n  const blockIdList = pageBlocks.map((b) => b.block_id);\n\n  return [\n    `Current page: ${pageNumber}`,\n    `Page blocks (${pageBlocks.length}) — you MUST pick target_block from this list:`,\n    JSON.stringify(pageBlocks),\n    '',\n    `Valid block_ids for this page: ${JSON.stringify(blockIdList)}`,\n    '',\n    `Cross-page figures index: ${JSON.stringify(xPageFigures)}`,\n    '',\n    `Current chunk (what the tutor just said): ${JSON.stringify(chunk)}`,\n    `Recent chunks: ${JSON.stringify(recent)}`,\n    `Current camera: ${JSON.stringify(camera)}`,\n    `Active overlays: ${JSON.stringify(overlaySummary)}`,\n    '',\n    `Max steps: ${maxSteps}`,\n    `Output JSON storyboard. Every target_block MUST be one of the ids above.`,\n  ].join('\\n');\n}\n","/**\n * Parses an OpenAI-style SSE stream (event-stream with data: ... lines).\n * Yields each JSON \"delta\" chunk as a parsed object. Ignores [DONE] markers.\n */\nexport async function* parseSse(\n  body: ReadableStream<Uint8Array>,\n): AsyncGenerator<unknown> {\n  const reader = body.getReader();\n  const decoder = new TextDecoder();\n  let buffer = '';\n\n  try {\n    while (true) {\n      const { value, done } = await reader.read();\n      if (done) break;\n      buffer += decoder.decode(value, { stream: true });\n\n      let idx: number;\n      while ((idx = buffer.indexOf('\\n')) !== -1) {\n        const rawLine = buffer.slice(0, idx).trim();\n        buffer = buffer.slice(idx + 1);\n        if (!rawLine.startsWith('data:')) continue;\n        const payload = rawLine.slice(5).trim();\n        if (!payload || payload === '[DONE]') continue;\n        try {\n          yield JSON.parse(payload);\n        } catch {\n          // malformed SSE payload — skip\n        }\n      }\n    }\n  } finally {\n    reader.releaseLock();\n  }\n}\n\n/** Extract the assistant-message content delta from an OpenAI-compatible chunk. */\nexport function extractDelta(chunk: unknown): string | null {\n  if (!chunk || typeof chunk !== 'object') return null;\n  const choices = (chunk as { choices?: Array<{ delta?: { content?: string } }> }).choices;\n  if (!choices || !choices.length) return null;\n  return choices[0].delta?.content ?? null;\n}\n","import {\n  StoryboardSchema,\n  StoryboardStepSchema,\n  storyboardJsonSchema,\n} from './storyboard-schema';\nimport {\n  SYSTEM_PROMPT,\n  buildUserPrompt,\n  type BuildUserPromptInput,\n} from './prompts';\nimport { parseSse, extractDelta } from './sse-parser';\nimport type { Storyboard } from '../types/storyboard';\n\nexport interface LlmConfig {\n  endpointUrl: string;\n  model: string;\n  authToken?: string;\n  extraBody?: Record<string, unknown>;\n  maxTokens?: number;\n  temperature?: number;\n  /** If true, include response_format: json_schema (disable if the backend doesn't support it). */\n  useJsonSchema?: boolean;\n  /** If true, request streaming (default false: simpler, more reliable for non-streaming backends). */\n  stream?: boolean;\n}\n\nexport interface DirectorInput extends BuildUserPromptInput {\n  signal?: AbortSignal;\n  timeoutMs?: number;\n}\n\nexport interface DirectorResult {\n  storyboard: Storyboard | null;\n  raw: string;\n  error?: string;\n}\n\n/**\n * Call the LLM, stream the response, extract a JSON storyboard, validate with zod.\n * Returns { storyboard: null } with an error string on any failure path.\n */\nexport async function directStoryboard(\n  config: LlmConfig,\n  input: DirectorInput,\n): Promise<DirectorResult> {\n  const {\n    endpointUrl,\n    model,\n    authToken,\n    extraBody,\n    maxTokens = 1024,\n    temperature = 0.3,\n    useJsonSchema = true,\n    stream = false,\n  } = config;\n\n  const userContent = buildUserPrompt(input);\n\n  const body: Record<string, unknown> = {\n    model,\n    stream,\n    temperature,\n    max_tokens: maxTokens,\n    messages: [\n      { role: 'system', content: SYSTEM_PROMPT },\n      { role: 'user', content: userContent },\n    ],\n    ...(extraBody ?? {}),\n  };\n\n  if (useJsonSchema) {\n    const validBlockIds = input.page.blocks.map((b) => b.block_id);\n    const validCrossPageBlockIds = input.index.crossPageFigures\n      .filter((f) => f.page !== input.pageNumber)\n      .map((f) => f.block_id);\n    body.response_format = {\n      type: 'json_schema',\n      json_schema: {\n        name: 'storyboard',\n        strict: true,\n        schema: storyboardJsonSchema({\n          validBlockIds,\n          validCrossPageBlockIds,\n        }),\n      },\n    };\n  }\n\n  const headers: Record<string, string> = {\n    'Content-Type': 'application/json',\n    Accept: stream ? 'text/event-stream' : 'application/json',\n  };\n  if (authToken) headers.Authorization = `Bearer ${authToken}`;\n\n  const timeoutController = new AbortController();\n  const timer = setTimeout(\n    () => timeoutController.abort(),\n    input.timeoutMs ?? 2500,\n  );\n  const signal = mergeSignals(input.signal, timeoutController.signal);\n\n  try {\n    const response = await fetch(endpointUrl, {\n      method: 'POST',\n      headers,\n      body: JSON.stringify(body),\n      signal,\n    });\n    if (!response.ok || !response.body) {\n      return {\n        storyboard: null,\n        raw: '',\n        error: `HTTP ${response.status}`,\n      };\n    }\n\n    let raw = '';\n    if (stream && response.body) {\n      for await (const chunk of parseSse(response.body)) {\n        const delta = extractDelta(chunk);\n        if (delta) raw += delta;\n      }\n    } else {\n      const json = (await response.json()) as {\n        choices?: Array<{ message?: { content?: string } }>;\n      };\n      raw = json.choices?.[0]?.message?.content ?? '';\n    }\n\n    const stripped = collapseWhitespaceRuns(stripCodeFences(raw).trim());\n    let parsed: unknown;\n    try {\n      parsed = JSON.parse(stripped);\n    } catch (e) {\n      return {\n        storyboard: null,\n        raw,\n        error: `parse error: ${(e as Error).message}`,\n      };\n    }\n\n    // OpenAI's strict structured-outputs mode forces every property to appear\n    // in `required`, so the LLM emits nulls for inapplicable fields (e.g.,\n    // target_bbox: null on a spotlight action). Strip nulls before validation\n    // so the per-action zod schemas see only the relevant fields.\n    const cleaned = clampNumericRanges(stripNullsDeep(parsed));\n\n    const validation = StoryboardSchema.safeParse(cleaned);\n    if (validation.success) {\n      return {\n        storyboard: enforceOverlayPresence(validation.data as Storyboard),\n        raw,\n      };\n    }\n\n    const salvaged = salvageStoryboard(cleaned);\n    if (salvaged) {\n      return { storyboard: enforceOverlayPresence(salvaged), raw };\n    }\n\n    return {\n      storyboard: null,\n      raw,\n      error: `validation failed: ${validation.error.message}`,\n    };\n  } catch (e) {\n    const name = (e as Error).name;\n    const msg = name === 'AbortError' ? 'aborted' : (e as Error).message;\n    return { storyboard: null, raw: '', error: msg };\n  } finally {\n    clearTimeout(timer);\n  }\n}\n\nfunction stripCodeFences(s: string): string {\n  const m = s.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n  return m ? m[1] : s;\n}\n\n/**\n * Small models (gpt-4.1-nano in particular) sometimes emit runs of dozens of\n * tab characters between a property value and the following comma. That's\n * technically valid JSON whitespace but blows up some downstream inspectors\n * and bloats the transcript. Collapse any run of 8+ whitespace chars into a\n * single space — only OUTSIDE string literals so we don't corrupt user text.\n */\nfunction collapseWhitespaceRuns(src: string): string {\n  let out = '';\n  let inString = false;\n  let escape = false;\n  let run = 0;\n  for (let i = 0; i < src.length; i++) {\n    const c = src[i];\n    if (inString) {\n      out += c;\n      if (escape) {\n        escape = false;\n      } else if (c === '\\\\') {\n        escape = true;\n      } else if (c === '\"') {\n        inString = false;\n      }\n      continue;\n    }\n    if (c === '\"') {\n      out += c;\n      inString = true;\n      run = 0;\n      continue;\n    }\n    if (c === ' ' || c === '\\t' || c === '\\n' || c === '\\r') {\n      run++;\n      if (run <= 1) out += ' ';\n      continue;\n    }\n    run = 0;\n    out += c;\n  }\n  return out;\n}\n\n/**\n * Clamp numeric fields that the LLM commonly emits out of range. The schema\n * rejects values outside [0.5, 4.0] for camera.scale etc.; rather than throw\n * away the whole storyboard over a 0.394 scale value, clamp to the nearest\n * legal value and proceed. Mirrors the zod schema min/max bounds.\n */\nfunction clampNumericRanges(input: unknown): unknown {\n  if (input === null || input === undefined) return input;\n  if (Array.isArray(input)) return input.map(clampNumericRanges);\n  if (typeof input !== 'object') return input;\n\n  const obj = input as Record<string, unknown>;\n  const out: Record<string, unknown> = {};\n  for (const [k, v] of Object.entries(obj)) {\n    out[k] = clampNumericRanges(v);\n  }\n\n  const type = typeof out.type === 'string' ? (out.type as string) : undefined;\n  if (type === 'camera') {\n    if (typeof out.scale === 'number') out.scale = clamp(out.scale, 0.5, 4.0);\n    if (typeof out.padding === 'number') {\n      out.padding = clamp(out.padding, 0, 400);\n    }\n  }\n  if (typeof out.dim_opacity === 'number') {\n    out.dim_opacity = clamp(out.dim_opacity, 0, 1);\n  }\n  if (typeof out.feather_px === 'number') {\n    out.feather_px = clamp(out.feather_px, 0, 200);\n  }\n  if (typeof out.draw_duration_ms === 'number') {\n    out.draw_duration_ms = clamp(out.draw_duration_ms, 100, 3000);\n  }\n  if (typeof out.count === 'number') {\n    out.count = Math.round(clamp(out.count, 1, 5));\n  }\n  // Step-level timings (at_ms 0-5000, duration_ms 100-5000).\n  if (typeof out.at_ms === 'number') {\n    out.at_ms = clamp(out.at_ms, 0, 5000);\n  }\n  if (typeof out.duration_ms === 'number' && type === undefined) {\n    // Only clamp on step objects (which have no `type`), not on action objects.\n    out.duration_ms = clamp(out.duration_ms, 100, 5000);\n  }\n  return out;\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n  return Math.min(hi, Math.max(lo, v));\n}\n\n/**\n * HARD REQUIREMENT from the system prompt: a storyboard may not be a single\n * camera step. If the LLM slips through with camera-only output, append a\n * gentle pulse on the same target so the viewer always sees an overlay.\n */\nfunction enforceOverlayPresence(sb: Storyboard): Storyboard {\n  if (sb.steps.length === 0) return sb;\n  const hasOverlay = sb.steps.some(\n    (s) => s.action.type !== 'camera' && s.action.type !== 'clear',\n  );\n  if (hasOverlay) return sb;\n\n  const cameraStep = sb.steps.find((s) => s.action.type === 'camera');\n  if (!cameraStep || cameraStep.action.type !== 'camera') return sb;\n  const target = cameraStep.action.target_block;\n  if (!target) return sb;\n\n  const prefix = sb.reasoning ? `${sb.reasoning} ` : '';\n  return {\n    ...sb,\n    reasoning: `${prefix}[auto-appended pulse: camera-only storyboards are forbidden]`,\n    steps: [\n      ...sb.steps,\n      {\n        at_ms: Math.min(4800, (cameraStep.at_ms ?? 0) + 200),\n        duration_ms: 900,\n        action: {\n          type: 'pulse' as const,\n          target_block: target,\n          count: 2,\n          intensity: 'normal' as const,\n        },\n      },\n    ],\n  };\n}\n\n/** Recursively remove keys whose value is null. Arrays of nulls become empty. */\nfunction stripNullsDeep(input: unknown): unknown {\n  if (input === null) return undefined;\n  if (Array.isArray(input)) {\n    return input\n      .map(stripNullsDeep)\n      .filter((v) => v !== undefined);\n  }\n  if (input && typeof input === 'object') {\n    const out: Record<string, unknown> = {};\n    for (const [k, v] of Object.entries(input)) {\n      const cleaned = stripNullsDeep(v);\n      if (cleaned !== undefined) out[k] = cleaned;\n    }\n    return out;\n  }\n  return input;\n}\n\n/**\n * Best-effort salvage when the full StoryboardSchema rejects the LLM output.\n * Tries to keep individual valid steps; returns null if nothing usable remains.\n */\nfunction salvageStoryboard(parsed: unknown): Storyboard | null {\n  if (!parsed || typeof parsed !== 'object') return null;\n  const obj = parsed as { steps?: unknown; reasoning?: unknown };\n  if (!Array.isArray(obj.steps)) return null;\n\n  const goodSteps: Array<ReturnType<typeof StoryboardStepSchema.parse>> = [];\n  for (const step of obj.steps) {\n    const r = StoryboardStepSchema.safeParse(step);\n    if (r.success) goodSteps.push(r.data);\n    if (goodSteps.length >= 4) break;\n  }\n  if (goodSteps.length === 0) return null;\n\n  return {\n    version: 1,\n    reasoning:\n      typeof obj.reasoning === 'string'\n        ? obj.reasoning + ' (salvaged)'\n        : 'salvaged',\n    steps: goodSteps as Storyboard['steps'],\n  };\n}\n\nfunction mergeSignals(a?: AbortSignal, b?: AbortSignal): AbortSignal {\n  if (!a) return b as AbortSignal;\n  if (!b) return a;\n  const ctrl = new AbortController();\n  const onAbort = () => ctrl.abort();\n  a.addEventListener('abort', onAbort);\n  b.addEventListener('abort', onAbort);\n  return ctrl.signal;\n}\n","import type { PageBBoxData, Block } from '../types/bbox';\nimport type { Storyboard } from '../types/storyboard';\n\nexport interface EmbeddingProvider {\n  /** Return embeddings (normalized or raw — similarity function handles either). */\n  embed: (texts: string[]) => Promise<Float32Array[]>;\n}\n\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n  let dot = 0;\n  let na = 0;\n  let nb = 0;\n  const n = Math.min(a.length, b.length);\n  for (let i = 0; i < n; i++) {\n    dot += a[i] * b[i];\n    na += a[i] * a[i];\n    nb += b[i] * b[i];\n  }\n  const denom = Math.sqrt(na) * Math.sqrt(nb);\n  return denom === 0 ? 0 : dot / denom;\n}\n\nexport interface BlockMatch {\n  block: Block;\n  score: number;\n}\n\nexport async function matchChunkToBlock(\n  chunk: string,\n  page: PageBBoxData,\n  provider: EmbeddingProvider,\n): Promise<BlockMatch | null> {\n  const textBlocks = page.blocks.filter(\n    (b) => typeof b.text === 'string' && b.text.trim().length > 0,\n  );\n  if (textBlocks.length === 0) return null;\n  const inputs = [chunk, ...textBlocks.map((b) => b.text as string)];\n  const embeds = await provider.embed(inputs);\n  if (embeds.length < 2) return null;\n  const chunkEmbed = embeds[0];\n  let best: BlockMatch | null = null;\n  for (let i = 0; i < textBlocks.length; i++) {\n    const score = cosineSimilarity(chunkEmbed, embeds[i + 1]);\n    if (!best || score > best.score) best = { block: textBlocks[i], score };\n  }\n  return best;\n}\n\nfunction nearestFigureOnPage(\n  caption: Block,\n  page: PageBBoxData | undefined,\n): Block | null {\n  if (!page) return null;\n  // Captions usually sit directly under/above their figure. Score figures on\n  // the same page by vertical centre distance; closest wins.\n  const [cx1, cy1, cx2, cy2] = caption.bbox;\n  const ccx = (cx1 + cx2) / 2;\n  const ccy = (cy1 + cy2) / 2;\n  let best: { block: Block; dist: number } | null = null;\n  for (const b of page.blocks) {\n    if (b.block_id === caption.block_id) continue;\n    if (b.type !== 'figure' && b.type !== 'figure_region') continue;\n    const [x1, y1, x2, y2] = b.bbox;\n    const fx = (x1 + x2) / 2;\n    const fy = (y1 + y2) / 2;\n    const dist = Math.hypot(fx - ccx, fy - ccy);\n    if (!best || dist < best.dist) best = { block: b, dist };\n  }\n  return best?.block ?? null;\n}\n\nfunction truncateLabel(text: string | null, max: number): string {\n  if (!text) return '';\n  const clean = text.replace(/\\s+/g, ' ').trim();\n  if (clean.length <= max) return clean;\n  return clean.slice(0, max - 1) + '…';\n}\n\n/**\n * Build a fallback storyboard from a matched block. Keys on `block.type`\n * (7 types) rather than `block.default_action` (4 values) so every block\n * class produces a visually distinct storyboard — not every failure rounds\n * down to camera + box. An optional `page` lets caption blocks route to a\n * callout→figure on the same page.\n *\n * Never throws — emits a clear-only storyboard when no match is supplied.\n */\nexport function storyboardFromMatch(\n  match: BlockMatch | null,\n  page?: PageBBoxData,\n): Storyboard {\n  if (!match) {\n    return {\n      version: 1,\n      reasoning: 'fallback: no match — clearing overlays',\n      steps: [\n        {\n          at_ms: 0,\n          duration_ms: 800,\n          action: { type: 'clear', targets: 'overlays' },\n        },\n      ],\n    };\n  }\n  const { block } = match;\n  const id = block.block_id;\n  const reason = `fallback (block.type=${block.type}): matched ${id} (${match.score.toFixed(2)})`;\n\n  switch (block.type) {\n    case 'heading': {\n      // Headings anchor structure — spotlight + title label.\n      return {\n        version: 1,\n        reasoning: reason,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 700,\n            action: {\n              type: 'spotlight',\n              target_block: id,\n              dim_opacity: 0.6,\n              feather_px: 40,\n              shape: 'rounded',\n            },\n          },\n          {\n            at_ms: 300,\n            duration_ms: 1200,\n            action: {\n              type: 'label',\n              target_block: id,\n              text: truncateLabel(block.text, 32) || 'section',\n              position: 'top',\n            },\n          },\n        ],\n      };\n    }\n    case 'paragraph': {\n      // Paragraphs read like prose — gentle re-centre + sketch underline.\n      return {\n        version: 1,\n        reasoning: reason,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 600,\n            action: {\n              type: 'camera',\n              target_block: id,\n              scale: 1.1,\n              padding: 80,\n              easing: 'ease-out',\n            },\n          },\n          {\n            at_ms: 300,\n            duration_ms: 900,\n            action: {\n              type: 'underline',\n              target_block: id,\n              color: '#FBBF24',\n              style: 'sketch',\n              draw_duration_ms: 800,\n            },\n          },\n        ],\n      };\n    }\n    case 'list_item':\n    case 'mcq_option': {\n      // Enumerated items — inline highlight, no camera move.\n      return {\n        version: 1,\n        reasoning: reason,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 500,\n            action: {\n              type: 'highlight',\n              target_block: id,\n              color: 'rgba(250, 204, 21, 0.35)',\n              draw_duration_ms: 450,\n            },\n          },\n        ],\n      };\n    }\n    case 'caption': {\n      // Caption → route a callout arrow to the nearest figure on the same page.\n      const figure = nearestFigureOnPage(block, page);\n      if (figure) {\n        return {\n          version: 1,\n          reasoning: `${reason}; caption → figure ${figure.block_id}`,\n          steps: [\n            {\n              at_ms: 0,\n              duration_ms: 900,\n              action: {\n                type: 'callout',\n                from_block: id,\n                to_block: figure.block_id,\n                label: 'see',\n                curve: 'curved',\n              },\n            },\n            {\n              at_ms: 600,\n              duration_ms: 1000,\n              action: {\n                type: 'pulse',\n                target_block: figure.block_id,\n                count: 2,\n                intensity: 'normal',\n              },\n            },\n          ],\n        };\n      }\n      // No figure on the page — just underline the caption so it stays legible.\n      return {\n        version: 1,\n        reasoning: `${reason}; no figure on page, underlining caption`,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 800,\n            action: {\n              type: 'underline',\n              target_block: id,\n              color: '#FBBF24',\n              style: 'sketch',\n              draw_duration_ms: 700,\n            },\n          },\n        ],\n      };\n    }\n    case 'figure': {\n      // Figure blocks — pulse to draw the eye, then frame with a box.\n      return {\n        version: 1,\n        reasoning: reason,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 900,\n            action: {\n              type: 'pulse',\n              target_block: id,\n              count: 2,\n              intensity: 'strong',\n            },\n          },\n          {\n            at_ms: 400,\n            duration_ms: 1200,\n            action: {\n              type: 'box',\n              target_block: id,\n              color: '#3B82F6',\n              style: 'solid',\n            },\n          },\n        ],\n      };\n    }\n    case 'figure_region': {\n      return {\n        version: 1,\n        reasoning: reason,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 900,\n            action: {\n              type: 'pulse',\n              target_block: id,\n              count: 2,\n              intensity: 'normal',\n            },\n          },\n        ],\n      };\n    }\n    case 'table': {\n      return {\n        version: 1,\n        reasoning: reason,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 700,\n            action: {\n              type: 'camera',\n              target_block: id,\n              scale: 1.2,\n              padding: 60,\n              easing: 'ease-out',\n            },\n          },\n          {\n            at_ms: 300,\n            duration_ms: 1000,\n            action: {\n              type: 'box',\n              target_block: id,\n              color: '#3B82F6',\n              style: 'dashed',\n            },\n          },\n        ],\n      };\n    }\n    default: {\n      // Unknown block type — safe default that still has variety.\n      return {\n        version: 1,\n        reasoning: `${reason}; unknown block.type, using highlight`,\n        steps: [\n          {\n            at_ms: 0,\n            duration_ms: 600,\n            action: {\n              type: 'highlight',\n              target_block: id,\n              color: 'rgba(250, 204, 21, 0.35)',\n              draw_duration_ms: 500,\n            },\n          },\n        ],\n      };\n    }\n  }\n}\n","import type { EmbeddingProvider } from './embedding-fallback';\n\nlet loaded: Promise<EmbeddingProvider> | null = null;\n\n/**\n * Lazily load a local MiniLM model (only on first call). The dynamic import\n * keeps `@xenova/transformers` out of the main bundle unless used.\n */\nexport function getLocalMiniLM(): Promise<EmbeddingProvider> {\n  if (loaded) return loaded;\n  loaded = (async (): Promise<EmbeddingProvider> => {\n    const mod = await import(/* webpackIgnore: true */ '@xenova/transformers');\n    const { pipeline } = mod;\n    const extractor = await pipeline(\n      'feature-extraction',\n      'Xenova/all-MiniLM-L6-v2',\n    );\n    return {\n      async embed(texts: string[]) {\n        const out: Float32Array[] = [];\n        for (const t of texts) {\n          const result = await extractor(t, {\n            pooling: 'mean',\n            normalize: true,\n          });\n          out.push(new Float32Array((result.data as Float32Array).slice()));\n        }\n        return out;\n      },\n    };\n  })();\n  return loaded;\n}\n","export {\n  PluginManager,\n  getPluginManager,\n  createPluginManager,\n  type PluginManagerOptions,\n} from './PluginManager';\n"],"mappings":"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","names":["version","loaded","document","numPages","document","z","initialState","import_vanilla","init_PDFViewer","isStorageAvailable","getStorageKey","STORAGE_PREFIX","focusRegionIdCounter","generateFocusRegionId","document","initialState","document","calculateMatchRects","import_vanilla","initialState","import_vanilla","generateId","isStorageAvailable","getStorageKey","STORAGE_PREFIX","initialState","import_vanilla","initialState","import_vanilla","initialState","import_react","document","import_react","numPages","import_react","import_react","import_react","import_react","options","import_react","import_react","getPluginManager","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","Toolbar","import_react","import_jsx_runtime","MobileToolbar","init_Toolbar","import_react","import_jsx_runtime","Thumbnail","document","ThumbnailPanel","import_react","import_jsx_runtime","SearchPanel","import_react","import_jsx_runtime","OutlineNode","OutlinePanel","document","import_react","import_jsx_runtime","HighlightItem","PageGroup","HighlightsPanel","import_react","import_jsx_runtime","SidebarTab","Sidebar","import_react","import_jsx_runtime","MobileSidebar","import_react","import_jsx_runtime","PageGroup","BookmarkItem","EditModal","BookmarksPanel","import_react","import_jsx_runtime","PageGroup","TakeawayItem","TakeawaysPanel","init_Sidebar","import_react","import_jsx_runtime","AnnotationToolbar","init_AnnotationToolbar","import_react","import_jsx_runtime","CanvasLayer","isTextItem","import_react","import_jsx_runtime","TextLayer","import_react","import_jsx_runtime","HighlightLayer","import_react","import_jsx_runtime","AnnotationLayer","import_react","import_jsx_runtime","PDFPage","import_react","import_jsx_runtime","FocusRegionLayer","init_PDFPage","import_react","import_jsx_runtime","PDFLoadingScreen","init_PDFLoadingScreen","import_react","import_jsx_runtime","PageSkeleton","import_react","import_jsx_runtime","SelectionToolbar","init_SelectionToolbar","import_react","import_jsx_runtime","HighlightPopover","init_HighlightPopover","import_react","import_jsx_runtime","init_PDFPage","init_PDFLoadingScreen","init_SelectionToolbar","init_HighlightPopover","DocumentContainer","document","import_react","import_jsx_runtime","DEFAULT_PAGE_WIDTH","DEFAULT_PAGE_HEIGHT","init_PDFPage","init_PDFLoadingScreen","init_SelectionToolbar","init_HighlightPopover","VirtualizedDocumentContainer","document","import_react","import_jsx_runtime","ContinuousScrollContainer","import_react","import_jsx_runtime","init_PDFPage","init_PDFLoadingScreen","init_SelectionToolbar","init_HighlightPopover","DualPageContainer","document","spread","import_react","import_jsx_runtime","init_PDFPage","init_PDFLoadingScreen","React","BookPage","BookModeContainer","document","HTMLFlipBook","import_react","import_jsx_runtime","FloatingZoomControls","document","init_FloatingZoomControls","calculateMatchRects","import_react","import_jsx_runtime","init_Toolbar","init_Sidebar","init_AnnotationToolbar","init_FloatingZoomControls","init_PDFLoadingScreen","PDFViewerInner","scale","currentPage","loaded","document","error","PDFViewerInnerWithRef","PDFViewerClient","import_react","import_jsx_runtime","PDFViewerClient","PDFViewerLoading","PDFViewer","init_PDFViewer","init_PDFViewer","init_PDFPage","init_Toolbar","init_Sidebar","init_SelectionToolbar","init_HighlightPopover","init_AnnotationToolbar","import_react","import_jsx_runtime","StickyNote","import_react","import_jsx_runtime","DrawingCanvas","import_react","import_jsx_runtime","ShapeRenderer","renderShape","ShapePreview","import_react","import_jsx_runtime","QuickNoteButton","import_react","import_jsx_runtime","QuickNotePopover","import_react","import_jsx_runtime","AskAboutOverlay","import_react","import_jsx_runtime","AskAboutTrigger","import_react","import_jsx_runtime","PageIndicator","Minimap","init_FloatingZoomControls","import_react","import_jsx_runtime","PDFThumbnailNav","document","isHorizontal","import_react","import_jsx_runtime","init_PDFLoadingScreen","import_react","import_zustand","init_PDFPage","import_jsx_runtime","import_framer_motion","import_react","import_framer_motion","import_jsx_runtime","import_framer_motion","import_jsx_runtime","import_framer_motion","import_jsx_runtime","import_framer_motion","import_jsx_runtime","import_react","import_framer_motion","import_jsx_runtime","import_framer_motion","import_jsx_runtime","import_jsx_runtime","import_framer_motion","import_framer_motion","import_jsx_runtime","INK","PAPER","ACCENT","SERIF","import_jsx_runtime","import_framer_motion","import_framer_motion","import_jsx_runtime","import_jsx_runtime","import_framer_motion","import_jsx_runtime","side","import_framer_motion","import_jsx_runtime","clamp","import_jsx_runtime","document","page"]}