{"version":3,"file":"index.modern.mjs","sources":["../src/useTransition.ts","../src/useMutationObserver.ts","../src/useEventBus.ts","../src/useWrappedChildren.ts","../src/usePreferredTheme.ts","../src/useNetworkState.ts","../src/useClipboard.ts","../src/useRageClick.ts","../src/useThreadedWorker.ts","../src/indexedDB/openDB.ts","../src/indexedDB/requestToPromise.ts","../src/indexedDB/tableController.ts","../src/useIndexedDB.ts","../src/indexedDB/dbController.ts","../src/useWebRTCIP.ts","../src/useWasmCompute.ts","../src/useWorkerNotifications.ts","../src/useLLMMetadata.ts","../src/useRefPrint.ts","../src/useRBAC.ts","../src/usePrefetch.ts","../src/usePoll.ts","../src/useDeviceData.ts"],"sourcesContent":["import { useState, useCallback } from \"preact/hooks\";\n\n/**\n * Mimics React's useTransition hook in Preact.\n * @returns [startTransition, isPending]\n */\nexport function useTransition(): [\n  startTransition: (callback: () => void) => void,\n  isPending: boolean,\n] {\n  const [isPending, setIsPending] = useState(false);\n\n  const startTransition = useCallback((callback: () => void) => {\n    setIsPending(true);\n    Promise.resolve().then(() => {\n      callback();\n      setIsPending(false);\n    });\n  }, []);\n\n  return [startTransition, isPending];\n}\n","import { RefObject } from \"preact\";\nimport { useEffect } from \"preact/hooks\";\n\nexport type UseMutationObserverOptions = MutationObserverInit;\n\n/**\n * A Preact hook to observe DOM mutations using MutationObserver.\n * @param target - The element to observe.\n * @param callback - Function to call on mutation.\n * @param options - MutationObserver options.\n */\nexport function useMutationObserver(\n  targetRef: RefObject<HTMLElement | null>,\n  callback: MutationCallback,\n  options: MutationObserverInit\n) {\n  useEffect(() => {\n    const node = targetRef.current;\n    if (!node) return;\n\n    const observer = new MutationObserver(callback);\n    observer.observe(node, options);\n\n    return () => observer.disconnect();\n  }, [targetRef, callback, options]);\n}\n","import { useCallback } from \"preact/hooks\";\n\ntype EventMap = Record<string, (...args: unknown[]) => void>;\n\nconst listeners = new Map<string, Set<(...args: unknown[]) => void>>();\n\n/**\n * A Preact hook to publish and subscribe to custom events across components.\n * @returns An object with `emit` and `on` methods.\n */\nexport function useEventBus<T extends EventMap>() {\n  const emit = useCallback(\n    <K extends keyof T>(event: K, ...args: Parameters<T[K]>) => {\n      const handlers = listeners.get(event as string);\n      if (handlers) {\n        handlers.forEach((handler) => handler(...args));\n      }\n    },\n    []\n  );\n\n  const on = useCallback(<K extends keyof T>(event: K, handler: T[K]) => {\n    let handlers = listeners.get(event as string);\n    if (!handlers) {\n      handlers = new Set();\n      listeners.set(event as string, handlers);\n    }\n    handlers.add(handler);\n\n    return () => {\n      handlers!.delete(handler);\n      if (handlers!.size === 0) {\n        listeners.delete(event as string);\n      }\n    };\n  }, []);\n\n  return { emit, on };\n}\n","import { ComponentChildren, cloneElement, isValidElement, VNode } from \"preact\";\nimport { useMemo } from \"preact/hooks\";\n\nexport type InjectableProps = Record<string, unknown>;\n\ninterface PropsWithStyle {\n  style?: Record<string, string | number>;\n}\n\n/**\n * A Preact hook to wrap children components and inject additional props into them.\n * @param children - The children to wrap and enhance with props.\n * @param injectProps - The props to inject into each child component.\n * @param mergeStrategy - How to handle prop conflicts ('override' | 'preserve'). Defaults to 'preserve'.\n * @returns Enhanced children with injected props.\n */\nexport function useWrappedChildren(\n  children: ComponentChildren,\n  injectProps: InjectableProps,\n  mergeStrategy: \"override\" | \"preserve\" = \"preserve\"\n): ComponentChildren {\n  return useMemo(() => {\n    if (!children) return children;\n\n    const enhanceChild = (child: ComponentChildren): ComponentChildren => {\n      if (!isValidElement(child)) return child;\n\n      const existingProps = (child as VNode).props || {};\n\n      let mergedProps: InjectableProps;\n\n      if (mergeStrategy === \"override\") {\n        // Injected props override existing ones\n        mergedProps = { ...existingProps, ...injectProps };\n      } else {\n        // Existing props are preserved, injected props are added only if not present\n        mergedProps = { ...injectProps, ...existingProps };\n      }\n\n      // Special handling for style prop to merge style objects properly\n      const existingStyle = (existingProps as PropsWithStyle)?.style;\n      const injectStyle = (injectProps as PropsWithStyle)?.style;\n\n      if (\n        existingStyle &&\n        injectStyle &&\n        typeof existingStyle === \"object\" &&\n        typeof injectStyle === \"object\"\n      ) {\n        if (mergeStrategy === \"override\") {\n          (mergedProps as PropsWithStyle).style = {\n            ...existingStyle,\n            ...injectStyle,\n          };\n        } else {\n          (mergedProps as PropsWithStyle).style = {\n            ...injectStyle,\n            ...existingStyle,\n          };\n        }\n      }\n\n      return cloneElement(child, mergedProps);\n    };\n\n    if (Array.isArray(children)) {\n      return children.map(enhanceChild);\n    }\n\n    return enhanceChild(children);\n  }, [children, injectProps, mergeStrategy]);\n}\n","import { useEffect, useState } from \"preact/hooks\";\n\nexport type PreferredTheme = \"light\" | \"dark\" | \"no-preference\";\n\n/**\n * A Preact hook that returns the user's preferred color scheme based on the\n * `prefers-color-scheme` media query. Updates reactively when the user changes\n * their system or browser theme preference.\n *\n * @returns The preferred theme: 'light', 'dark', or 'no-preference'\n *\n * @example\n * ```tsx\n * function ThemeAwareComponent() {\n *   const theme = usePreferredTheme();\n *   return (\n *     <div data-theme={theme}>\n *       Current preference: {theme}\n *     </div>\n *   );\n * }\n * ```\n */\nexport function usePreferredTheme(): PreferredTheme {\n  const [theme, setTheme] = useState<PreferredTheme>(() => {\n    if (typeof window === \"undefined\") return \"no-preference\";\n\n    const darkQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n    const lightQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n\n    if (darkQuery.matches) return \"dark\";\n    if (lightQuery.matches) return \"light\";\n    return \"no-preference\";\n  });\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n\n    const mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n\n    const handleChange = (e: MediaQueryListEvent) => {\n      setTheme(e.matches ? \"dark\" : \"light\");\n    };\n\n    // Re-check in case of no-preference (some browsers don't support light query)\n    const updateTheme = () => {\n      const darkQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n      const lightQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n\n      if (darkQuery.matches) setTheme(\"dark\");\n      else if (lightQuery.matches) setTheme(\"light\");\n      else setTheme(\"no-preference\");\n    };\n\n    mediaQuery.addEventListener(\"change\", handleChange);\n\n    // Fallback: some environments may not fire change, so we also listen for light\n    const lightQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n    lightQuery.addEventListener(\"change\", updateTheme);\n\n    return () => {\n      mediaQuery.removeEventListener(\"change\", handleChange);\n      lightQuery.removeEventListener(\"change\", updateTheme);\n    };\n  }, []);\n\n  return theme;\n}\n","import { useEffect, useState } from \"preact/hooks\";\n\n/** Network Information API (not in all browsers) */\ninterface NetworkInformation extends EventTarget {\n  effectiveType?: string;\n  downlink?: number;\n  rtt?: number;\n  saveData?: boolean;\n  type?: string;\n}\n\n/** Effective connection type from Network Information API */\nexport type EffectiveConnectionType = \"slow-2g\" | \"2g\" | \"3g\" | \"4g\";\n\n/** Network connection type (e.g., wifi, cellular) */\nexport type ConnectionType =\n  | \"bluetooth\"\n  | \"cellular\"\n  | \"ethernet\"\n  | \"mixed\"\n  | \"none\"\n  | \"other\"\n  | \"unknown\"\n  | \"wifi\";\n\nexport interface NetworkState {\n  /** Whether the browser is online */\n  online: boolean;\n  /** Effective connection type (when supported) */\n  effectiveType?: EffectiveConnectionType;\n  /** Estimated downlink speed in Mbps (when supported) */\n  downlink?: number;\n  /** Estimated round-trip time in ms (when supported) */\n  rtt?: number;\n  /** Whether the user has requested reduced data usage (when supported) */\n  saveData?: boolean;\n  /** Connection type (when supported) */\n  connectionType?: ConnectionType;\n}\n\nfunction getNetworkState(): NetworkState {\n  if (typeof navigator === \"undefined\") {\n    return { online: true };\n  }\n\n  const state: NetworkState = {\n    online: navigator.onLine,\n  };\n\n  const connection = (\n    navigator as Navigator & { connection?: NetworkInformation }\n  ).connection;\n\n  if (connection) {\n    if (connection.effectiveType !== undefined) {\n      state.effectiveType = connection.effectiveType as EffectiveConnectionType;\n    }\n    if (connection.downlink !== undefined) {\n      state.downlink = connection.downlink;\n    }\n    if (connection.rtt !== undefined) {\n      state.rtt = connection.rtt;\n    }\n    if (connection.saveData !== undefined) {\n      state.saveData = connection.saveData;\n    }\n    if (connection.type !== undefined) {\n      state.connectionType = connection.type as ConnectionType;\n    }\n  }\n\n  return state;\n}\n\n/**\n * A Preact hook that returns the current network state, including online/offline\n * status and (when supported) connection type, downlink, RTT, and save-data preference.\n * Updates reactively when the network state changes.\n *\n * @returns The current network state object\n *\n * @example\n * ```tsx\n * function NetworkStatus() {\n *   const { online, effectiveType, saveData } = useNetworkState();\n *   return (\n *     <div>\n *       Status: {online ? 'Online' : 'Offline'}\n *       {effectiveType && ` (${effectiveType})`}\n *       {saveData && ' - Reduced data mode'}\n *     </div>\n * );\n * }\n * ```\n */\nexport function useNetworkState(): NetworkState {\n  const [state, setState] = useState<NetworkState>(getNetworkState);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n\n    const updateState = () => setState(getNetworkState());\n\n    window.addEventListener(\"online\", updateState);\n    window.addEventListener(\"offline\", updateState);\n\n    const connection = (\n      navigator as Navigator & { connection?: NetworkInformation }\n    ).connection;\n    if (connection?.addEventListener) {\n      connection.addEventListener(\"change\", updateState);\n    }\n\n    return () => {\n      window.removeEventListener(\"online\", updateState);\n      window.removeEventListener(\"offline\", updateState);\n      if (connection?.removeEventListener) {\n        connection.removeEventListener(\"change\", updateState);\n      }\n    };\n  }, []);\n\n  return state;\n}\n","import { useCallback, useState } from \"preact/hooks\";\n\nexport interface UseClipboardOptions {\n  /** Duration in ms to keep `copied` true before resetting. Default: 2000 */\n  resetDelay?: number;\n}\n\nexport interface UseClipboardReturn {\n  /** Copy text to the clipboard. Returns true on success. */\n  copy: (text: string) => Promise<boolean>;\n  /** Read text from the clipboard. Returns empty string if denied or unavailable. */\n  paste: () => Promise<string>;\n  /** Whether the last copy operation succeeded (resets after resetDelay) */\n  copied: boolean;\n  /** Error from the last failed operation, or null */\n  error: Error | null;\n  /** Manually reset copied and error state */\n  reset: () => void;\n}\n\n/**\n * A Preact hook for reading and writing the clipboard. Uses the async\n * Clipboard API when available (requires secure context and user gesture).\n *\n * @param options - Optional configuration (e.g., resetDelay for copied state)\n * @returns Object with copy, paste, copied, error, and reset\n *\n * @example\n * ```tsx\n * function CopyButton() {\n *   const { copy, copied, error } = useClipboard();\n *   return (\n *     <button onClick={() => copy('Hello!')}>\n *       {copied ? 'Copied!' : 'Copy'}\n *     </button>\n *   );\n * }\n * ```\n */\nexport function useClipboard(\n  options: UseClipboardOptions = {}\n): UseClipboardReturn {\n  const { resetDelay = 2000 } = options;\n\n  const [copied, setCopied] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n\n  const reset = useCallback(() => {\n    setCopied(false);\n    setError(null);\n  }, []);\n\n  const copy = useCallback(\n    async (text: string): Promise<boolean> => {\n      setError(null);\n\n      if (typeof navigator === \"undefined\" || !navigator.clipboard) {\n        const err = new Error(\"Clipboard API is not available\");\n        setError(err);\n        return false;\n      }\n\n      try {\n        await navigator.clipboard.writeText(text);\n        setCopied(true);\n        if (resetDelay > 0) {\n          setTimeout(() => setCopied(false), resetDelay);\n        }\n        return true;\n      } catch (e) {\n        const err = e instanceof Error ? e : new Error(String(e));\n        setError(err);\n        return false;\n      }\n    },\n    [resetDelay]\n  );\n\n  const paste = useCallback(async (): Promise<string> => {\n    setError(null);\n\n    if (typeof navigator === \"undefined\" || !navigator.clipboard) {\n      const err = new Error(\"Clipboard API is not available\");\n      setError(err);\n      return \"\";\n    }\n\n    try {\n      const text = await navigator.clipboard.readText();\n      return text;\n    } catch (e) {\n      const err = e instanceof Error ? e : new Error(String(e));\n      setError(err);\n      return \"\";\n    }\n  }, []);\n\n  return { copy, paste, copied, error, reset };\n}\n","import type { RefObject } from \"preact\";\nimport { useEffect, useRef } from \"preact/hooks\";\n\nexport interface RageClickPayload {\n  /** Number of clicks that triggered the rage click */\n  count: number;\n  /** Last click event (e.g. for Sentry context) */\n  event: MouseEvent;\n}\n\nexport interface UseRageClickOptions {\n  /** Called when a rage click is detected. Use this to report to Sentry or your error tracker. */\n  onRageClick: (payload: RageClickPayload) => void;\n  /** Minimum number of clicks in the time window to count as rage click. Default: 5 (Sentry-style). */\n  threshold?: number;\n  /** Time window in ms. Default: 1000. */\n  timeWindow?: number;\n  /** Max distance in px between clicks to count as same spot. Default: 30. Set to Infinity to ignore distance. */\n  distanceThreshold?: number;\n}\n\ninterface ClickRecord {\n  time: number;\n  x: number;\n  y: number;\n}\n\nfunction distance(a: ClickRecord, b: ClickRecord): number {\n  return Math.hypot(b.x - a.x, b.y - a.y);\n}\n\n/**\n * Detects \"rage clicks\" (repeated rapid clicks in the same area), e.g. when the UI\n * is unresponsive. Use the callback to report to Sentry or similar tools to surface\n * rage click issues and lower rage-click-related support.\n *\n * @param targetRef - Ref of the element to monitor (e.g. a button or card).\n * @param options - onRageClick callback and optional threshold, timeWindow, distanceThreshold.\n *\n * @example\n * ```tsx\n * const ref = useRef<HTMLButtonElement>(null)\n * useRageClick(ref, {\n *   onRageClick: ({ count, event }) => {\n *     Sentry.captureMessage('Rage click detected', { extra: { count, target: event.target } })\n *   },\n * })\n * return <button ref={ref}>Submit</button>\n * ```\n */\nexport function useRageClick(\n  targetRef: RefObject<HTMLElement | null>,\n  options: UseRageClickOptions\n) {\n  const {\n    onRageClick,\n    threshold = 5,\n    timeWindow = 1000,\n    distanceThreshold = 30,\n  } = options;\n\n  const onRageClickRef = useRef(onRageClick);\n  onRageClickRef.current = onRageClick;\n\n  const clicksRef = useRef<ClickRecord[]>([]);\n\n  useEffect(() => {\n    const node = targetRef.current;\n    if (!node) return;\n\n    const handleClick = (e: MouseEvent) => {\n      const now = Date.now();\n      const record: ClickRecord = { time: now, x: e.clientX, y: e.clientY };\n\n      const clicks = clicksRef.current;\n      const cutoff = now - timeWindow;\n      const recent = clicks.filter((c) => c.time >= cutoff);\n      recent.push(record);\n\n      if (distanceThreshold !== Infinity) {\n        const inRange = recent.filter(\n          (c) => distance(c, record) <= distanceThreshold\n        );\n        if (inRange.length >= threshold) {\n          onRageClickRef.current({ count: inRange.length, event: e });\n          clicksRef.current = [];\n          return;\n        }\n      } else {\n        if (recent.length >= threshold) {\n          onRageClickRef.current({ count: recent.length, event: e });\n          clicksRef.current = [];\n          return;\n        }\n      }\n\n      clicksRef.current = recent;\n    };\n\n    node.addEventListener(\"click\", handleClick);\n    return () => node.removeEventListener(\"click\", handleClick);\n  }, [targetRef, threshold, timeWindow, distanceThreshold]);\n}\n","import { useState, useCallback, useRef, useEffect } from \"preact/hooks\";\n\n/** Lower number = higher priority. Default priority when not specified. */\nconst DEFAULT_PRIORITY = 1;\n\nexport type ThreadedWorkerMode = \"sequential\" | \"parallel\";\n\nexport interface UseThreadedWorkerOptions {\n  /** Sequential: single worker, priority-ordered. Parallel: worker pool. */\n  mode: ThreadedWorkerMode;\n  /** Max concurrent workers. Only used when mode is \"parallel\". Default 4. */\n  concurrency?: number;\n}\n\nexport interface RunOptions {\n  /** 1 = highest priority. Lower number runs first. FIFO within same priority. */\n  priority?: number;\n}\n\ninterface QueuedTask<TData, TResult> {\n  data: TData;\n  priority: number;\n  sequence: number;\n  resolve: (value: TResult) => void;\n  reject: (reason: unknown) => void;\n}\n\nexport interface UseThreadedWorkerReturn<TData, TResult> {\n  /** Enqueue work. Returns a Promise that resolves with the worker result. */\n  run: (data: TData, options?: RunOptions) => Promise<TResult>;\n  /** True while any task is queued or running. */\n  loading: boolean;\n  /** Result of the most recently completed successful task. */\n  result: TResult | undefined;\n  /** Error from the most recently failed task. */\n  error: unknown;\n  /** Number of tasks currently queued + running. */\n  queueSize: number;\n  /** Clear all pending (not yet started) tasks. Running tasks continue. */\n  clearQueue: () => void;\n  /** Stop accepting new work and clear pending queue. Running tasks finish. */\n  terminate: () => void;\n}\n\n/**\n * Production-grade hook to run async work in a queue with optional priority\n * and either sequential or parallel execution.\n *\n * @param workerFn - Async function to run for each task (e.g. API call, heavy compute).\n * @param options - mode: \"sequential\" | \"parallel\", concurrency (parallel only).\n * @returns run, loading, result, error, queueSize, clearQueue, terminate.\n */\nexport function useThreadedWorker<TData, TResult>(\n  workerFn: (data: TData) => Promise<TResult>,\n  options: UseThreadedWorkerOptions\n): UseThreadedWorkerReturn<TData, TResult> {\n  const { mode, concurrency = 4 } = options;\n  const maxConcurrent = mode === \"sequential\" ? 1 : Math.max(1, concurrency);\n\n  const [loading, setLoading] = useState(false);\n  const [result, setResult] = useState<TResult | undefined>(undefined);\n  const [error, setError] = useState<unknown>(undefined);\n  const [queueSize, setQueueSize] = useState(0);\n\n  const queueRef = useRef<QueuedTask<TData, TResult>[]>([]);\n  const sequenceRef = useRef(0);\n  const activeCountRef = useRef(0);\n  const terminatedRef = useRef(false);\n  const workerFnRef = useRef(workerFn);\n  workerFnRef.current = workerFn;\n\n  const updateQueueSize = useCallback(() => {\n    setQueueSize(queueRef.current.length + activeCountRef.current);\n  }, []);\n\n  const processNext = useCallback(() => {\n    if (terminatedRef.current) return;\n    if (activeCountRef.current >= maxConcurrent) return;\n    if (queueRef.current.length === 0) {\n      if (activeCountRef.current === 0) setLoading(false);\n      updateQueueSize();\n      return;\n    }\n\n    // Sort by priority (asc), then by sequence (FIFO within same priority).\n    queueRef.current.sort((a, b) => {\n      if (a.priority !== b.priority) return a.priority - b.priority;\n      return a.sequence - b.sequence;\n    });\n    const task = queueRef.current.shift()!;\n    activeCountRef.current += 1;\n    setLoading(true);\n    updateQueueSize();\n\n    const fn = workerFnRef.current;\n    fn(task.data)\n      .then((value) => {\n        setResult(value);\n        setError(undefined);\n        task.resolve(value);\n      })\n      .catch((err) => {\n        setError(err);\n        task.reject(err);\n      })\n      .finally(() => {\n        activeCountRef.current -= 1;\n        updateQueueSize();\n        processNext();\n      });\n\n    // Fill remaining slots (parallel mode).\n    if (queueRef.current.length > 0 && activeCountRef.current < maxConcurrent) {\n      processNext();\n    }\n  }, [maxConcurrent, updateQueueSize]);\n\n  const run = useCallback(\n    (data: TData, runOptions?: RunOptions): Promise<TResult> => {\n      if (terminatedRef.current) {\n        return Promise.reject(new Error(\"Worker is terminated\"));\n      }\n      const priority = runOptions?.priority ?? DEFAULT_PRIORITY;\n      const sequence = ++sequenceRef.current;\n      const promise = new Promise<TResult>((resolve, reject) => {\n        queueRef.current.push({ data, priority, sequence, resolve, reject });\n      });\n      updateQueueSize();\n      setLoading(true);\n      queueMicrotask(processNext);\n      return promise;\n    },\n    [processNext, updateQueueSize]\n  );\n\n  const clearQueue = useCallback(() => {\n    const pending = queueRef.current;\n    queueRef.current = [];\n    pending.forEach((t) => t.reject(new Error(\"Task cleared from queue\")));\n    updateQueueSize();\n    if (activeCountRef.current === 0) setLoading(false);\n  }, [updateQueueSize]);\n\n  const terminate = useCallback(() => {\n    terminatedRef.current = true;\n    clearQueue();\n  }, [clearQueue]);\n\n  // Reset terminated on unmount so the same hook instance can't be \"revived\" without options change.\n  useEffect(() => {\n    return () => {\n      terminatedRef.current = true;\n    };\n  }, []);\n\n  return {\n    run,\n    loading,\n    result,\n    error,\n    queueSize,\n    clearQueue,\n    terminate,\n  };\n}\n","/**\n * Opens IndexedDB and runs onupgradeneeded to create stores and indexes.\n * Singleton per (name, version).\n * @module indexedDB/openDB\n */\n\nimport type { IndexedDBConfig, TableSchema } from \"./types\";\n\nconst connectionCache = new Map<string, Promise<IDBDatabase>>();\n\n/**\n * Opens the database and creates/upgrades object stores and indexes from config.\n * Uses a singleton cache per (name, version); repeated calls with the same config reuse the same connection.\n */\nexport function openDB(config: IndexedDBConfig): Promise<IDBDatabase> {\n  const key = `${config.name}_v${config.version}`;\n  let promise = connectionCache.get(key);\n  if (promise) return promise;\n  promise = _openDB(config);\n  connectionCache.set(key, promise);\n  return promise;\n}\n\nfunction _openDB(config: IndexedDBConfig): Promise<IDBDatabase> {\n  return new Promise<IDBDatabase>((resolve, reject) => {\n    const request = indexedDB.open(config.name, config.version);\n    request.onerror = () =>\n      reject(request.error ?? new DOMException(\"Failed to open database\"));\n    request.onsuccess = () => resolve(request.result);\n    request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\n      const db = (event.target as IDBOpenDBRequest).result;\n      const tables = config.tables;\n      for (const tableName of Object.keys(tables)) {\n        const schema = tables[tableName] as TableSchema;\n        if (!db.objectStoreNames.contains(tableName)) {\n          const store = db.createObjectStore(tableName, {\n            keyPath: schema.keyPath,\n            autoIncrement: schema.autoIncrement ?? false,\n          });\n          if (schema.indexes) {\n            for (const indexName of schema.indexes) {\n              store.createIndex(indexName, indexName, { unique: false });\n            }\n          }\n        }\n      }\n    };\n  });\n}\n","/**\n * Wraps an IDBRequest in a Promise.\n * @module indexedDB/requestToPromise\n */\n\n/**\n * Converts an IDBRequest to a Promise. Rejects with the request's error on failure.\n * @param request - Native IndexedDB request.\n * @returns Promise that resolves with the request result or rejects with DOMException.\n */\nexport function requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n  return new Promise<T>((resolve, reject) => {\n    request.onsuccess = () => resolve(request.result);\n    request.onerror = () =>\n      reject(request.error ?? new DOMException(\"Unknown IndexedDB error\"));\n  });\n}\n","/**\n * Table controller: insert, update, delete, exists, query, upsert, bulkInsert, clear, count.\n * Works in standalone mode (opens its own transaction per op) or bound to a transaction.\n * @module indexedDB/tableController\n */\n\nimport type { OperationCallbacks } from \"./types\";\nimport { requestToPromise } from \"./requestToPromise\";\n\n/** Runs optional callbacks and returns the result. */\nfunction withCallbacks<T>(\n  promise: Promise<T>,\n  options?: OperationCallbacks<T>\n): Promise<T> {\n  if (!options) return promise;\n  return promise\n    .then((result) => {\n      options.onSuccess?.(result);\n      return result;\n    })\n    .catch((err: DOMException) => {\n      options.onError?.(err);\n      throw err;\n    });\n}\n\n/**\n * Standalone table controller: opens a new transaction for each operation.\n */\nfunction createStandaloneController(\n  db: IDBDatabase,\n  tableName: string\n): ITableController {\n  function getStore(mode: IDBTransactionMode): IDBObjectStore {\n    const tx = db.transaction([tableName], mode);\n    return tx.objectStore(tableName);\n  }\n\n  return {\n    insert<T>(\n      data: T,\n      options?: OperationCallbacks<IDBValidKey>\n    ): Promise<IDBValidKey> {\n      const store = getStore(\"readwrite\");\n      return withCallbacks(requestToPromise(store.add(data)), options);\n    },\n\n    update<T>(\n      key: IDBValidKey,\n      updates: Partial<T>,\n      options?: OperationCallbacks<void>\n    ): Promise<void> {\n      const store = getStore(\"readwrite\");\n      const getReq = store.get(key);\n      return withCallbacks(\n        requestToPromise(getReq)\n          .then((existing) => {\n            if (existing === undefined) {\n              throw new DOMException(\"Key not found\", \"NotFoundError\");\n            }\n            const merged = { ...existing, ...updates } as T;\n            return requestToPromise(store.put(merged));\n          })\n          .then(() => undefined),\n        options\n      );\n    },\n\n    delete(\n      key: IDBValidKey,\n      options?: OperationCallbacks<void>\n    ): Promise<void> {\n      const store = getStore(\"readwrite\");\n      return withCallbacks(\n        requestToPromise(store.delete(key)).then(() => undefined),\n        options\n      );\n    },\n\n    exists(key: IDBValidKey): Promise<boolean> {\n      const store = getStore(\"readonly\");\n      return requestToPromise(store.getKey(key)).then((k) => k !== undefined);\n    },\n\n    query<T>(\n      filterFn: (item: T) => boolean,\n      options?: OperationCallbacks<T[]>\n    ): Promise<T[]> {\n      const store = getStore(\"readonly\");\n      const request = store.openCursor();\n      const results: T[] = [];\n      return withCallbacks(\n        new Promise<T[]>((resolve, reject) => {\n          request.onsuccess = () => {\n            const cursor = request.result;\n            if (cursor) {\n              if (filterFn(cursor.value as T)) results.push(cursor.value as T);\n              cursor.continue();\n            } else {\n              resolve(results);\n            }\n          };\n          request.onerror = () =>\n            reject(request.error ?? new DOMException(\"Unknown error\"));\n        }),\n        options\n      );\n    },\n\n    upsert<T>(\n      data: T,\n      options?: OperationCallbacks<IDBValidKey>\n    ): Promise<IDBValidKey> {\n      const store = getStore(\"readwrite\");\n      return withCallbacks(requestToPromise(store.put(data)), options);\n    },\n\n    bulkInsert<T>(\n      items: T[],\n      options?: OperationCallbacks<IDBValidKey[]>\n    ): Promise<IDBValidKey[]> {\n      const store = getStore(\"readwrite\");\n      const keys: IDBValidKey[] = [];\n      if (items.length === 0) {\n        return withCallbacks(Promise.resolve(keys), options);\n      }\n      let completed = 0;\n      const promise = new Promise<IDBValidKey[]>((resolve, reject) => {\n        const onDone = () => {\n          completed++;\n          if (completed === items.length) resolve(keys);\n        };\n        items.forEach((item, i) => {\n          const req = store.add(item);\n          req.onsuccess = () => {\n            keys[i] = req.result;\n            onDone();\n          };\n          req.onerror = () =>\n            reject(req.error ?? new DOMException(\"Unknown error\"));\n        });\n      });\n      return withCallbacks(promise, options);\n    },\n\n    clear(options?: OperationCallbacks<void>): Promise<void> {\n      const store = getStore(\"readwrite\");\n      return withCallbacks(\n        requestToPromise(store.clear()).then(() => undefined),\n        options\n      );\n    },\n\n    count(options?: OperationCallbacks<number>): Promise<number> {\n      const store = getStore(\"readonly\");\n      return withCallbacks(requestToPromise(store.count()), options ?? {});\n    },\n  };\n}\n\n/**\n * Transaction-scoped table controller: uses the given transaction (no new transaction).\n */\nfunction createTransactionController(\n  tx: IDBTransaction,\n  tableName: string\n): ITableController {\n  function getStore(): IDBObjectStore {\n    return tx.objectStore(tableName);\n  }\n\n  return {\n    insert<T>(\n      data: T,\n      options?: OperationCallbacks<IDBValidKey>\n    ): Promise<IDBValidKey> {\n      const store = getStore();\n      return withCallbacks(requestToPromise(store.add(data)), options);\n    },\n\n    update<T>(\n      key: IDBValidKey,\n      updates: Partial<T>,\n      options?: OperationCallbacks<void>\n    ): Promise<void> {\n      const store = getStore();\n      return withCallbacks(\n        requestToPromise(store.get(key))\n          .then((existing) => {\n            if (existing === undefined) {\n              throw new DOMException(\"Key not found\", \"NotFoundError\");\n            }\n            const merged = { ...existing, ...updates } as T;\n            return requestToPromise(store.put(merged));\n          })\n          .then(() => undefined),\n        options\n      );\n    },\n\n    delete(\n      key: IDBValidKey,\n      options?: OperationCallbacks<void>\n    ): Promise<void> {\n      const store = getStore();\n      return withCallbacks(\n        requestToPromise(store.delete(key)).then(() => undefined),\n        options\n      );\n    },\n\n    exists(key: IDBValidKey): Promise<boolean> {\n      const store = getStore();\n      return requestToPromise(store.getKey(key)).then((k) => k !== undefined);\n    },\n\n    query<T>(\n      filterFn: (item: T) => boolean,\n      options?: OperationCallbacks<T[]>\n    ): Promise<T[]> {\n      const store = getStore();\n      const request = store.openCursor();\n      const results: T[] = [];\n      return withCallbacks(\n        new Promise<T[]>((resolve, reject) => {\n          request.onsuccess = () => {\n            const cursor = request.result;\n            if (cursor) {\n              if (filterFn(cursor.value as T)) results.push(cursor.value as T);\n              cursor.continue();\n            } else {\n              resolve(results);\n            }\n          };\n          request.onerror = () =>\n            reject(request.error ?? new DOMException(\"Unknown error\"));\n        }),\n        options\n      );\n    },\n\n    upsert<T>(\n      data: T,\n      options?: OperationCallbacks<IDBValidKey>\n    ): Promise<IDBValidKey> {\n      const store = getStore();\n      return withCallbacks(requestToPromise(store.put(data)), options);\n    },\n\n    bulkInsert<T>(\n      items: T[],\n      options?: OperationCallbacks<IDBValidKey[]>\n    ): Promise<IDBValidKey[]> {\n      const store = getStore();\n      const keys: IDBValidKey[] = [];\n      if (items.length === 0) {\n        return withCallbacks(Promise.resolve(keys), options);\n      }\n      let completed = 0;\n      const promise = new Promise<IDBValidKey[]>((resolve, reject) => {\n        items.forEach((item, i) => {\n          const req = store.add(item);\n          req.onsuccess = () => {\n            keys[i] = req.result;\n            completed++;\n            if (completed === items.length) resolve(keys);\n          };\n          req.onerror = () =>\n            reject(req.error ?? new DOMException(\"Unknown error\"));\n        });\n      });\n      return withCallbacks(promise, options);\n    },\n\n    clear(options?: OperationCallbacks<void>): Promise<void> {\n      const store = getStore();\n      return withCallbacks(\n        requestToPromise(store.clear()).then(() => undefined),\n        options\n      );\n    },\n\n    count(options?: OperationCallbacks<number>): Promise<number> {\n      const store = getStore();\n      return withCallbacks(requestToPromise(store.count()), options ?? {});\n    },\n  };\n}\n\n/** Public interface for a table controller (standalone or transaction-scoped). */\nexport interface ITableController {\n  insert<T>(\n    data: T,\n    options?: OperationCallbacks<IDBValidKey>\n  ): Promise<IDBValidKey>;\n  update<T>(\n    key: IDBValidKey,\n    updates: Partial<T>,\n    options?: OperationCallbacks<void>\n  ): Promise<void>;\n  delete(key: IDBValidKey, options?: OperationCallbacks<void>): Promise<void>;\n  exists(key: IDBValidKey): Promise<boolean>;\n  query<T>(\n    filterFn: (item: T) => boolean,\n    options?: OperationCallbacks<T[]>\n  ): Promise<T[]>;\n  upsert<T>(\n    data: T,\n    options?: OperationCallbacks<IDBValidKey>\n  ): Promise<IDBValidKey>;\n  bulkInsert<T>(\n    items: T[],\n    options?: OperationCallbacks<IDBValidKey[]>\n  ): Promise<IDBValidKey[]>;\n  clear(options?: OperationCallbacks<void>): Promise<void>;\n  count(options?: OperationCallbacks<number>): Promise<number>;\n}\n\nexport function createTableController(\n  db: IDBDatabase,\n  tableName: string\n): ITableController {\n  return createStandaloneController(db, tableName);\n}\n\nexport function createTransactionTableController(\n  tx: IDBTransaction,\n  tableName: string\n): ITableController {\n  return createTransactionController(tx, tableName);\n}\n","/**\n * Preact hook for IndexedDB: open database, create stores/indexes, return a database controller.\n * Uses a singleton connection per (name, version).\n * @module useIndexedDB\n */\n\nimport { useState, useEffect, useRef } from \"preact/hooks\";\nimport type { IndexedDBConfig } from \"./indexedDB/types\";\nimport { openDB } from \"./indexedDB/openDB\";\nimport { createDBController } from \"./indexedDB/dbController\";\nimport type { IDBController } from \"./indexedDB/dbController\";\n\nexport type { IndexedDBConfig, IDBController } from \"./indexedDB\";\n\nexport interface UseIndexedDBReturn {\n  /** Database controller (table, transaction). Null until the database is open. */\n  db: IDBController | null;\n  /** True once the database is open and ready. */\n  isReady: boolean;\n  /** Error from opening the database, if any. */\n  error: DOMException | null;\n}\n\n/**\n * Opens an IndexedDB database and returns a controller for tables and transactions.\n * Handles onupgradeneeded: creates object stores and indexes from config.\n * Connection is a singleton per (config.name, config.version).\n *\n * @param config - Database name, version, and table schemas (keyPath, autoIncrement, indexes).\n * @returns { db, isReady, error }. Use db.table(name) and db.transaction(...) when isReady is true.\n *\n * @example\n * const { db, isReady, error } = useIndexedDB({\n *   name: 'my-db',\n *   version: 1,\n *   tables: {\n *     users: { keyPath: 'id', autoIncrement: true, indexes: ['email'] },\n *   },\n * })\n * if (isReady && db) {\n *   const users = db.table('users')\n *   await users.insert({ email: 'a@b.com' })\n *   await db.transaction(['users'], 'readwrite', (tx) => tx.table('users').insert({ email: 'b@b.com' }))\n * }\n */\nexport function useIndexedDB(config: IndexedDBConfig): UseIndexedDBReturn {\n  const [db, setDb] = useState<IDBController | null>(null);\n  const [error, setError] = useState<DOMException | null>(null);\n  const [isReady, setIsReady] = useState(false);\n  const configRef = useRef(config);\n  configRef.current = config;\n\n  useEffect(() => {\n    let cancelled = false;\n    setError(null);\n    setIsReady(false);\n    setDb(null);\n\n    const { name, version, tables } = configRef.current;\n    openDB({ name, version, tables })\n      .then((database) => {\n        if (cancelled) {\n          database.close();\n          return;\n        }\n        const controller = createDBController(database, configRef.current);\n        setDb(controller);\n        setIsReady(true);\n      })\n      .catch((err: DOMException) => {\n        if (!cancelled) setError(err);\n      });\n\n    return () => {\n      cancelled = true;\n    };\n  }, [config.name, config.version]);\n\n  return { db, isReady, error };\n}\n\n/*\n * Usage example:\n *\n * const { db, isReady, error } = useIndexedDB({\n *   name: 'my-app-db',\n *   version: 1,\n *   tables: {\n *     users: { keyPath: 'id', autoIncrement: true, indexes: ['email'] },\n *     settings: { keyPath: 'key' },\n *   },\n * })\n *\n * if (error) return <div>Failed to open database</div>\n * if (!isReady || !db) return <div>Loading...</div>\n *\n * const users = db.table('users')\n * await users.insert({ email: 'a@b.com', name: 'Alice' })\n * await users.update(1, { name: 'Alice Smith' })\n * const found = await users.query((u) => u.email.startsWith('a@'))\n * const n = await users.count()\n * await users.delete(1)\n * await users.upsert({ id: 2, email: 'b@b.com' })\n * await users.bulkInsert([{ email: 'c@b.com' }, { email: 'd@b.com' }])\n * await users.clear({ onSuccess: () => console.log('cleared') })\n *\n * await db.transaction(['users', 'settings'], 'readwrite', async (tx) => {\n *   await tx.table('users').insert({ email: 'e@b.com' })\n *   await tx.table('settings').upsert({ key: 'theme', value: 'dark' })\n * }, { onSuccess: () => console.log('transaction done') })\n */\n","/**\n * Database controller: table(name), transaction(storeNames, mode, callback, options).\n * @module indexedDB/dbController\n */\n\nimport type { IndexedDBConfig, TransactionOptions } from \"./types\";\nimport type { ITableController } from \"./tableController\";\nimport {\n  createTableController,\n  createTransactionTableController,\n} from \"./tableController\";\n\n/** Transaction context passed to the callback: provides table(name) bound to this transaction. */\nexport interface TransactionContext {\n  /** Returns a table controller bound to this transaction. Use for all ops inside the callback. */\n  table: (name: string) => ITableController;\n}\n\n/**\n * Database controller built from an open IDBDatabase.\n * Exposes table(name) and transaction(...).\n */\nexport interface IDBController {\n  /** Underlying IDBDatabase (read-only). */\n  readonly db: IDBDatabase;\n  /** Returns true if an object store with the given name exists. */\n  hasTable: (name: string) => boolean;\n  /** Returns a table controller for the given store (each op opens its own transaction). */\n  table: (name: string) => ITableController;\n  /**\n   * Runs a callback inside a single transaction. All operations in the callback use the same transaction.\n   * @param storeNames - Object store names to include in the transaction.\n   * @param mode - 'readonly' | 'readwrite'.\n   * @param callback - Async or sync function receiving { table(name) }. Return value is ignored; await all ops inside.\n   * @param options - Optional onSuccess/onError callbacks.\n   * @returns Promise that resolves when the transaction completes (after all requests and the callback).\n   */\n  transaction: <T = void>(\n    storeNames: string[],\n    mode: IDBTransactionMode,\n    callback: (tx: TransactionContext) => T | Promise<T>,\n    options?: TransactionOptions\n  ) => Promise<void>;\n}\n\nfunction withTransactionCallbacks(\n  promise: Promise<void>,\n  options?: TransactionOptions\n): Promise<void> {\n  if (!options) return promise;\n  return promise\n    .then(() => options.onSuccess?.())\n    .catch((err: DOMException) => {\n      options.onError?.(err);\n      throw err;\n    });\n}\n\n/**\n * Creates a database controller from an open IDBDatabase instance.\n */\nexport function createDBController(\n  db: IDBDatabase,\n  _config: IndexedDBConfig\n): IDBController {\n  void _config; // Reserved for future config options\n  return {\n    get db(): IDBDatabase {\n      return db;\n    },\n\n    hasTable(name: string): boolean {\n      return db.objectStoreNames.contains(name);\n    },\n\n    table(name: string): ITableController {\n      return createTableController(db, name);\n    },\n\n    transaction<T = void>(\n      storeNames: string[],\n      mode: IDBTransactionMode,\n      callback: (tx: TransactionContext) => T | Promise<T>,\n      options?: TransactionOptions\n    ): Promise<void> {\n      const tx = db.transaction(storeNames, mode);\n      const txContext: TransactionContext = {\n        table: (tableName: string) =>\n          createTransactionTableController(tx, tableName),\n      };\n      const txPromise = new Promise<void>((resolve, reject) => {\n        tx.oncomplete = () => resolve();\n        tx.onerror = () =>\n          reject(tx.error ?? new DOMException(\"Transaction failed\"));\n      });\n      const callbackResult = callback(txContext);\n      const promise = Promise.resolve(callbackResult).then(() => txPromise);\n      return withTransactionCallbacks(promise, options);\n    },\n  };\n}\n","/**\n * useWebRTCIP – detect local/public IPs via WebRTC ICE candidates and STUN.\n * Not highly reliable; use as first-priority hint and fall back to a public IP API (e.g. ipapi.co) if needed.\n * @module useWebRTCIP\n */\n\nimport { useEffect, useState, useRef } from \"preact/hooks\";\n\n/** IPv4 regex for ICE candidate strings (captures dotted-decimal). */\nconst IPV4_REGEX =\n  /\\b(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})(?:\\.(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})){3}\\b/g;\n\nconst DEFAULT_STUN_SERVERS: string[] = [\"stun:stun.l.google.com:19302\"];\nconst DEFAULT_TIMEOUT_MS = 3000;\n\nexport interface UseWebRTCIPOptions {\n  /** STUN server URLs (default: Google STUN). */\n  stunServers?: string[];\n  /** Stop gathering after this many ms (default: 3000). */\n  timeout?: number;\n  /** Called once per newly detected IP (no duplicates). */\n  onDetect?: (ip: string) => void;\n}\n\nexport interface UseWebRTCIPReturn {\n  /** Unique IPv4 addresses found from ICE candidates. */\n  ips: string[];\n  /** True while ICE gathering is in progress. */\n  loading: boolean;\n  /** Error message if WebRTC is unavailable or detection fails. */\n  error: string | null;\n}\n\nfunction isSSR(): boolean {\n  return typeof window === \"undefined\";\n}\n\nfunction isWebRTCAvailable(): boolean {\n  return typeof RTCPeerConnection !== \"undefined\";\n}\n\n/**\n * Extracts IPv4 addresses from an ICE candidate string.\n * Filters out common non-public/local patterns (e.g. 0.0.0.0) if desired; currently returns all matches.\n */\nfunction extractIPv4FromCandidate(candidate: string): string[] {\n  const matches = candidate.match(IPV4_REGEX);\n  return matches ? [...matches] : [];\n}\n\n/**\n * Attempts to detect client IP addresses using WebRTC ICE candidates and a STUN server.\n * Works frontend-only (no backend). Not guaranteed to return a public IP; use as a hint and\n * fall back to a public IP API (e.g. ipapi.co, ip-api.com) if you need reliability.\n *\n * @param options - Optional: stunServers, timeout (ms), onDetect(ip) callback.\n * @returns { ips, loading, error } – unique IPv4s, loading flag, and error message.\n *\n * @example\n * const { ips, loading, error } = useWebRTCIP({\n *   timeout: 5000,\n *   onDetect: (ip) => console.log('Detected:', ip),\n * })\n * // If ips is empty and error is set, fall back to: fetch('https://api.ipify.org?format=json')\n */\nexport function useWebRTCIP(\n  options: UseWebRTCIPOptions = {}\n): UseWebRTCIPReturn {\n  const {\n    stunServers = DEFAULT_STUN_SERVERS,\n    timeout: timeoutMs = DEFAULT_TIMEOUT_MS,\n    onDetect,\n  } = options;\n\n  const [ips, setIps] = useState<string[]>([]);\n  const [loading, setLoading] = useState(true);\n  const [error, setError] = useState<string | null>(null);\n\n  const pcRef = useRef<RTCPeerConnection | null>(null);\n  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const reportedRef = useRef<Set<string>>(new Set());\n  const onDetectRef = useRef(onDetect);\n  onDetectRef.current = onDetect;\n\n  useEffect(() => {\n    if (isSSR()) {\n      setLoading(false);\n      setError(\"WebRTC IP detection is not available during SSR\");\n      return;\n    }\n\n    if (!isWebRTCAvailable()) {\n      setLoading(false);\n      setError(\"RTCPeerConnection is not available\");\n      return;\n    }\n\n    const reported = new Set<string>();\n    reportedRef.current = reported;\n\n    const finish = () => {\n      if (timeoutRef.current) {\n        clearTimeout(timeoutRef.current);\n        timeoutRef.current = null;\n      }\n      if (pcRef.current) {\n        pcRef.current.close();\n        pcRef.current = null;\n      }\n      setLoading(false);\n    };\n\n    const addIP = (ip: string) => {\n      if (reported.has(ip)) return;\n      reported.add(ip);\n      setIps((prev) => {\n        const next = [...prev, ip];\n        return next;\n      });\n      onDetectRef.current?.(ip);\n    };\n\n    try {\n      const pc = new RTCPeerConnection({\n        iceServers: [{ urls: stunServers }],\n      });\n      pcRef.current = pc;\n\n      pc.onicecandidate = (event) => {\n        const c = event.candidate;\n        if (!c || !c.candidate) return;\n        const found = extractIPv4FromCandidate(c.candidate);\n        found.forEach(addIP);\n      };\n\n      pc.createDataChannel(\"\");\n\n      pc.createOffer()\n        .then((offer) => pc.setLocalDescription(offer))\n        .catch((err) => {\n          setError(\n            err instanceof Error ? err.message : \"Failed to create offer\"\n          );\n          finish();\n        });\n\n      timeoutRef.current = setTimeout(() => finish(), timeoutMs);\n    } catch (err) {\n      setError(err instanceof Error ? err.message : \"WebRTC setup failed\");\n      finish();\n    }\n\n    return () => {\n      finish();\n    };\n  }, [stunServers.join(\",\"), timeoutMs]);\n\n  return { ips, loading, error };\n}\n\n/*\n * Example usage (Preact component):\n *\n * function MyIPDisplay() {\n *   const { ips, loading, error } = useWebRTCIP({\n *     timeout: 4000,\n *     onDetect: (ip) => { / * optional: e.g. send to analytics * / },\n *   })\n *\n *   if (loading) return <p>Detecting IP…</p>\n *   if (error) return <p>WebRTC failed: {error}. Try fallback API.</p>\n *   return <p>IPs (WebRTC): {ips.join(', ') || 'None'}</p>\n * }\n *\n * Fallback to public IP API when WebRTC fails or returns empty:\n *   const [apiIP, setApiIP] = useState<string | null>(null)\n *   useEffect(() => {\n *     if (!loading && ips.length === 0 && error)\n *       fetch('https://api.ipify.org?format=json').then(r => r.json()).then(d => setApiIP(d.ip))\n *   }, [loading, ips.length, error])\n */\n","/**\n * useWasmCompute – run WebAssembly computation off the main thread via a Web Worker.\n * Flow: Preact Component → useWasmCompute() → Web Worker → WASM Module → Return result.\n * @module useWasmCompute\n */\n\nimport { useState, useCallback, useRef, useEffect } from \"preact/hooks\";\n\nconst WASM_WORKER_SCRIPT = `\nself.onmessage = async (e) => {\n  const d = e.data;\n  if (d.type === 'init') {\n    try {\n      const res = await fetch(d.wasmUrl);\n      const buf = await res.arrayBuffer();\n      const mod = await WebAssembly.instantiate(buf, d.importObject || {});\n      self.wasmInstance = mod.instance;\n      self.exportName = d.exportName || 'compute';\n      self.postMessage({ type: 'ready' });\n    } catch (err) {\n      self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n    }\n    return;\n  }\n  if (d.type === 'compute') {\n    try {\n      const fn = self.wasmInstance.exports[self.exportName];\n      if (typeof fn !== 'function') {\n        self.postMessage({ type: 'error', error: 'Export \"' + self.exportName + '\" is not a function' });\n        return;\n      }\n      const result = fn(d.input);\n      self.postMessage({ type: 'result', result: result });\n    } catch (err) {\n      self.postMessage({ type: 'error', error: (err && err.message) || String(err) });\n    }\n  }\n};\n`;\n\nexport interface UseWasmComputeOptions {\n  /** URL of the .wasm module to load in the worker. */\n  wasmUrl: string;\n  /** Name of the exported function to call for compute (default: 'compute'). */\n  exportName?: string;\n  /** Optional custom worker script URL. If provided, worker must handle init (wasmUrl, exportName) and compute(input) messages. */\n  workerUrl?: string;\n  /** Optional import object for WebAssembly.instantiate (only used when using default inline worker; must be serializable). */\n  importObject?: WebAssembly.Imports;\n}\n\nexport interface UseWasmComputeReturn<TInput = number, TResult = number> {\n  /** Invoke the WASM export with the given input. Resolves with the return value when ready. */\n  compute: (input: TInput) => Promise<TResult>;\n  /** Last result from a successful compute call. */\n  result: TResult | undefined;\n  /** True while WASM is loading or a compute is in progress. */\n  loading: boolean;\n  /** Error message if environment is unsupported, init failed, or compute failed. */\n  error: string | null;\n  /** True when the WASM module is loaded and compute can be called. */\n  ready: boolean;\n}\n\nfunction isSSR(): boolean {\n  return typeof window === \"undefined\";\n}\n\nfunction isWorkerSupported(): boolean {\n  return typeof Worker !== \"undefined\";\n}\n\nfunction isWebAssemblySupported(): boolean {\n  return (\n    typeof WebAssembly !== \"undefined\" &&\n    typeof WebAssembly.instantiate === \"function\"\n  );\n}\n\nfunction createWorker(workerUrl?: string): Worker {\n  if (workerUrl) {\n    return new Worker(workerUrl);\n  }\n  const blob = new Blob([WASM_WORKER_SCRIPT], {\n    type: \"application/javascript\",\n  });\n  const url = URL.createObjectURL(blob);\n  const w = new Worker(url);\n  URL.revokeObjectURL(url);\n  return w;\n}\n\n/**\n * Runs WebAssembly computation in a Web Worker. Validates environment (browser, Worker, WebAssembly)\n * and returns a stable compute function plus result/loading/error/ready state.\n *\n * @param options - wasmUrl, optional exportName, optional workerUrl, optional importObject.\n * @returns { compute, result, loading, error, ready }.\n *\n * @example\n * const { compute, result, loading, error, ready } = useWasmCompute({ wasmUrl: '/add.wasm', exportName: 'add' });\n * // When ready: compute(2).then(sum => ...); result will update with the last return value.\n */\nexport function useWasmCompute<TInput = number, TResult = number>(\n  options: UseWasmComputeOptions\n): UseWasmComputeReturn<TInput, TResult> {\n  const { wasmUrl, exportName = \"compute\", workerUrl, importObject } = options;\n\n  const [result, setResult] = useState<TResult | undefined>(undefined);\n  const [loading, setLoading] = useState(true);\n  const [error, setError] = useState<string | null>(null);\n  const [ready, setReady] = useState(false);\n\n  const workerRef = useRef<Worker | null>(null);\n  const pendingResolveRef = useRef<((value: TResult) => void) | null>(null);\n  const pendingRejectRef = useRef<((reason: Error) => void) | null>(null);\n\n  useEffect(() => {\n    if (isSSR()) {\n      setError(\"useWasmCompute is not available during SSR\");\n      setLoading(false);\n      return;\n    }\n    if (!isWorkerSupported()) {\n      setError(\"Worker is not supported in this environment\");\n      setLoading(false);\n      return;\n    }\n    if (!isWebAssemblySupported()) {\n      setError(\"WebAssembly is not supported in this environment\");\n      setLoading(false);\n      return;\n    }\n\n    setError(null);\n    setReady(false);\n    const worker = createWorker(workerUrl);\n    workerRef.current = worker;\n\n    const onMessage = (e: MessageEvent) => {\n      const { type, result: msgResult, error: msgError } = e.data ?? {};\n      if (type === \"ready\") {\n        setReady(true);\n        setLoading(false);\n        return;\n      }\n      if (type === \"error\") {\n        setError(msgError ?? \"Unknown error\");\n        setLoading(false);\n        if (pendingRejectRef.current) {\n          pendingRejectRef.current(new Error(msgError));\n          pendingResolveRef.current = null;\n          pendingRejectRef.current = null;\n        }\n        return;\n      }\n      if (type === \"result\") {\n        setResult(msgResult);\n        setLoading(false);\n        if (pendingResolveRef.current) {\n          pendingResolveRef.current(msgResult);\n          pendingResolveRef.current = null;\n          pendingRejectRef.current = null;\n        }\n      }\n    };\n\n    worker.addEventListener(\"message\", onMessage);\n    worker.postMessage({\n      type: \"init\",\n      wasmUrl,\n      exportName,\n      importObject: importObject ?? {},\n    });\n\n    return () => {\n      worker.removeEventListener(\"message\", onMessage);\n      worker.terminate();\n      workerRef.current = null;\n      if (pendingRejectRef.current) {\n        pendingRejectRef.current(new Error(\"Worker terminated\"));\n        pendingResolveRef.current = null;\n        pendingRejectRef.current = null;\n      }\n    };\n  }, [wasmUrl, exportName, workerUrl, importObject]);\n\n  const compute = useCallback(\n    (input: TInput): Promise<TResult> => {\n      return new Promise((resolve, reject) => {\n        if (!workerRef.current || !ready) {\n          reject(new Error(\"WASM not ready\"));\n          return;\n        }\n        if (error) {\n          reject(new Error(error));\n          return;\n        }\n        pendingResolveRef.current = resolve;\n        pendingRejectRef.current = reject;\n        setLoading(true);\n        workerRef.current.postMessage({ type: \"compute\", input });\n      });\n    },\n    [ready, error]\n  );\n\n  return { compute, result, loading, error, ready };\n}\n","/**\n * useWorkerNotifications – listen to worker messages and maintain running state, counts, history, and derived stats.\n * @module useWorkerNotifications\n */\n\nimport { useState, useRef, useEffect, useMemo } from \"preact/hooks\";\n\n/** Supported worker event types for tracking. Worker should postMessage with these shapes. */\nexport type WorkerEventType =\n  | \"task_start\"\n  | \"task_end\"\n  | \"task_fail\"\n  | \"queue_size\";\n\nexport interface WorkerNotificationEvent {\n  type: WorkerEventType;\n  taskId?: string;\n  duration?: number;\n  error?: string;\n  size?: number;\n  timestamp: number;\n}\n\nexport interface UseWorkerNotificationsOptions {\n  /** Max events to keep in history. Default 100. */\n  maxHistory?: number;\n  /** Window in ms for throughput calculation (completed per second). Default 1000. */\n  throughputWindowMs?: number;\n}\n\nexport interface UseWorkerNotificationsReturn {\n  /** Task IDs currently running (received task_start, not yet task_end/task_fail). */\n  runningTasks: string[];\n  /** Total tasks that completed successfully. */\n  completedCount: number;\n  /** Total tasks that failed. */\n  failedCount: number;\n  /** Recent events (oldest first), capped at maxHistory. */\n  eventHistory: WorkerNotificationEvent[];\n  /** Average task duration in ms (from task_end events that include duration). */\n  averageDurationMs: number;\n  /** Completed tasks per second over the throughput window. */\n  throughputPerSecond: number;\n  /** Last reported queue size (from queue_size events); 0 if never sent. */\n  currentQueueSize: number;\n  /** Default view: all active worker data and progress in one object. */\n  progress: {\n    runningTasks: string[];\n    completedCount: number;\n    failedCount: number;\n    averageDurationMs: number;\n    throughputPerSecond: number;\n    currentQueueSize: number;\n    totalProcessed: number;\n    recentEventCount: number;\n  };\n}\n\nfunction parseMessage(data: unknown): WorkerNotificationEvent | null {\n  if (data == null || typeof data !== \"object\") return null;\n  const d = data as Record<string, unknown>;\n  const type = d.type as string;\n  if (\n    type !== \"task_start\" &&\n    type !== \"task_end\" &&\n    type !== \"task_fail\" &&\n    type !== \"queue_size\"\n  ) {\n    return null;\n  }\n  const taskId = typeof d.taskId === \"string\" ? d.taskId : undefined;\n  const duration = typeof d.duration === \"number\" ? d.duration : undefined;\n  const error = typeof d.error === \"string\" ? d.error : undefined;\n  const size = typeof d.size === \"number\" ? d.size : undefined;\n  return {\n    type: type as WorkerEventType,\n    taskId,\n    duration,\n    error,\n    size,\n    timestamp: Date.now(),\n  };\n}\n\n/**\n * Listens to a Worker's messages and maintains state: running tasks, completed/failed counts,\n * event history, execution time per task, average duration, throughput per second, and queue size.\n * Worker should postMessage with: { type: 'task_start'|'task_end'|'task_fail'|'queue_size', taskId?, duration?, error?, size? }.\n *\n * @param worker - The Worker instance to listen to, or null/undefined to listen to nothing.\n * @param options - Optional maxHistory and throughputWindowMs.\n * @returns State and derived stats plus a default progress object.\n */\nexport function useWorkerNotifications(\n  worker: Worker | null | undefined,\n  options: UseWorkerNotificationsOptions = {}\n): UseWorkerNotificationsReturn {\n  const { maxHistory = 100, throughputWindowMs = 1000 } = options;\n\n  const [runningTasks, setRunningTasks] = useState<string[]>([]);\n  const [completedCount, setCompletedCount] = useState(0);\n  const [failedCount, setFailedCount] = useState(0);\n  const [eventHistory, setEventHistory] = useState<WorkerNotificationEvent[]>(\n    []\n  );\n  const [currentQueueSize, setCurrentQueueSize] = useState(0);\n\n  const completedTimestampsRef = useRef<number[]>([]);\n  const durationSumRef = useRef(0);\n  const durationCountRef = useRef(0);\n\n  useEffect(() => {\n    if (!worker) return;\n\n    const onMessage = (e: MessageEvent) => {\n      const ev = parseMessage(e.data);\n      if (!ev) return;\n\n      setEventHistory((prev) => {\n        const next = [...prev, ev].slice(-maxHistory);\n        return next;\n      });\n\n      if (ev.type === \"task_start\" && ev.taskId) {\n        setRunningTasks((prev) =>\n          prev.includes(ev.taskId!) ? prev : [...prev, ev.taskId!]\n        );\n      } else if (ev.type === \"task_end\") {\n        if (ev.taskId) {\n          setRunningTasks((prev) => prev.filter((id) => id !== ev.taskId));\n        }\n        setCompletedCount((c) => c + 1);\n        const cutoff = Date.now() - throughputWindowMs;\n        completedTimestampsRef.current = [\n          ...completedTimestampsRef.current.filter((t) => t >= cutoff),\n          ev.timestamp,\n        ];\n        if (typeof ev.duration === \"number\") {\n          durationSumRef.current += ev.duration;\n          durationCountRef.current += 1;\n        }\n      } else if (ev.type === \"task_fail\") {\n        if (ev.taskId) {\n          setRunningTasks((prev) => prev.filter((id) => id !== ev.taskId));\n        }\n        setFailedCount((c) => c + 1);\n      } else if (ev.type === \"queue_size\" && typeof ev.size === \"number\") {\n        setCurrentQueueSize(ev.size);\n      }\n    };\n\n    worker.addEventListener(\"message\", onMessage);\n    return () => worker.removeEventListener(\"message\", onMessage);\n  }, [worker, maxHistory]);\n\n  const averageDurationMs = useMemo(() => {\n    const count = durationCountRef.current;\n    const sum = durationSumRef.current;\n    return count > 0 ? sum / count : 0;\n  }, [eventHistory]);\n\n  const throughputPerSecond = useMemo(() => {\n    const now = Date.now();\n    const cutoff = now - throughputWindowMs;\n    const timestamps = completedTimestampsRef.current.filter(\n      (t) => t >= cutoff\n    );\n    return timestamps.length / (throughputWindowMs / 1000);\n  }, [eventHistory, throughputWindowMs]);\n\n  const progress = useMemo(\n    () => ({\n      runningTasks,\n      completedCount,\n      failedCount,\n      averageDurationMs,\n      throughputPerSecond,\n      currentQueueSize,\n      totalProcessed: completedCount + failedCount,\n      recentEventCount: eventHistory.length,\n    }),\n    [\n      runningTasks,\n      completedCount,\n      failedCount,\n      averageDurationMs,\n      throughputPerSecond,\n      currentQueueSize,\n      eventHistory.length,\n    ]\n  );\n\n  return {\n    runningTasks,\n    completedCount,\n    failedCount,\n    eventHistory,\n    averageDurationMs,\n    throughputPerSecond,\n    currentQueueSize,\n    progress,\n  };\n}\n","import { useEffect, useRef } from \"react\";\n\nconst SCRIPT_SELECTOR = 'script[data-llm=\"true\"]';\nconst SCRIPT_TYPE = \"application/llm+json\";\n\n/** Max lengths for string fields to avoid huge payloads and XSS surface. */\nconst MAX_TITLE = 200;\nconst MAX_DESCRIPTION = 2000;\nconst MAX_TAG_LENGTH = 100;\nconst MAX_TAGS = 50;\nconst MAX_OUTLINE_ITEM = 300;\nconst MAX_OUTLINE_ITEMS = 50;\nconst MAX_URL_LENGTH = 2048;\nconst MAX_AUTHOR = 200;\nconst MAX_SITE_NAME = 100;\nconst MAX_ROBOTS = 100;\n\n/** Open Graph / content type for og:type. */\nexport type OGType =\n  | \"website\"\n  | \"article\"\n  | \"profile\"\n  | \"video.other\"\n  | \"product\"\n  | \"music.song\"\n  | \"book\";\n\n/** Config for the useLLMMetadata hook. All fields optional except route. */\nexport interface LLMConfig {\n  /** Current route path (e.g. \"/blog/ai-hooks\"). Changes trigger metadata update. */\n  route: string;\n  /** \"manual\" = use title/description/tags from config. \"auto-extract\" = derive from DOM. */\n  mode?: \"manual\" | \"auto-extract\";\n  /** Page title (manual mode). */\n  title?: string;\n  /** Page description (manual mode). */\n  description?: string;\n  /** Tags/keywords (manual mode). */\n  tags?: string[];\n  /** Canonical URL (absolute). */\n  canonicalUrl?: string;\n  /** Content language (e.g. \"en\", \"en-US\"). */\n  language?: string;\n  /** Open Graph type (website, article, etc.). */\n  ogType?: OGType;\n  /** OG image URL (absolute). */\n  ogImage?: string;\n  /** OG image alt text. */\n  ogImageAlt?: string;\n  /** Site name (e.g. for social previews). */\n  siteName?: string;\n  /** Author name (for articles). */\n  author?: string;\n  /** ISO date string (article publish). */\n  publishedTime?: string;\n  /** ISO date string (article last modified). */\n  modifiedTime?: string;\n  /** Robots hint (e.g. \"index, follow\"). */\n  robots?: string;\n  /** Extra key-value pairs (e.g. section, category). Keys/values are sanitized. */\n  extra?: Record<string, string | number | boolean | string[]>;\n}\n\n/** Payload injected as JSON in the LLM script tag. Only includes defined, safe values. */\nexport interface LLMPayload {\n  route: string;\n  title?: string;\n  description?: string;\n  tags?: string[];\n  outline?: string[];\n  canonicalUrl?: string;\n  language?: string;\n  ogType?: string;\n  ogImage?: string;\n  ogImageAlt?: string;\n  siteName?: string;\n  author?: string;\n  publishedTime?: string;\n  modifiedTime?: string;\n  robots?: string;\n  generatedAt: string;\n  extra?: Record<string, string | number | boolean | string[]>;\n}\n\n/** Selectors for elements to ignore when auto-extracting. */\nconst IGNORE_SELECTOR =\n  \"nav, footer, [role='navigation'], [role='contentinfo'], script, style, noscript\";\n\n/**\n * Coerce value to a safe string for JSON. Never throws.\n */\nfunction safeStr(value: unknown, maxLen: number): string {\n  if (value == null) return \"\";\n  const s = typeof value === \"string\" ? value : String(value);\n  const trimmed = s.trim();\n  return trimmed.length > maxLen ? trimmed.slice(0, maxLen) : trimmed;\n}\n\n/**\n * Coerce to safe string array. Never throws.\n */\nfunction safeTagList(value: unknown): string[] {\n  if (!Array.isArray(value)) return [];\n  const out: string[] = [];\n  for (let i = 0; i < value.length && out.length < MAX_TAGS; i++) {\n    const s = safeStr(value[i], MAX_TAG_LENGTH);\n    if (s) out.push(s);\n  }\n  return out;\n}\n\n/**\n * Safe URL: only include if it looks like a valid http(s) URL and within length.\n */\nfunction safeUrl(value: unknown): string {\n  const s = safeStr(value, MAX_URL_LENGTH);\n  if (!s) return \"\";\n  try {\n    const u = new URL(s);\n    if (u.protocol === \"http:\" || u.protocol === \"https:\") return s;\n  } catch {\n    // ignore\n  }\n  return \"\";\n}\n\n/**\n * Returns true if el is visible. Never throws.\n */\nfunction isVisible(el: Element): boolean {\n  try {\n    if (typeof window === \"undefined\") return false;\n    const style = window.getComputedStyle(el);\n    return (\n      style.display !== \"none\" &&\n      style.visibility !== \"hidden\" &&\n      style.opacity !== \"0\"\n    );\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Auto-extract title, outline (h1/h2), and first 3 visible paragraphs.\n * Fully safe: never throws; returns defaults on any error.\n */\nfunction autoExtract(): {\n  title: string;\n  outline: string[];\n  description: string;\n} {\n  const empty = { title: \"\", outline: [] as string[], description: \"\" };\n  try {\n    if (typeof document === \"undefined\") return empty;\n    const title = safeStr(document.title, MAX_TITLE);\n    const outline: string[] = [];\n    let description = \"\";\n\n    try {\n      const ignoreRoots = document.querySelectorAll(IGNORE_SELECTOR);\n      const isInsideIgnored = (el: Element): boolean => {\n        for (const root of ignoreRoots) {\n          if (root.contains(el)) return true;\n        }\n        return false;\n      };\n\n      const headings = document.querySelectorAll(\"h1, h2\");\n      for (const h of headings) {\n        if (outline.length >= MAX_OUTLINE_ITEMS) break;\n        if (isVisible(h) && !isInsideIgnored(h)) {\n          const text = safeStr(h.textContent, MAX_OUTLINE_ITEM);\n          if (text) outline.push(text);\n        }\n      }\n\n      const paragraphs = document.querySelectorAll(\"p\");\n      const visibleParagraphs: string[] = [];\n      for (const p of paragraphs) {\n        if (visibleParagraphs.length >= 3) break;\n        if (isVisible(p) && !isInsideIgnored(p)) {\n          const text = safeStr(p.textContent, 1000);\n          if (text) visibleParagraphs.push(text);\n        }\n      }\n      description =\n        visibleParagraphs.join(\" \").trim().slice(0, MAX_DESCRIPTION) || \"\";\n    } catch {\n      // keep title, empty outline/description\n    }\n\n    return { title, outline, description };\n  } catch {\n    return empty;\n  }\n}\n\n/**\n * Normalize config to a safe object. Never throws.\n */\nfunction normalizeConfig(config: LLMConfig | null | undefined): LLMConfig {\n  if (config == null || typeof config !== \"object\") {\n    return { route: \"/\" };\n  }\n  return {\n    route: safeStr(config.route, 2048) || \"/\",\n    mode: config.mode === \"auto-extract\" ? \"auto-extract\" : \"manual\",\n    title:\n      config.title !== undefined ? safeStr(config.title, MAX_TITLE) : undefined,\n    description:\n      config.description !== undefined\n        ? safeStr(config.description, MAX_DESCRIPTION)\n        : undefined,\n    tags: config.tags !== undefined ? safeTagList(config.tags) : undefined,\n    canonicalUrl:\n      config.canonicalUrl !== undefined\n        ? safeUrl(config.canonicalUrl)\n        : undefined,\n    language:\n      config.language !== undefined ? safeStr(config.language, 20) : undefined,\n    ogType:\n      config.ogType !== undefined\n        ? (safeStr(config.ogType, 50) as OGType)\n        : undefined,\n    ogImage: config.ogImage !== undefined ? safeUrl(config.ogImage) : undefined,\n    ogImageAlt:\n      config.ogImageAlt !== undefined\n        ? safeStr(config.ogImageAlt, 200)\n        : undefined,\n    siteName:\n      config.siteName !== undefined\n        ? safeStr(config.siteName, MAX_SITE_NAME)\n        : undefined,\n    author:\n      config.author !== undefined\n        ? safeStr(config.author, MAX_AUTHOR)\n        : undefined,\n    publishedTime:\n      config.publishedTime !== undefined\n        ? safeStr(config.publishedTime, 50)\n        : undefined,\n    modifiedTime:\n      config.modifiedTime !== undefined\n        ? safeStr(config.modifiedTime, 50)\n        : undefined,\n    robots:\n      config.robots !== undefined\n        ? safeStr(config.robots, MAX_ROBOTS)\n        : undefined,\n    extra:\n      config.extra !== undefined &&\n      typeof config.extra === \"object\" &&\n      !Array.isArray(config.extra)\n        ? sanitizeExtra(config.extra)\n        : undefined,\n  };\n}\n\n/**\n * Sanitize extra object: only string/number/boolean/string[] values; keys and strings bounded.\n */\nfunction sanitizeExtra(\n  extra: Record<string, unknown>\n): Record<string, string | number | boolean | string[]> {\n  const out: Record<string, string | number | boolean | string[]> = {};\n  try {\n    for (const key of Object.keys(extra).slice(0, 20)) {\n      const safeKey = safeStr(key, 50);\n      if (!safeKey) continue;\n      const v = extra[key];\n      if (typeof v === \"string\") out[safeKey] = v.slice(0, 500);\n      else if (typeof v === \"number\" && Number.isFinite(v)) out[safeKey] = v;\n      else if (typeof v === \"boolean\") out[safeKey] = v;\n      else if (Array.isArray(v))\n        out[safeKey] = v\n          .map((x) => safeStr(x, 200))\n          .filter(Boolean)\n          .slice(0, 20);\n    }\n  } catch {\n    // ignore\n  }\n  return out;\n}\n\n/**\n * Build the LLM payload. Never throws; returns minimal payload on any error.\n */\nfunction buildPayload(normalized: LLMConfig): LLMPayload {\n  try {\n    const generatedAt = new Date().toISOString();\n    const base: LLMPayload = {\n      route: normalized.route,\n      generatedAt,\n    };\n\n    if (normalized.mode === \"auto-extract\") {\n      const extracted = autoExtract();\n      base.title = (normalized.title ?? extracted.title) || undefined;\n      base.description =\n        (normalized.description ?? extracted.description) || undefined;\n      if (extracted.outline.length > 0) base.outline = extracted.outline;\n    } else {\n      if (normalized.title !== undefined && normalized.title !== \"\")\n        base.title = normalized.title;\n      if (normalized.description !== undefined && normalized.description !== \"\")\n        base.description = normalized.description;\n    }\n\n    if (normalized.tags && normalized.tags.length > 0)\n      base.tags = normalized.tags;\n    if (normalized.canonicalUrl) base.canonicalUrl = normalized.canonicalUrl;\n    if (normalized.language) base.language = normalized.language;\n    if (normalized.ogType) base.ogType = normalized.ogType;\n    if (normalized.ogImage) base.ogImage = normalized.ogImage;\n    if (normalized.ogImageAlt) base.ogImageAlt = normalized.ogImageAlt;\n    if (normalized.siteName) base.siteName = normalized.siteName;\n    if (normalized.author) base.author = normalized.author;\n    if (normalized.publishedTime) base.publishedTime = normalized.publishedTime;\n    if (normalized.modifiedTime) base.modifiedTime = normalized.modifiedTime;\n    if (normalized.robots) base.robots = normalized.robots;\n    if (normalized.extra && Object.keys(normalized.extra).length > 0)\n      base.extra = normalized.extra;\n\n    return base;\n  } catch {\n    return {\n      route: normalized?.route ?? \"/\",\n      generatedAt: new Date().toISOString(),\n    };\n  }\n}\n\n/**\n * Remove any existing LLM script. Never throws.\n */\nfunction removeExistingScript(): void {\n  try {\n    if (typeof document === \"undefined\" || !document.querySelectorAll) return;\n    document.querySelectorAll(SCRIPT_SELECTOR).forEach((el) => el.remove());\n  } catch {\n    // ignore\n  }\n}\n\n/**\n * Inject a new LLM script. Never throws.\n */\nfunction injectScript(payload: LLMPayload): void {\n  try {\n    if (typeof document === \"undefined\" || !document.head) return;\n    const script = document.createElement(\"script\");\n    script.type = SCRIPT_TYPE;\n    script.setAttribute(\"data-llm\", \"true\");\n    script.textContent = JSON.stringify(payload);\n    document.head.appendChild(script);\n  } catch {\n    // ignore\n  }\n}\n\n/**\n * Production-ready hook: injects an AI-readable metadata block into the document head\n * when the route changes. Framework-agnostic (React 18+ and Preact 10+ via aliasing).\n *\n * - Rich structure: route, title, description, tags, outline (auto), canonicalUrl, language,\n *   ogType, ogImage, ogImageAlt, siteName, author, publishedTime, modifiedTime, robots, extra.\n * - Safe usage: never throws; invalid/missing config is normalized; DOM and JSON are guarded.\n * - Cacheable: if the generated payload is unchanged, the script is not replaced.\n * - SSR-safe: no-op when window/document is undefined.\n * - Cleans up on unmount (removes the script).\n *\n * @param config - Route (required), mode, and optional metadata fields. Can be partial; defaults applied.\n */\nexport function useLLMMetadata(config: LLMConfig | null | undefined): void {\n  const prevPayloadRef = useRef<string | null>(null);\n\n  useEffect(() => {\n    try {\n      if (typeof window === \"undefined\") return;\n\n      const normalized = normalizeConfig(config);\n      const payload = buildPayload(normalized);\n      const payloadStr = JSON.stringify(payload);\n\n      if (prevPayloadRef.current === payloadStr) return;\n      prevPayloadRef.current = payloadStr;\n\n      removeExistingScript();\n      injectScript(payload);\n\n      return () => {\n        removeExistingScript();\n        prevPayloadRef.current = null;\n      };\n    } catch {\n      // no-op: never throw from effect\n    }\n  }, [\n    config?.route,\n    config?.mode,\n    config?.title,\n    config?.description,\n    config?.tags,\n    config?.canonicalUrl,\n    config?.language,\n    config?.ogType,\n    config?.ogImage,\n    config?.ogImageAlt,\n    config?.siteName,\n    config?.author,\n    config?.publishedTime,\n    config?.modifiedTime,\n    config?.robots,\n    // extra is read inside effect; change route/title/etc. to force update when only extra changed\n  ]);\n}\n","import type { RefObject } from \"preact\";\nimport { useCallback, useRef } from \"preact/hooks\";\n\nconst PRINT_CLASS = \"use-ref-print-target\";\nconst PRINT_STYLE_ID = \"use-ref-print-styles\";\n\nconst PRINT_CSS = `\n@media print {\n  body * {\n    visibility: hidden;\n  }\n  .${PRINT_CLASS},\n  .${PRINT_CLASS} * {\n    visibility: visible;\n  }\n  .${PRINT_CLASS} {\n    position: absolute !important;\n    left: 0 !important;\n    top: 0 !important;\n    width: 100% !important;\n  }\n}\n`;\n\nexport interface UseRefPrintOptions {\n  /**\n   * When true, the print flow is triggered so the user can choose\n   * \"Save as PDF\" in the native print dialog. Uses the same window.print() path.\n   */\n  downloadAsPdf?: boolean;\n  /** Title for the print document (e.g. used when saving as PDF). */\n  documentTitle?: string;\n}\n\nexport interface UseRefPrintReturn {\n  /** Triggers native print for the section bound to the ref (opens print dialog; only that section is printed via @media print). */\n  print: () => void;\n}\n\n/**\n * A Preact hook that binds a ref to a printable section and provides a function\n * to print only that section using the native window.print() and @media print CSS.\n * When print() is called (or user presses Ctrl+P after focusing that section), only\n * the ref section is visible in the print layout. User can then print or save as PDF.\n *\n * @param printRef - Ref to the DOM element (e.g. a div) that should be printed.\n * @param options - Optional: downloadAsPdf hint, documentTitle for the print document.\n * @returns Object with a print() function.\n *\n * @example\n * ```tsx\n * function Report() {\n *   const printRef = useRef<HTMLDivElement>(null);\n *   const { print } = useRefPrint(printRef, { documentTitle: 'Report', downloadAsPdf: true });\n *   return (\n *     <div>\n *       <div ref={printRef}>Content to print or save as PDF</div>\n *       <button onClick={print}>Print / Save as PDF</button>\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useRefPrint(\n  printRef: RefObject<HTMLElement | null>,\n  options: UseRefPrintOptions = {}\n): UseRefPrintReturn {\n  const { documentTitle } = options;\n  const originalTitleRef = useRef<string>(\"\");\n\n  const print = useCallback(() => {\n    const el = printRef.current;\n    if (!el || typeof window === \"undefined\" || !window.print) {\n      return;\n    }\n\n    // Ensure print-only styles exist (once per document)\n    let styleEl = document.getElementById(\n      PRINT_STYLE_ID\n    ) as HTMLStyleElement | null;\n    if (!styleEl) {\n      styleEl = document.createElement(\"style\");\n      styleEl.id = PRINT_STYLE_ID;\n      styleEl.textContent = PRINT_CSS;\n      document.head.appendChild(styleEl);\n    }\n\n    el.classList.add(PRINT_CLASS);\n    if (documentTitle) {\n      originalTitleRef.current = document.title;\n      document.title = documentTitle;\n    }\n\n    const cleanup = () => {\n      el.classList.remove(PRINT_CLASS);\n      if (documentTitle && originalTitleRef.current !== undefined) {\n        document.title = originalTitleRef.current;\n      }\n    };\n\n    if (\"onafterprint\" in window) {\n      const onAfterPrint = () => {\n        cleanup();\n        window.removeEventListener(\"afterprint\", onAfterPrint);\n      };\n      window.addEventListener(\"afterprint\", onAfterPrint);\n    }\n\n    window.print();\n\n    // Fallback cleanup if afterprint is not fired (e.g. user cancels)\n    setTimeout(cleanup, 1000);\n  }, [printRef, documentTitle]);\n\n  return { print };\n}\n","import { useCallback, useEffect, useRef, useState } from \"preact/hooks\";\n\n/** Flexible user object; your app can use any shape. */\nexport type RBACUser = Record<string, unknown>;\n\n/** Get auth state (user + optional roles/capabilities). Used by custom source. */\nexport interface RBACAuthState {\n  user?: RBACUser | null;\n  roles?: string[];\n  capabilities?: string[];\n}\n\n/** Pluggable source for current user (and optionally roles/capabilities). */\nexport type RBACUserSource =\n  | { type: \"localStorage\"; key: string }\n  | { type: \"sessionStorage\"; key: string }\n  | { type: \"api\"; fetch: () => Promise<RBACUser> }\n  | { type: \"memory\"; getUser: () => RBACUser | null }\n  | { type: \"custom\"; getAuth: () => RBACAuthState | Promise<RBACAuthState> };\n\n/** Role definition: name + condition to grant this role based on user. */\nexport interface RBACRoleDefinition {\n  role: string;\n  condition: (user: RBACUser | null) => boolean;\n}\n\n/** Role name -> list of capability strings. Use '*' for full access. */\nexport type RBACRoleCapabilities = Record<string, string[]>;\n\n/** Optional override: get capabilities directly (e.g. from API) instead of deriving from roles. */\nexport type RBACCapabilitiesOverride =\n  | { type: \"localStorage\"; key: string }\n  | { type: \"sessionStorage\"; key: string }\n  | { type: \"api\"; fetch: () => Promise<string[]> };\n\nexport interface UseRBACOptions {\n  /** Where to get the current user (and optionally roles/capabilities if type is 'custom'). */\n  userSource: RBACUserSource;\n  /** Role definitions: each role has a condition(user) to determine if the user has that role. */\n  roleDefinitions: RBACRoleDefinition[];\n  /** Capabilities per role. User gets union of capabilities for all their roles. Use '*' for admin. */\n  roleCapabilities: RBACRoleCapabilities;\n  /** Optional: fetch capabilities directly (overrides role-derived capabilities when provided). */\n  capabilitiesOverride?: RBACCapabilitiesOverride;\n}\n\nexport interface UseRBACReturn {\n  /** Current user from source, or null. */\n  user: RBACUser | null;\n  /** Resolved roles for the current user. */\n  roles: string[];\n  /** Resolved capabilities (union of role capabilities, or from override). */\n  capabilities: string[];\n  /** True when user/roles/capabilities have been resolved (or failed). */\n  isReady: boolean;\n  /** Error from source (e.g. API or parse). */\n  error: Error | null;\n  /** Check if the user has the given role. */\n  hasRole: (role: string) => boolean;\n  /** Check if the user has the given capability (or '*' ). */\n  hasCapability: (capability: string) => boolean;\n  /** Alias for hasCapability. */\n  can: (capability: string) => boolean;\n  /** Re-fetch user/roles/capabilities from source. */\n  refetch: () => Promise<void>;\n  /** Helpers to persist auth to storage (for frontend-only flows). */\n  setUserInStorage: (\n    user: RBACUser | null,\n    storage: \"localStorage\" | \"sessionStorage\",\n    key: string\n  ) => void;\n  setRolesInStorage: (\n    roles: string[],\n    storage: \"localStorage\" | \"sessionStorage\",\n    key: string\n  ) => void;\n  setCapabilitiesInStorage: (\n    capabilities: string[],\n    storage: \"localStorage\" | \"sessionStorage\",\n    key: string\n  ) => void;\n}\n\nconst WILDCARD = \"*\";\n\nfunction parseUserFromStorage(\n  type: \"localStorage\" | \"sessionStorage\",\n  key: string\n): RBACUser | null {\n  if (typeof window === \"undefined\") return null;\n  const storage =\n    type === \"localStorage\" ? window.localStorage : window.sessionStorage;\n  try {\n    const raw = storage.getItem(key);\n    if (raw == null) return null;\n    const data = JSON.parse(raw) as unknown;\n    return data && typeof data === \"object\" ? (data as RBACUser) : null;\n  } catch {\n    return null;\n  }\n}\n\nfunction parseCapabilitiesFromStorage(\n  type: \"localStorage\" | \"sessionStorage\",\n  key: string\n): string[] {\n  if (typeof window === \"undefined\") return [];\n  const storage =\n    type === \"localStorage\" ? window.localStorage : window.sessionStorage;\n  try {\n    const raw = storage.getItem(key);\n    if (raw == null) return [];\n    const data = JSON.parse(raw) as unknown;\n    return Array.isArray(data)\n      ? data.filter((x): x is string => typeof x === \"string\")\n      : [];\n  } catch {\n    return [];\n  }\n}\n\nfunction computeRoles(\n  user: RBACUser | null,\n  roleDefinitions: RBACRoleDefinition[]\n): string[] {\n  return roleDefinitions\n    .filter((def) => def.condition(user))\n    .map((def) => def.role);\n}\n\nfunction computeCapabilitiesFromRoles(\n  roles: string[],\n  roleCapabilities: RBACRoleCapabilities\n): string[] {\n  const set = new Set<string>();\n  for (const role of roles) {\n    const caps = roleCapabilities[role];\n    if (Array.isArray(caps)) {\n      for (const c of caps) set.add(c);\n    }\n  }\n  return Array.from(set);\n}\n\nfunction hasCapabilityImpl(\n  capabilities: string[],\n  capability: string\n): boolean {\n  if (capabilities.includes(WILDCARD)) return true;\n  return capabilities.includes(capability);\n}\n\n/**\n * Frontend-only role-based access control hook. Define roles with conditions,\n * assign capabilities per role, and plug in user source (localStorage, sessionStorage, API, or custom).\n * Supports full flexibility: frontend-only with storage or pluggable API.\n *\n * @param options - userSource, roleDefinitions, roleCapabilities, optional capabilitiesOverride\n * @returns user, roles, capabilities, hasRole, hasCapability, can, isReady, error, refetch, and storage helpers\n *\n * @example\n * ```tsx\n * const { hasRole, can, roles, setUserInStorage } = useRBAC({\n *   userSource: { type: 'localStorage', key: 'user' },\n *   roleDefinitions: [\n *     { role: 'admin', condition: (u) => u?.role === 'admin' },\n *     { role: 'editor', condition: (u) => u?.role === 'editor' || u?.role === 'admin' },\n *   ],\n *   roleCapabilities: {\n *     admin: ['*'],\n *     editor: ['posts:edit', 'posts:create'],\n *   },\n * });\n * if (can('posts:edit')) { ... }\n * ```\n */\nexport function useRBAC(options: UseRBACOptions): UseRBACReturn {\n  const { userSource } = options;\n\n  const optsRef = useRef(options);\n  optsRef.current = options;\n\n  const [user, setUser] = useState<RBACUser | null>(null);\n  const [roles, setRoles] = useState<string[]>([]);\n  const [capabilities, setCapabilities] = useState<string[]>([]);\n  const [isReady, setIsReady] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n\n  const resolveAuth = useCallback(async () => {\n    const {\n      userSource: us,\n      roleDefinitions: rdefs,\n      roleCapabilities: rcaps,\n      capabilitiesOverride: capOver,\n    } = optsRef.current;\n    setError(null);\n    let resolvedUser: RBACUser | null = null;\n    let resolvedRoles: string[] = [];\n    let resolvedCapabilities: string[] = [];\n\n    try {\n      if (us.type === \"localStorage\") {\n        resolvedUser = parseUserFromStorage(\"localStorage\", us.key);\n        resolvedRoles = computeRoles(resolvedUser, rdefs);\n        resolvedCapabilities = computeCapabilitiesFromRoles(\n          resolvedRoles,\n          rcaps\n        );\n      } else if (us.type === \"sessionStorage\") {\n        resolvedUser = parseUserFromStorage(\"sessionStorage\", us.key);\n        resolvedRoles = computeRoles(resolvedUser, rdefs);\n        resolvedCapabilities = computeCapabilitiesFromRoles(\n          resolvedRoles,\n          rcaps\n        );\n      } else if (us.type === \"api\") {\n        resolvedUser = await us.fetch();\n        resolvedRoles = computeRoles(resolvedUser, rdefs);\n        resolvedCapabilities = computeCapabilitiesFromRoles(\n          resolvedRoles,\n          rcaps\n        );\n      } else if (us.type === \"memory\") {\n        resolvedUser = us.getUser();\n        resolvedRoles = computeRoles(resolvedUser, rdefs);\n        resolvedCapabilities = computeCapabilitiesFromRoles(\n          resolvedRoles,\n          rcaps\n        );\n      } else if (us.type === \"custom\") {\n        const auth = await Promise.resolve(us.getAuth());\n        resolvedUser = auth.user ?? null;\n        resolvedRoles = auth.roles ?? computeRoles(resolvedUser, rdefs);\n        resolvedCapabilities =\n          auth.capabilities ??\n          computeCapabilitiesFromRoles(resolvedRoles, rcaps);\n      }\n\n      if (capOver) {\n        if (capOver.type === \"localStorage\") {\n          const override = parseCapabilitiesFromStorage(\n            \"localStorage\",\n            capOver.key\n          );\n          if (override.length > 0) resolvedCapabilities = override;\n        } else if (capOver.type === \"sessionStorage\") {\n          const override = parseCapabilitiesFromStorage(\n            \"sessionStorage\",\n            capOver.key\n          );\n          if (override.length > 0) resolvedCapabilities = override;\n        } else if (capOver.type === \"api\") {\n          const override = await capOver.fetch();\n          resolvedCapabilities = override;\n        }\n      }\n\n      setUser(resolvedUser);\n      setRoles(resolvedRoles);\n      setCapabilities(resolvedCapabilities);\n    } catch (e) {\n      setError(e instanceof Error ? e : new Error(String(e)));\n      setUser(null);\n      setRoles([]);\n      setCapabilities([]);\n    } finally {\n      setIsReady(true);\n    }\n  }, []);\n\n  useEffect(() => {\n    resolveAuth();\n  }, [resolveAuth]);\n\n  // Listen to storage events when using localStorage/sessionStorage so we refetch when another tab changes data\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n    const key =\n      userSource.type === \"localStorage\" || userSource.type === \"sessionStorage\"\n        ? userSource.key\n        : null;\n    if (!key) return;\n    const handler = (e: StorageEvent) => {\n      if (e.key === key) void resolveAuth();\n    };\n    window.addEventListener(\"storage\", handler);\n    return () => window.removeEventListener(\"storage\", handler);\n  }, [\n    userSource.type,\n    userSource.type === \"localStorage\" || userSource.type === \"sessionStorage\"\n      ? (userSource as { key: string }).key\n      : \"\",\n    resolveAuth,\n  ]);\n\n  const hasRole = useCallback((role: string) => roles.includes(role), [roles]);\n\n  const hasCapability = useCallback(\n    (capability: string) => hasCapabilityImpl(capabilities, capability),\n    [capabilities]\n  );\n\n  const can = hasCapability;\n\n  const refetch = useCallback(() => resolveAuth(), [resolveAuth]);\n\n  const setUserInStorage = useCallback(\n    (\n      newUser: RBACUser | null,\n      storage: \"localStorage\" | \"sessionStorage\",\n      key: string\n    ) => {\n      if (typeof window === \"undefined\") return;\n      const s =\n        storage === \"localStorage\"\n          ? window.localStorage\n          : window.sessionStorage;\n      if (newUser == null) s.removeItem(key);\n      else s.setItem(key, JSON.stringify(newUser));\n      if (\n        (userSource.type === \"localStorage\" &&\n          storage === \"localStorage\" &&\n          userSource.key === key) ||\n        (userSource.type === \"sessionStorage\" &&\n          storage === \"sessionStorage\" &&\n          userSource.key === key)\n      ) {\n        void resolveAuth();\n      }\n    },\n    [userSource, resolveAuth]\n  );\n\n  const setRolesInStorage = useCallback(\n    (\n      newRoles: string[],\n      storage: \"localStorage\" | \"sessionStorage\",\n      key: string\n    ) => {\n      if (typeof window === \"undefined\") return;\n      const s =\n        storage === \"localStorage\"\n          ? window.localStorage\n          : window.sessionStorage;\n      s.setItem(key, JSON.stringify(newRoles));\n    },\n    []\n  );\n\n  const setCapabilitiesInStorage = useCallback(\n    (\n      newCaps: string[],\n      storage: \"localStorage\" | \"sessionStorage\",\n      key: string\n    ) => {\n      if (typeof window === \"undefined\") return;\n      const s =\n        storage === \"localStorage\"\n          ? window.localStorage\n          : window.sessionStorage;\n      s.setItem(key, JSON.stringify(newCaps));\n    },\n    []\n  );\n\n  return {\n    user,\n    roles,\n    capabilities,\n    isReady,\n    error,\n    hasRole,\n    hasCapability,\n    can,\n    refetch,\n    setUserInStorage,\n    setRolesInStorage,\n    setCapabilitiesInStorage,\n  };\n}\n","import { useCallback, useRef, useState } from \"preact/hooks\";\n\nexport interface UsePrefetchOptions {\n  /**\n   * Resource type for prefetch.\n   * - \"document\": uses <link rel=\"prefetch\"> (default, for next navigation)\n   * - \"fetch\": uses fetch() to warm the HTTP cache (e.g. for API or same-origin data)\n   */\n  as?: \"document\" | \"fetch\";\n}\n\nexport interface UsePrefetchReturn {\n  /** Prefetch a URL so it is cached for later use. No-op if URL was already prefetched or empty. */\n  prefetch: (url: string, options?: UsePrefetchOptions) => void;\n  /** Check whether a URL has already been prefetched in this hook instance. */\n  isPrefetched: (url: string) => boolean;\n}\n\nfunction prefetchDocument(url: string): void {\n  if (typeof document === \"undefined\") return;\n  const links = document.querySelectorAll('link[rel=\"prefetch\"]');\n  for (let i = 0; i < links.length; i++) {\n    if ((links[i] as HTMLLinkElement).href === url) return;\n  }\n\n  const link = document.createElement(\"link\");\n  link.rel = \"prefetch\";\n  link.href = url;\n  document.head.appendChild(link);\n}\n\nfunction prefetchFetch(url: string): void {\n  if (typeof fetch === \"undefined\") return;\n  fetch(url, { method: \"GET\", mode: \"cors\" }).catch(() => {\n    /* ignore; prefetch is best-effort */\n  });\n}\n\n/**\n * A Preact hook that returns a stable prefetch function to preload URLs (documents or data)\n * so they are cached before the user navigates or needs them. Useful for link hover or\n * route preloading.\n *\n * @returns Object with prefetch(url, options?) and isPrefetched(url)\n *\n * @example\n * ```tsx\n * function NavLink({ href, children }) {\n *   const { prefetch } = usePrefetch();\n *   return (\n *     <a\n *       href={href}\n *       onMouseEnter={() => prefetch(href)}\n *     >\n *       {children}\n *     </a>\n *   );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Prefetch API data\n * const { prefetch } = usePrefetch();\n * prefetch('/api/user', { as: 'fetch' });\n * ```\n */\nexport function usePrefetch(): UsePrefetchReturn {\n  const prefetchedRef = useRef<Set<string>>(new Set());\n  const [, setTick] = useState(0);\n\n  const prefetch = useCallback((url: string, options?: UsePrefetchOptions) => {\n    const trimmed = url?.trim();\n    if (!trimmed) return;\n    if (prefetchedRef.current.has(trimmed)) return;\n\n    const as = options?.as ?? \"document\";\n    if (as === \"document\") {\n      prefetchDocument(trimmed);\n    } else {\n      prefetchFetch(trimmed);\n    }\n    prefetchedRef.current.add(trimmed);\n    setTick((n) => n + 1);\n  }, []);\n\n  const isPrefetched = useCallback((url: string) => {\n    return prefetchedRef.current.has(url?.trim() ?? \"\");\n  }, []);\n\n  return { prefetch, isPrefetched };\n}\n","import { useCallback, useEffect, useRef, useState } from \"preact/hooks\";\n\nexport interface UsePollOptions {\n  /** Polling interval in milliseconds. Default: 1000 */\n  intervalMs?: number;\n  /** Run the poll function immediately when the hook mounts. Default: true */\n  immediate?: boolean;\n  /** When false, do not start or continue polling. Default: true */\n  enabled?: boolean;\n}\n\nexport interface UsePollResult<T> {\n  /** Last resolved data when poll returned done: true */\n  data: T | null;\n  /** True once the poll function returned { done: true } */\n  done: boolean;\n  /** Error from the last failed poll call */\n  error: Error | null;\n  /** Number of times the poll function has been invoked */\n  pollCount: number;\n  /** Manually start polling (e.g. after reset). Only has effect when not already polling. */\n  start: () => void;\n  /** Stop polling. */\n  stop: () => void;\n}\n\n/**\n * Polls an async function at a fixed interval until it returns { done: true, data? }.\n * Useful for waiting on a backend job, readiness checks, or until a condition is met.\n *\n * @param pollFn - Async function called each tick. Return { done: true, data? } to stop and set result.\n * @param options - intervalMs, immediate, enabled\n * @returns { data, done, error, pollCount, start, stop }\n *\n * @example\n * ```tsx\n * const { data, done, pollCount } = usePoll(\n *   async () => {\n *     const res = await fetch('/api/status');\n *     const json = await res.json();\n *     return json.ready ? { done: true, data: json } : { done: false };\n *   },\n *   { intervalMs: 500, immediate: true }\n * );\n * return done ? <div>Ready: {JSON.stringify(data)}</div> : <div>Polling… ({pollCount})</div>;\n * ```\n */\nexport function usePoll<T>(\n  pollFn: () => Promise<{ done: boolean; data?: T }>,\n  options: UsePollOptions = {}\n): UsePollResult<T> {\n  const { intervalMs = 1000, immediate = true, enabled = true } = options;\n\n  const [data, setData] = useState<T | null>(null);\n  const [done, setDone] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n  const [pollCount, setPollCount] = useState(0);\n  const [running, setRunning] = useState(false);\n\n  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n  const pollFnRef = useRef(pollFn);\n  pollFnRef.current = pollFn;\n\n  const stop = useCallback(() => {\n    if (intervalRef.current != null) {\n      clearInterval(intervalRef.current);\n      intervalRef.current = null;\n    }\n    setRunning(false);\n  }, []);\n\n  const tick = useCallback(async () => {\n    try {\n      setError(null);\n      const result = await pollFnRef.current();\n      setPollCount((n) => n + 1);\n      if (result.done) {\n        stop();\n        setDone(true);\n        if (result.data !== undefined) {\n          setData(result.data);\n        }\n      }\n    } catch (e) {\n      const err = e instanceof Error ? e : new Error(String(e));\n      setError(err);\n      stop();\n    }\n  }, [stop]);\n\n  const start = useCallback(() => {\n    if (!enabled || running) return;\n    setRunning(true);\n    if (immediate) {\n      tick();\n    }\n    intervalRef.current = setInterval(tick, intervalMs);\n  }, [enabled, immediate, intervalMs, running, tick]);\n\n  useEffect(() => {\n    if (enabled) {\n      start();\n    }\n    return () => {\n      stop();\n    };\n  }, [enabled]);\n\n  return { data, done, error, pollCount, start, stop };\n}\n","import { useCallback, useEffect, useState } from \"preact/hooks\";\n\n/** Parsed Client Hints from `navigator.userAgentData` when available */\nexport interface UserAgentDataInfo {\n  mobile: boolean;\n  platform: string;\n  brands: ReadonlyArray<{ brand: string; version: string }>;\n}\n\n/** Screen and display metrics from `screen` and `window` */\nexport interface DeviceScreenInfo {\n  width: number;\n  height: number;\n  availWidth: number;\n  availHeight: number;\n  colorDepth: number;\n  pixelRatio: number;\n}\n\n/** Viewport size (`window.innerWidth` / `innerHeight`) */\nexport interface DeviceViewportInfo {\n  width: number;\n  height: number;\n}\n\n/** Battery status from the Battery Status API when available */\nexport interface DeviceBatteryInfo {\n  charging: boolean;\n  level: number;\n}\n\n/** Detected browser name and version */\nexport interface DeviceBrowserInfo {\n  name: string;\n  version: string;\n}\n\n/** Detected operating system name and version */\nexport interface DeviceOsInfo {\n  name: string;\n  version: string;\n}\n\n/** Snapshot of device / browser data from native Navigator and related APIs */\nexport interface DeviceData {\n  userAgent: string;\n  language: string;\n  languages: readonly string[];\n  platform: string;\n  /** Detected browser (from Client Hints or user-agent parsing) */\n  browser: DeviceBrowserInfo;\n  /** Detected OS (from Client Hints or user-agent parsing) */\n  os: DeviceOsInfo;\n  cookieEnabled: boolean;\n  online: boolean;\n  hardwareConcurrency?: number;\n  /** Approximate device RAM in GB (Chrome / some browsers only) */\n  deviceMemory?: number;\n  maxTouchPoints: number;\n  vendor: string;\n  touch: boolean;\n  screen: DeviceScreenInfo;\n  viewport: DeviceViewportInfo;\n  userAgentData?: UserAgentDataInfo;\n  reducedMotion: boolean;\n  colorScheme: \"light\" | \"dark\" | \"no-preference\";\n  battery?: DeviceBatteryInfo;\n}\n\nexport interface UseDeviceDataOptions {\n  /** Fetch battery info when the Battery Status API exists (default: true) */\n  includeBattery?: boolean;\n  /** Battery refresh interval in ms (default: 60000) */\n  batteryPollIntervalMs?: number;\n  /**\n   * Request high-entropy Client Hints (`platformVersion`, `fullVersionList`)\n   * when `navigator.userAgentData` supports it (default: true)\n   */\n  includeHighEntropy?: boolean;\n}\n\ninterface NavigatorUAData {\n  mobile?: boolean;\n  platform?: string;\n  brands?: Array<{ brand: string; version: string }>;\n  getHighEntropyValues?: (hints: string[]) => Promise<{\n    platformVersion?: string;\n    fullVersionList?: Array<{ brand: string; version: string }>;\n  }>;\n}\n\ntype NavigatorWithExtras = Navigator & {\n  deviceMemory?: number;\n  userAgentData?: NavigatorUAData;\n};\n\nconst UNKNOWN_BROWSER: DeviceBrowserInfo = { name: \"Unknown\", version: \"\" };\nconst UNKNOWN_OS: DeviceOsInfo = { name: \"Unknown\", version: \"\" };\n\nconst SSR_DEVICE_DATA: DeviceData = {\n  userAgent: \"\",\n  language: \"en\",\n  languages: [\"en\"],\n  platform: \"\",\n  browser: UNKNOWN_BROWSER,\n  os: UNKNOWN_OS,\n  cookieEnabled: false,\n  online: true,\n  maxTouchPoints: 0,\n  vendor: \"\",\n  touch: false,\n  screen: {\n    width: 0,\n    height: 0,\n    availWidth: 0,\n    availHeight: 0,\n    colorDepth: 24,\n    pixelRatio: 1,\n  },\n  viewport: { width: 0, height: 0 },\n  reducedMotion: false,\n  colorScheme: \"no-preference\",\n};\n\nconst NOT_A_BRAND = /not.?a.?brand/i;\n\n/** Parse browser and OS from a user-agent string (sync fallback). */\nexport function parseUserAgent(userAgent: string): {\n  browser: DeviceBrowserInfo;\n  os: DeviceOsInfo;\n} {\n  const browser: DeviceBrowserInfo = { ...UNKNOWN_BROWSER };\n  const os: DeviceOsInfo = { ...UNKNOWN_OS };\n\n  if (!userAgent) {\n    return { browser, os };\n  }\n\n  const win = userAgent.match(/Windows NT ([\\d.]+)/);\n  if (win) {\n    os.name = \"Windows\";\n    os.version = win[1];\n  } else {\n    const mac = userAgent.match(/Mac OS X ([\\d._]+)/);\n    if (mac) {\n      os.name = \"macOS\";\n      os.version = mac[1].replace(/_/g, \".\");\n    } else {\n      const android = userAgent.match(/Android ([\\d.]+)/);\n      if (android) {\n        os.name = \"Android\";\n        os.version = android[1];\n      } else {\n        const ios = userAgent.match(/(?:iPhone OS|CPU OS) ([\\d_]+)/);\n        if (ios) {\n          os.name = \"iOS\";\n          os.version = ios[1].replace(/_/g, \".\");\n        } else if (/Linux/.test(userAgent)) {\n          os.name = \"Linux\";\n          const linux = userAgent.match(/Linux ([\\d.]+)/);\n          os.version = linux?.[1] ?? \"\";\n        }\n      }\n    }\n  }\n\n  const edg = userAgent.match(/Edg(?:A|iOS)?\\/([\\d.]+)/);\n  const opera = userAgent.match(/OPR\\/([\\d.]+)/);\n  const firefox = userAgent.match(/Firefox\\/([\\d.]+)/);\n  const safari =\n    /Version\\/([\\d.]+)/.test(userAgent) &&\n    /Safari/.test(userAgent) &&\n    !/Chrome|Chromium|Edg|OPR/.test(userAgent)\n      ? userAgent.match(/Version\\/([\\d.]+)/)\n      : null;\n  const chrome = userAgent.match(/Chrome\\/([\\d.]+)/);\n\n  if (edg) {\n    browser.name = \"Edge\";\n    browser.version = edg[1];\n  } else if (opera) {\n    browser.name = \"Opera\";\n    browser.version = opera[1];\n  } else if (firefox) {\n    browser.name = \"Firefox\";\n    browser.version = firefox[1];\n  } else if (safari) {\n    browser.name = \"Safari\";\n    browser.version = safari[1];\n  } else if (chrome) {\n    browser.name = \"Chrome\";\n    browser.version = chrome[1];\n  }\n\n  return { browser, os };\n}\n\nfunction pickBrowserBrand(\n  brands: Array<{ brand: string; version: string }>\n): DeviceBrowserInfo {\n  const meaningful = brands.find((b) => !NOT_A_BRAND.test(b.brand));\n  const pick = meaningful ?? brands[0];\n  if (!pick) return { ...UNKNOWN_BROWSER };\n  return { name: pick.brand, version: pick.version };\n}\n\nfunction mergeBrowserOsFromUaData(\n  uaData: NavigatorUAData,\n  fallback: { browser: DeviceBrowserInfo; os: DeviceOsInfo }\n): { browser: DeviceBrowserInfo; os: DeviceOsInfo } {\n  const browser = uaData.brands?.length\n    ? pickBrowserBrand(uaData.brands)\n    : { ...fallback.browser };\n  const os: DeviceOsInfo = {\n    name: uaData.platform?.trim() || fallback.os.name,\n    version: fallback.os.version,\n  };\n  return { browser, os };\n}\n\nfunction getColorScheme(): DeviceData[\"colorScheme\"] {\n  if (typeof window === \"undefined\" || !window.matchMedia) {\n    return \"no-preference\";\n  }\n  if (window.matchMedia(\"(prefers-color-scheme: dark)\").matches) {\n    return \"dark\";\n  }\n  if (window.matchMedia(\"(prefers-color-scheme: light)\").matches) {\n    return \"light\";\n  }\n  return \"no-preference\";\n}\n\nfunction getReducedMotion(): boolean {\n  if (typeof window === \"undefined\" || !window.matchMedia) {\n    return false;\n  }\n  return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** Reads synchronous device / browser data from Navigator, Screen, and matchMedia. */\nexport function getDeviceData(): DeviceData {\n  if (typeof navigator === \"undefined\") {\n    return SSR_DEVICE_DATA;\n  }\n\n  const nav = navigator as NavigatorWithExtras;\n  const screen =\n    typeof globalThis.screen !== \"undefined\" ? globalThis.screen : null;\n  const win =\n    typeof globalThis.window !== \"undefined\" ? globalThis.window : null;\n\n  const ua = nav.userAgent ?? \"\";\n  const parsed = parseUserAgent(ua);\n  const uaData = nav.userAgentData;\n  const { browser, os } = uaData\n    ? mergeBrowserOsFromUaData(uaData, parsed)\n    : parsed;\n\n  const data: DeviceData = {\n    userAgent: ua,\n    language: nav.language ?? \"\",\n    languages: nav.languages ? [...nav.languages] : [],\n    platform: nav.platform ?? \"\",\n    browser,\n    os,\n    cookieEnabled: Boolean(nav.cookieEnabled),\n    online: Boolean(nav.onLine),\n    maxTouchPoints: nav.maxTouchPoints ?? 0,\n    vendor: nav.vendor ?? \"\",\n    touch: (nav.maxTouchPoints ?? 0) > 0,\n    screen: {\n      width: screen?.width ?? 0,\n      height: screen?.height ?? 0,\n      availWidth: screen?.availWidth ?? 0,\n      availHeight: screen?.availHeight ?? 0,\n      colorDepth: screen?.colorDepth ?? 24,\n      pixelRatio: win?.devicePixelRatio ?? 1,\n    },\n    viewport: {\n      width: win?.innerWidth ?? 0,\n      height: win?.innerHeight ?? 0,\n    },\n    reducedMotion: getReducedMotion(),\n    colorScheme: getColorScheme(),\n  };\n\n  if (typeof nav.hardwareConcurrency === \"number\") {\n    data.hardwareConcurrency = nav.hardwareConcurrency;\n  }\n  if (typeof nav.deviceMemory === \"number\") {\n    data.deviceMemory = nav.deviceMemory;\n  }\n\n  if (uaData) {\n    data.userAgentData = {\n      mobile: Boolean(uaData.mobile),\n      platform: uaData.platform ?? \"\",\n      brands: uaData.brands ? [...uaData.brands] : [],\n    };\n  }\n\n  return data;\n}\n\nasync function readHighEntropyBrowserOs(\n  uaData: NavigatorUAData,\n  current: { browser: DeviceBrowserInfo; os: DeviceOsInfo }\n): Promise<{ browser: DeviceBrowserInfo; os: DeviceOsInfo } | undefined> {\n  if (!uaData.getHighEntropyValues) return undefined;\n  try {\n    const hints = await uaData.getHighEntropyValues([\n      \"platformVersion\",\n      \"fullVersionList\",\n    ]);\n    const browser = hints.fullVersionList?.length\n      ? pickBrowserBrand(hints.fullVersionList)\n      : { ...current.browser };\n    const os: DeviceOsInfo = {\n      name: current.os.name,\n      version: hints.platformVersion?.trim() || current.os.version,\n    };\n    return { browser, os };\n  } catch {\n    return undefined;\n  }\n}\n\nasync function readBattery(): Promise<DeviceBatteryInfo | undefined> {\n  if (typeof navigator === \"undefined\") return undefined;\n  const getBattery = (\n    navigator as Navigator & {\n      getBattery?: () => Promise<{\n        charging: boolean;\n        level: number;\n      }>;\n    }\n  ).getBattery;\n  if (!getBattery) return undefined;\n  try {\n    const battery = await getBattery.call(navigator);\n    return { charging: battery.charging, level: battery.level };\n  } catch {\n    return undefined;\n  }\n}\n\n/**\n * Extracts device and browser data from native Navigator, Screen, window, and\n * matchMedia APIs. Updates on resize, orientation, online/offline, and\n * prefers-color-scheme / prefers-reduced-motion changes. Optionally polls the\n * Battery Status API when available.\n *\n * @param options - `includeBattery` (default true), `batteryPollIntervalMs` (default 60000)\n * @returns Current {@link DeviceData} snapshot\n *\n * @example\n * ```tsx\n * function DevicePanel() {\n *   const device = useDeviceData();\n *   return (\n *     <dl>\n *       <dt>Browser</dt><dd>{device.browser.name} {device.browser.version}</dd>\n *       <dt>OS</dt><dd>{device.os.name} {device.os.version}</dd>\n *       <dt>Language</dt><dd>{device.language}</dd>\n *       <dt>Viewport</dt><dd>{device.viewport.width}×{device.viewport.height}</dd>\n *     </dl>\n *   );\n * }\n * ```\n */\nexport function useDeviceData(options: UseDeviceDataOptions = {}): DeviceData {\n  const {\n    includeBattery = true,\n    batteryPollIntervalMs = 60_000,\n    includeHighEntropy = true,\n  } = options;\n\n  const [data, setData] = useState<DeviceData>(() => getDeviceData());\n\n  const refresh = useCallback(() => {\n    setData((prev) => {\n      const next = getDeviceData();\n      return {\n        ...next,\n        ...(prev.battery ? { battery: prev.battery } : {}),\n      };\n    });\n  }, []);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n\n    const onResize = () => refresh();\n    window.addEventListener(\"resize\", onResize);\n    window.addEventListener(\"orientationchange\", onResize);\n    window.addEventListener(\"online\", refresh);\n    window.addEventListener(\"offline\", refresh);\n\n    const reducedMotionMq = window.matchMedia?.(\n      \"(prefers-reduced-motion: reduce)\"\n    );\n    const darkMq = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n    const lightMq = window.matchMedia?.(\"(prefers-color-scheme: light)\");\n\n    const onMediaChange = () => refresh();\n    reducedMotionMq?.addEventListener?.(\"change\", onMediaChange);\n    darkMq?.addEventListener?.(\"change\", onMediaChange);\n    lightMq?.addEventListener?.(\"change\", onMediaChange);\n\n    return () => {\n      window.removeEventListener(\"resize\", onResize);\n      window.removeEventListener(\"orientationchange\", onResize);\n      window.removeEventListener(\"online\", refresh);\n      window.removeEventListener(\"offline\", refresh);\n      reducedMotionMq?.removeEventListener?.(\"change\", onMediaChange);\n      darkMq?.removeEventListener?.(\"change\", onMediaChange);\n      lightMq?.removeEventListener?.(\"change\", onMediaChange);\n    };\n  }, [refresh]);\n\n  useEffect(() => {\n    if (!includeHighEntropy || typeof navigator === \"undefined\") return;\n\n    const uaData = (navigator as NavigatorWithExtras).userAgentData;\n    if (!uaData?.getHighEntropyValues) return;\n\n    let cancelled = false;\n\n    const updateHighEntropy = async () => {\n      const base = getDeviceData();\n      const enriched = await readHighEntropyBrowserOs(uaData, {\n        browser: base.browser,\n        os: base.os,\n      });\n      if (cancelled || !enriched) return;\n      setData((prev) => ({\n        ...prev,\n        browser: enriched.browser,\n        os: enriched.os,\n      }));\n    };\n\n    void updateHighEntropy();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [includeHighEntropy]);\n\n  useEffect(() => {\n    if (!includeBattery || typeof navigator === \"undefined\") return;\n\n    let cancelled = false;\n    let intervalId: ReturnType<typeof setInterval> | undefined;\n\n    const updateBattery = async () => {\n      const battery = await readBattery();\n      if (cancelled || battery === undefined) return;\n      setData((prev) => ({ ...prev, battery }));\n    };\n\n    void updateBattery();\n    if (batteryPollIntervalMs > 0) {\n      intervalId = setInterval(\n        () => void updateBattery(),\n        batteryPollIntervalMs\n      );\n    }\n\n    return () => {\n      cancelled = true;\n      if (intervalId !== undefined) clearInterval(intervalId);\n    };\n  }, [includeBattery, batteryPollIntervalMs]);\n\n  return data;\n}\n"],"names":["useTransition","isPending","setIsPending","useState","useCallback","callback","Promise","resolve","then","useMutationObserver","targetRef","options","useEffect","node","current","observer","MutationObserver","observe","disconnect","listeners","Map","useEventBus","emit","event","args","handlers","get","forEach","handler","on","Set","set","add","delete","size","useWrappedChildren","children","injectProps","mergeStrategy","useMemo","enhanceChild","child","isValidElement","existingProps","props","mergedProps","_extends","existingStyle","style","injectStyle","cloneElement","Array","isArray","map","usePreferredTheme","theme","setTheme","window","darkQuery","matchMedia","lightQuery","matches","mediaQuery","handleChange","e","updateTheme","addEventListener","removeEventListener","getNetworkState","navigator","online","state","onLine","connection","undefined","effectiveType","downlink","rtt","saveData","type","connectionType","useNetworkState","setState","updateState","useClipboard","resetDelay","copied","setCopied","error","setError","reset","copy","async","clipboard","err","Error","writeText","text","setTimeout","String","paste","readText","useRageClick","onRageClick","threshold","timeWindow","distanceThreshold","onRageClickRef","useRef","clicksRef","handleClick","now","Date","record","time","x","clientX","y","clientY","cutoff","recent","filter","c","push","Infinity","inRange","distance","a","b","Math","hypot","length","count","useThreadedWorker","workerFn","mode","concurrency","maxConcurrent","max","loading","setLoading","result","setResult","queueSize","setQueueSize","queueRef","sequenceRef","activeCountRef","terminatedRef","workerFnRef","updateQueueSize","processNext","sort","priority","sequence","task","shift","fn","data","value","catch","reject","finally","run","runOptions","_runOptions$priority","promise","queueMicrotask","clearQueue","pending","t","terminate","connectionCache","requestToPromise","request","onsuccess","onerror","_request$error","DOMException","withCallbacks","onSuccess","onError","useIndexedDB","config","db","setDb","isReady","setIsReady","configRef","cancelled","name","version","tables","key","indexedDB","open","onupgradeneeded","target","tableName","Object","keys","schema","objectStoreNames","contains","_schema$autoIncrement","store","createObjectStore","keyPath","autoIncrement","indexes","indexName","createIndex","unique","_openDB","openDB","database","close","controller","hasTable","table","getStore","transaction","objectStore","insert","update","updates","existing","merged","put","exists","getKey","k","query","filterFn","openCursor","results","cursor","continue","upsert","bulkInsert","items","completed","item","i","req","_req$error","clear","createStandaloneController","createTableController","storeNames","tx","txContext","_request$error2","_req$error2","createTransactionController","createTransactionTableController","txPromise","oncomplete","_tx$error","callbackResult","withTransactionCallbacks","createDBController","IPV4_REGEX","DEFAULT_STUN_SERVERS","DEFAULT_TIMEOUT_MS","useWebRTCIP","stunServers","timeout","timeoutMs","onDetect","ips","setIps","pcRef","timeoutRef","reportedRef","onDetectRef","RTCPeerConnection","reported","finish","clearTimeout","addIP","ip","has","prev","pc","iceServers","urls","onicecandidate","candidate","match","extractIPv4FromCandidate","createDataChannel","createOffer","offer","setLocalDescription","message","join","useWasmCompute","wasmUrl","exportName","workerUrl","importObject","ready","setReady","workerRef","pendingResolveRef","pendingRejectRef","Worker","WebAssembly","instantiate","worker","blob","Blob","url","URL","createObjectURL","w","revokeObjectURL","createWorker","onMessage","_e$data","msgResult","msgError","postMessage","compute","input","useWorkerNotifications","maxHistory","throughputWindowMs","runningTasks","setRunningTasks","completedCount","setCompletedCount","failedCount","setFailedCount","eventHistory","setEventHistory","currentQueueSize","setCurrentQueueSize","completedTimestampsRef","durationSumRef","durationCountRef","ev","taskId","duration","timestamp","parseMessage","slice","includes","id","averageDurationMs","throughputPerSecond","progress","totalProcessed","recentEventCount","safeStr","maxLen","trimmed","trim","safeTagList","out","s","safeUrl","u","protocol","_unused","isVisible","el","getComputedStyle","display","visibility","opacity","_unused2","sanitizeExtra","extra","safeKey","v","Number","isFinite","Boolean","_unused5","removeExistingScript","document","querySelectorAll","remove","_unused7","useLLMMetadata","prevPayloadRef","normalized","route","title","description","tags","canonicalUrl","language","ogType","ogImage","ogImageAlt","siteName","author","publishedTime","modifiedTime","robots","normalizeConfig","payload","generatedAt","toISOString","base","_normalized$title","_normalized$descripti","extracted","empty","outline","ignoreRoots","isInsideIgnored","root","headings","h","textContent","paragraphs","visibleParagraphs","p","_unused3","_unused4","autoExtract","_unused6","_normalized$route","buildPayload","payloadStr","JSON","stringify","head","script","createElement","setAttribute","appendChild","_unused8","injectScript","_unused9","PRINT_CLASS","PRINT_STYLE_ID","PRINT_CSS","useRefPrint","printRef","documentTitle","originalTitleRef","print","styleEl","getElementById","classList","cleanup","onAfterPrint","parseUserFromStorage","storage","localStorage","sessionStorage","raw","getItem","parse","parseCapabilitiesFromStorage","computeRoles","user","roleDefinitions","def","condition","role","computeCapabilitiesFromRoles","roles","roleCapabilities","caps","from","useRBAC","userSource","optsRef","setUser","setRoles","capabilities","setCapabilities","resolveAuth","us","rdefs","rcaps","capabilitiesOverride","capOver","resolvedUser","resolvedRoles","resolvedCapabilities","fetch","getUser","_auth$user","_auth$roles","_auth$capabilities","auth","getAuth","override","hasRole","hasCapability","capability","hasCapabilityImpl","can","refetch","setUserInStorage","newUser","removeItem","setItem","setRolesInStorage","newRoles","setCapabilitiesInStorage","newCaps","usePrefetch","prefetchedRef","setTick","prefetch","_options$as","as","links","href","link","rel","prefetchDocument","method","prefetchFetch","n","isPrefetched","_url$trim","usePoll","pollFn","intervalMs","immediate","enabled","setData","done","setDone","pollCount","setPollCount","running","setRunning","intervalRef","pollFnRef","stop","clearInterval","tick","start","setInterval","UNKNOWN_BROWSER","UNKNOWN_OS","SSR_DEVICE_DATA","userAgent","languages","platform","browser","os","cookieEnabled","maxTouchPoints","vendor","touch","screen","width","height","availWidth","availHeight","colorDepth","pixelRatio","viewport","reducedMotion","colorScheme","NOT_A_BRAND","parseUserAgent","win","mac","replace","android","ios","test","_linux$","linux","edg","opera","firefox","safari","chrome","pickBrowserBrand","brands","meaningful","find","brand","pick","getDeviceData","_nav$userAgent","_nav$language","_nav$platform","_nav$maxTouchPoints","_nav$vendor","_nav$maxTouchPoints2","_screen$width","_screen$height","_screen$availWidth","_screen$availHeight","_screen$colorDepth","_win$devicePixelRatio","_win$innerWidth","_win$innerHeight","nav","globalThis","ua","parsed","uaData","userAgentData","fallback","_uaData$brands","_uaData$platform","mergeBrowserOsFromUaData","devicePixelRatio","innerWidth","innerHeight","_uaData$platform2","hardwareConcurrency","deviceMemory","mobile","useDeviceData","includeBattery","batteryPollIntervalMs","includeHighEntropy","refresh","next","battery","onResize","reducedMotionMq","darkMq","lightMq","onMediaChange","getHighEntropyValues","enriched","_hints$fullVersionLis","_hints$platformVersio","hints","fullVersionList","platformVersion","readHighEntropyBrowserOs","updateHighEntropy","intervalId","updateBattery","getBattery","call","charging","level","readBattery"],"mappings":"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"}