{"version":3,"sources":["../src/types.ts","../src/messaging.ts","../src/logger.ts","../src/request.ts","../src/tracker.ts","../src/ad-renderer.ts","../src/utils.ts","../src/background-handler.ts","../src/sdk.ts"],"names":["ALLOWED_AD_SIZES","MessageType","PlayaYieldError","message","code","details","NetworkError","ConfigError","sendToBackground","resolve","reject","response","PREFIX","debugEnabled","isRuntimeDebugEnabled","shouldLog","setDebugMode","enabled","logger","args","getConfig","requestAd","options","error","trackEvent","event","trackImpression","impressionId","metadata","trackClick","impressionObserverByElement","lastImpressionIdByElement","LAYOUT_TOKENS","applyTextOverflowSafety","el","createAdChoicesIcon","adChoicesUrl","provider","icon","e","baseUrl","providerParam","renderDisplayAd","container","creative","width","height","imageUrl","imageAlt","backgroundColor","img","populateAdContainer","format","title","description","advertiser","useTightTextLayout","imgWrapper","contentWrapper","advertiserEl","titleEl","descEl","useTightTitleClamp","trackAdAvailable","setupViewportImpressionTracking","element","priorObserver","track","tracked","observer","entries","entry","createAdElement","clickUrl","buildAdElement","setupClickTracking","updateAdElement","generateUUID","c","r","isContentScript","validatePlacementContext","placement","url","DEFAULT_BASE_URL","AD_REQUEST_ENDPOINT","TRACK_IMPRESSION_ENDPOINT","REQUEST_TIMEOUT","TRACK_CLICK_ENDPOINT","TRACK_AVAILABLE_ENDPOINT","globalConfig","listenerRegistered","SESSION_STORAGE_KEY","DEFAULT_MAX_IMPRESSIONS","DEFAULT_SESSION_WINDOW_MS","inMemorySession","activeRefreshableAds","initializePlayaYield","config","sender","sendResponse","isPlayaYieldMessage","data","handleMessage","errorMessage","originalAddListener","listener","handleAdRequest","handleTrackEvent","handleTrackAvailable","getSessionData","updateSessionImpression","stopRefreshableAd","payload","params","controller","timeoutId","viewHash","impressionHash","body","referrer","result","newSession","maxImpressions","sessionWindowMs","session","now","windowStartTime","windowExpired","currentCount","newCount","allowed","remaining","updatedSession","adId","ad","updatedActiveAds","id","managedAdCleanupByContainer","isAllowedAdSize","size","validateAdSize","createAd","createManagedRefreshableAd","resolvedContainer","_","adOptions","refreshable","createRefreshableAdInternal","existingCleanup","child","checkIfRemoved","checkInterval","stopManagedAd","DEFAULT_REFRESH_INTERVAL_MS","DEFAULT_MAX_IMPRESSIONS_PER_SESSION","adInstanceId","initialCreative","refreshConfig","refreshIntervalMs","maxImpressionsPerSession","sessionCheck","currentCreative","isActive","isTabVisible","isAdInViewport","visibilityObserver","handleVisibilityChange","timerId","newCreative","newRefreshConfig","newMaxImpressions","newSessionWindowMs"],"mappings":"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","file":"sdk.mjs","sourcesContent":["/**\n * Ad size configuration\n */\nexport const ALLOWED_AD_SIZES = [\n  { width: 300, height: 250 },\n  { width: 320, height: 50 },\n  { width: 320, height: 100 },\n] as const;\n\nexport type Size = (typeof ALLOWED_AD_SIZES)[number];\n\n/**\n * Ad format type - native (text+image) or display (image-only)\n */\nexport type AdFormat = 'native' | 'display';\n\n/**\n * Refresh configuration returned by backend\n * Controls refreshable ad behavior dynamically\n */\nexport interface RefreshConfig {\n  /** Interval between ad refreshes in milliseconds */\n  intervalMs: number;\n  /** Maximum impressions allowed per session window */\n  maxImpressionsPerSession: number;\n  /** Duration of the session window in milliseconds */\n  sessionWindowMs: number;\n}\n\n/**\n * Ad placement types - predefined or custom string\n */\nexport type Placement = 'internal' | 'popup' | 'sidepanel' | 'content_script';\n\n/**\n * Options for requesting an ad\n */\nexport interface AdOptions {\n  /** Placement identifier for the ad slot */\n  placement: Placement;\n  /** Dimensions of the ad */\n  size: Size;\n  /** Optional content categories for targeting */\n  categories?: string[];\n  /** Additional custom parameters */\n  [key: string]: any;\n}\n\n/**\n * Result returned from createAd()\n */\nexport interface AdResult {\n  /** Ready-to-append div element containing ad HTML */\n  element: HTMLDivElement;\n  /** Unique impression ID for tracking */\n  impressionId: string;\n  /** Optional click-through URL */\n  clickUrl?: string;\n}\n\n/**\n * SDK initialization configuration\n */\nexport interface SDKConfig {\n  /** Your PlayaYield API key */\n  apiKey: string;\n  /** Base API URL (defaults to https://api.yourplatform.com) */\n  baseUrl?: string;\n  /**\n   * Enable verbose SDK logging to the console.\n   * Defaults to false. Set to true during development to see detailed logs.\n   *\n   * You can also toggle logging at runtime without changing code by running\n   * this in the extension's DevTools console:\n   *   localStorage.setItem('playayield:debug', 'true')\n   */\n  debug?: boolean;\n}\n\n/**\n * Ad creative response from backend\n * Contains structured data for building ad elements - never raw HTML\n */\nexport interface AdCreative {\n  /** Unique identifier for tracking this impression */\n  impressionId: string;\n  /** Click-through URL for the ad */\n  clickUrl: string;\n  /** Ad dimensions */\n  width: number;\n  height: number;\n  /** URL to the ad image */\n  imageUrl: string;\n  /** Alt text for the image (accessibility) */\n  imageAlt?: string;\n  /** Optional headline text */\n  title?: string;\n  /** Optional description text */\n  description?: string;\n  /** Optional call-to-action text */\n  ctaText?: string;\n  /** Optional advertiser/sponsor name */\n  advertiser?: string;\n  /** Provider name (e.g. 'mgid', 'revcontent') */\n  provider?: string;\n  /** Optional background color (hex or CSS color) */\n  backgroundColor?: string;\n  /** Tracking hash for view events */\n  viewHash?: string;\n  /** Tracking hash for impression events */\n  impressionHash?: string;\n  /** Tracking hash for available events (Taboola) */\n  availableHash?: string;\n  /** URL to the Ad Choices icon hosted on the backend */\n  adChoicesUrl?: string;\n  /** Refresh configuration from backend - controls refreshable ad behavior */\n  refreshConfig?: RefreshConfig;\n  /** Ad format: 'native' (text+image) or 'display' (image-only). Defaults to 'native' if omitted. */\n  format?: AdFormat;\n}\n\n/**\n * Tracking event types supported by the SDK\n */\nexport enum TrackingEventType {\n  IMPRESSION = 'impression',\n  CLICK = 'click',\n}\n\n/**\n * Event tracking payload\n */\nexport interface TrackingEvent {\n  type: TrackingEventType;\n  impressionId: string;\n  timestamp: number;\n  metadata?: Record<string, any>;\n}\n\n/**\n * Message types for chrome.runtime communication\n */\nexport enum MessageType {\n  AD_REQUEST = 'AD_REQUEST',\n  TRACK_EVENT = 'TRACK_EVENT',\n  TRACK_AVAILABLE = 'TRACK_AVAILABLE',\n  GET_CONFIG = 'GET_CONFIG',\n  PING = 'PING',\n  GET_SESSION_DATA = 'GET_SESSION_DATA',\n  UPDATE_SESSION_IMPRESSION = 'UPDATE_SESSION_IMPRESSION',\n  STOP_REFRESHABLE_AD = 'STOP_REFRESHABLE_AD',\n}\n\n/**\n * Message structure for background communication\n */\nexport interface BackgroundMessage {\n  type: MessageType;\n  payload: any;\n}\n\n/**\n * Response from background handler\n */\nexport interface BackgroundResponse<T = any> {\n  success: boolean;\n  data?: T;\n  error?: string;\n}\n\n/**\n * Custom error types\n */\nexport interface ManagedRefreshableAdOptions extends AdOptions {\n  /** Container element or CSS selector where ad should be appended */\n  container: HTMLElement | string;\n}\n\n/**\n * Session data stored in chrome.storage.session\n */\nexport interface SessionData {\n  sessionId: string;\n  startTime: number;\n  windowStartTime: number;\n  impressionCount: number;\n  activeRefreshableAds: string[];\n}\n\n/**\n * Result returned from createManagedRefreshableAd()\n */\nexport interface ManagedRefreshableAdResult {\n  /** Stop refreshing and cleanup */\n  stop: () => void;\n  /** Check if still active */\n  isActive: () => boolean;\n}\n\nexport class PlayaYieldError extends Error {\n  constructor(\n    message: string,\n    public code: string,\n    public details?: any\n  ) {\n    super(message);\n    this.name = 'PlayaYieldError';\n  }\n}\n\nexport class NetworkError extends PlayaYieldError {\n  constructor(message: string, details?: any) {\n    super(message, 'NETWORK_ERROR', details);\n    this.name = 'NetworkError';\n  }\n}\n\nexport class ConfigError extends PlayaYieldError {\n  constructor(message: string) {\n    super(message, 'CONFIG_ERROR');\n    this.name = 'ConfigError';\n  }\n}\n","import type { BackgroundMessage, BackgroundResponse } from './types';\nimport { MessageType } from './types';\n\n/**\n * Send a message to the background service worker and await response\n * @param message Message to send\n * @returns Promise resolving to the response\n */\nexport async function sendToBackground<T = any>(\n  message: BackgroundMessage\n): Promise<BackgroundResponse<T>> {\n  return new Promise((resolve, reject) => {\n    if (!chrome?.runtime?.sendMessage) {\n      reject(new Error('chrome.runtime.sendMessage not available'));\n      return;\n    }\n\n    chrome.runtime.sendMessage(message, (response: BackgroundResponse<T>) => {\n      if (chrome.runtime.lastError) {\n        reject(new Error(chrome.runtime.lastError.message));\n        return;\n      }\n\n      if (!response) {\n        reject(new Error('No response from background'));\n        return;\n      }\n\n      if (!response.success) {\n        reject(new Error(response.error || 'Background request failed'));\n        return;\n      }\n\n      resolve(response);\n    });\n  });\n}\n\n/**\n * Check if background service worker is available\n */\nexport async function isBackgroundAvailable(): Promise<boolean> {\n  try {\n    const response = await chrome.runtime.sendMessage({\n      type: MessageType.PING,\n    });\n    return !!response;\n  } catch {\n    return false;\n  }\n}\n","const PREFIX = '[PlayaYield]';\n\nlet debugEnabled = false;\n\n/**\n * Checks for a runtime debug override via localStorage.\n * Works in extension pages (popup, sidepanel) where localStorage is available.\n * Background service workers do not have localStorage, so this safely returns false there.\n *\n * To enable at runtime without changing code:\n *   localStorage.setItem('playayield:debug', 'true')   // enable\n *   localStorage.removeItem('playayield:debug')         // disable\n */\nfunction isRuntimeDebugEnabled(): boolean {\n  try {\n    return localStorage.getItem('playayield:debug') === 'true';\n  } catch {\n    return false;\n  }\n}\n\nfunction shouldLog(): boolean {\n  return debugEnabled || isRuntimeDebugEnabled();\n}\n\n/**\n * Enable or disable verbose SDK logging.\n * Called internally by initializePlayaYield() based on the `debug` config option.\n */\nexport function setDebugMode(enabled: boolean): void {\n  debugEnabled = enabled;\n}\n\n/**\n * Internal SDK logger.\n *\n * - `log` and `warn` are gated behind the `debug` flag (or the `playayield:debug` localStorage key).\n * - `error` is always emitted — errors should never be silenced.\n *\n * @example\n * // In your background script:\n * initializePlayaYield({ apiKey: 'xxx', debug: true });\n *\n * // Or toggle at runtime in DevTools console (extension pages only):\n * localStorage.setItem('playayield:debug', 'true');\n */\nexport const logger = {\n  log(message: string, ...args: any[]): void {\n    if (shouldLog()) {\n      console.log(`${PREFIX} ${message}`, ...args);\n    }\n  },\n\n  warn(message: string, ...args: any[]): void {\n    if (shouldLog()) {\n      console.warn(`${PREFIX} ${message}`, ...args);\n    }\n  },\n\n  error(message: string, ...args: any[]): void {\n    console.error(`${PREFIX} ${message}`, ...args);\n  },\n};\n","import type { SDKConfig, AdOptions, AdCreative, TrackingEvent } from './types';\nimport { NetworkError, MessageType, ConfigError } from './types';\nimport { sendToBackground } from './messaging';\nimport { logger } from './logger';\n\n/**\n * Get the current configuration from background worker\n */\nexport async function getConfig(): Promise<SDKConfig> {\n  try {\n    const response = await sendToBackground<SDKConfig>({\n      type: MessageType.GET_CONFIG,\n      payload: {},\n    });\n    return response.data!;\n  } catch (error) {\n    throw new ConfigError(\n      'Failed to get SDK config. Make sure initializePlayaYield() is called in your background script.'\n    );\n  }\n}\n\n/**\n * Request an ad from the backend\n */\nexport async function requestAd(options: AdOptions): Promise<AdCreative> {\n  // Always use background for requests (config is stored there)\n  try {\n    const response = await sendToBackground<AdCreative>({\n      type: MessageType.AD_REQUEST,\n      payload: { options },\n    });\n    return response.data!;\n  } catch (error) {\n    throw new NetworkError(\n      `Ad request failed: ${\n        error instanceof Error ? error.message : 'Unknown error'\n      }`\n    );\n  }\n}\n\n/**\n * Track an event (impression or click)\n */\nexport async function trackEvent(event: TrackingEvent): Promise<void> {\n  try {\n    await sendToBackground({\n      type: MessageType.TRACK_EVENT,\n      payload: { event },\n    });\n  } catch (error) {\n    logger.error('Tracking failed:', error);\n    // Don't throw - tracking failures shouldn't break the app\n  }\n}\n","import type { TrackingEvent } from './types';\nimport { TrackingEventType } from './types';\nimport { trackEvent } from './request';\n\n/**\n * Track an impression event\n * @param impressionId Unique impression ID\n * @param metadata Optional additional metadata\n */\nexport async function trackImpression(\n  impressionId: string,\n  metadata?: Record<string, any>\n): Promise<void> {\n  const event: TrackingEvent = {\n    type: TrackingEventType.IMPRESSION,\n    impressionId,\n    timestamp: Date.now(),\n    metadata,\n  };\n\n  await trackEvent(event);\n}\n\n/**\n * Track a click event\n * @param impressionId Unique impression ID\n * @param metadata Optional additional metadata\n */\nexport async function trackClick(\n  impressionId: string,\n  metadata?: Record<string, any>\n): Promise<void> {\n  const event: TrackingEvent = {\n    type: TrackingEventType.CLICK,\n    impressionId,\n    timestamp: Date.now(),\n    metadata,\n  };\n\n  await trackEvent(event);\n}\n","/**\n * @fileoverview Ad Rendering Module\n *\n * This module handles the creation and configuration of ad elements for display\n * in Chrome extensions. It builds DOM elements programmatically from structured\n * ad data - never using innerHTML or raw HTML strings for security.\n *\n * Key Features:\n * - Secure DOM-based ad rendering (no innerHTML)\n * - Automatic impression and click tracking\n * - Accessible image ads with alt text\n * - Performance optimizations\n *\n * The module prioritizes security and performance while providing a simple,\n * developer-friendly API for ad display.\n *\n * @author PlayaYield SDK Team\n * @version 2.0.0\n */\n\nimport type { AdCreative, AdResult } from './types';\nimport { MessageType } from './types';\nimport { trackImpression, trackClick } from './tracker';\nimport { sendToBackground } from './messaging';\nimport { logger } from './logger';\n\n/**\n * Tracks IntersectionObserver instances per ad element.\n *\n * Used to prevent double-counting and to ensure that when a refresh swaps the creative\n * within the same DOM element, any previous observer is disconnected before a new one\n * is attached.\n */\nconst impressionObserverByElement = new WeakMap<\n  HTMLElement,\n  IntersectionObserver\n>();\n\n/**\n * Tracks the last impressionId observed for a given element.\n *\n * If the same creative/impressionId is re-rendered into the same element, we skip\n * re-attaching observers and re-firing tracking.\n */\nconst lastImpressionIdByElement = new WeakMap<HTMLElement, string>();\n\nconst LAYOUT_TOKENS = {\n  card: {\n    minImageHeight: 100,\n    contentPadding: '10px',\n    contentGap: '5px',\n  },\n  banner: {\n    imageWidth: 100,\n    contentPadding: '4px 10px',\n    contentGap: '3px',\n  },\n  bar: {\n    imageWidth: 50,\n    contentPadding: '0 8px',\n    contentGap: '2px',\n  },\n} as const;\n\nfunction applyTextOverflowSafety(el: HTMLElement): void {\n  el.style.minWidth = '0';\n  el.style.overflowWrap = 'anywhere';\n  el.style.wordBreak = 'break-word';\n}\n\n/**\n * Creates an Ad Choices icon element positioned at the top-right corner.\n * Clicking the icon opens the Ad Choices info page in a new tab.\n *\n * @param adChoicesUrl - URL to the Ad Choices icon image\n * @param provider - The ad provider name for the info page\n * @returns Configured HTMLImageElement with click handler\n */\nfunction createAdChoicesIcon(\n  adChoicesUrl: string,\n  provider?: string\n): HTMLImageElement {\n  const icon = document.createElement('img');\n  icon.src = adChoicesUrl;\n  icon.alt = 'Ad Choices';\n  icon.style.position = 'absolute';\n  icon.style.top = '0';\n  icon.style.right = '0';\n  icon.style.width = '18px';\n  icon.style.height = '18px';\n  icon.style.zIndex = '10';\n  icon.style.cursor = 'pointer';\n\n  // Prevent click from bubbling to ad click handler\n  icon.onclick = (e) => {\n    e.stopPropagation();\n    e.preventDefault();\n\n    const baseUrl = 'https://playayield.com/ad-choices';\n    const providerParam = provider\n      ? `?provider=${encodeURIComponent(provider)}`\n      : '';\n    window.open(`${baseUrl}${providerParam}`, '_blank', 'noopener,noreferrer');\n  };\n\n  return icon;\n}\n\n/**\n * Renders a display ad (image-only, no text elements).\n * Display ads are pre-designed creatives where all content is baked into the image.\n * The image fills the entire container with object-fit: cover.\n *\n * @param container - The container element to populate\n * @param creative - The ad creative data\n */\nfunction renderDisplayAd(\n  container: HTMLDivElement,\n  creative: AdCreative\n): void {\n  const {\n    width,\n    height,\n    imageUrl,\n    imageAlt,\n    backgroundColor,\n    adChoicesUrl,\n    provider,\n  } = creative;\n\n  container.innerHTML = '';\n\n  // Base container styles\n  container.style.width = `${width}px`;\n  container.style.height = `${height}px`;\n  container.style.overflow = 'hidden';\n  container.style.position = 'relative';\n  container.style.boxSizing = 'border-box';\n  container.style.backgroundColor = backgroundColor || '#f1f5f9';\n  container.style.border = '1px solid #e2e8f0';\n\n  // Full-bleed image\n  const img = document.createElement('img');\n  img.src = imageUrl;\n  img.alt = imageAlt || 'Advertisement';\n  img.style.width = '100%';\n  img.style.height = '100%';\n  img.style.objectFit = 'cover';\n  img.style.display = 'block';\n  container.appendChild(img);\n\n  // Ad Choices icon\n  if (adChoicesUrl) {\n    container.appendChild(createAdChoicesIcon(adChoicesUrl, provider));\n  }\n}\n\n/**\n * Populates the ad container with the correct layout based on ad format and size.\n *\n * For display ads (format: 'display'):\n * - Full-bleed image with no text elements\n *\n * For native ads (format: 'native' or undefined):\n * - 300x250: Vertical layout (image top, text bottom)\n * - 320x100: Horizontal layout (image left, text right)\n * - 320x50: Compact horizontal layout (image left, text right)\n */\nfunction populateAdContainer(\n  container: HTMLDivElement,\n  creative: AdCreative\n): void {\n  const { format = 'native' } = creative;\n\n  // Display ads: full-bleed image, no text\n  if (format === 'display') {\n    renderDisplayAd(container, creative);\n    return;\n  }\n\n  // Native ads: size-based layouts with text content\n  const {\n    width,\n    height,\n    imageUrl,\n    imageAlt,\n    title,\n    description,\n    advertiser,\n    backgroundColor,\n    adChoicesUrl,\n    provider,\n  } = creative;\n  container.innerHTML = '';\n\n  // Base container styles\n  container.style.width = `${width}px`;\n  container.style.height = `${height}px`;\n  container.style.overflow = 'hidden';\n  container.style.position = 'relative';\n  container.style.boxSizing = 'border-box';\n  container.style.display = 'flex';\n  container.style.backgroundColor = backgroundColor || '#ffffff';\n  container.style.border = '1px solid #e2e8f0';\n  container.style.fontFamily = 'system-ui, -apple-system, sans-serif';\n  container.style.color = '#0f172a';\n  container.style.textAlign = 'left';\n  container.style.lineHeight = 'normal';\n  container.style.letterSpacing = 'normal';\n  container.style.wordBreak = 'break-word';\n  container.style.overflowWrap = 'anywhere';\n\n  if (width === 300 && height === 250) {\n    container.style.flexDirection = 'column';\n\n    const useTightTextLayout = !!advertiser && (title?.length ?? 0) > 64;\n\n    const imgWrapper = document.createElement('div');\n    imgWrapper.style.width = '100%';\n    imgWrapper.style.flexGrow = '1';\n    imgWrapper.style.flexShrink = '1';\n    imgWrapper.style.minHeight = `${LAYOUT_TOKENS.card.minImageHeight}px`;\n    imgWrapper.style.backgroundColor = '#f1f5f9';\n\n    const img = document.createElement('img');\n    img.src = imageUrl;\n    img.alt = imageAlt || 'Advertisement';\n    img.style.width = '100%';\n    img.style.height = '100%';\n    img.style.objectFit = 'cover';\n    img.style.display = 'block';\n\n    imgWrapper.appendChild(img);\n    container.appendChild(imgWrapper);\n\n    const contentWrapper = document.createElement('div');\n    contentWrapper.style.padding = LAYOUT_TOKENS.card.contentPadding;\n    contentWrapper.style.display = 'flex';\n    contentWrapper.style.flexDirection = 'column';\n    contentWrapper.style.gap = LAYOUT_TOKENS.card.contentGap;\n    contentWrapper.style.flexShrink = '0';\n    contentWrapper.style.overflow = 'hidden';\n    applyTextOverflowSafety(contentWrapper);\n\n    if (advertiser) {\n      const advertiserEl = document.createElement('div');\n      advertiserEl.style.fontSize = '10px';\n      advertiserEl.style.fontWeight = '600';\n      advertiserEl.style.lineHeight = '1.2';\n      advertiserEl.style.color = '#64748b';\n      advertiserEl.style.textTransform = 'uppercase';\n      advertiserEl.style.whiteSpace = 'nowrap';\n      advertiserEl.style.textOverflow = 'ellipsis';\n      advertiserEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(advertiserEl);\n      advertiserEl.textContent = 'SPONSORED';\n      contentWrapper.appendChild(advertiserEl);\n    }\n\n    if (title) {\n      const titleEl = document.createElement('div');\n      titleEl.style.fontSize = '15px';\n      titleEl.style.fontWeight = '700';\n      titleEl.style.lineHeight = '1.3';\n      titleEl.style.display = '-webkit-box';\n      titleEl.style.webkitLineClamp = '2';\n      titleEl.style.webkitBoxOrient = 'vertical';\n      titleEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(titleEl);\n      titleEl.textContent = title;\n      contentWrapper.appendChild(titleEl);\n    }\n\n    if (description) {\n      const descEl = document.createElement('div');\n      descEl.style.fontSize = '12px';\n      descEl.style.lineHeight = '1.25';\n      descEl.style.color = '#475569';\n      descEl.style.display = '-webkit-box';\n      descEl.style.webkitLineClamp = useTightTextLayout ? '2' : '3';\n      descEl.style.webkitBoxOrient = 'vertical';\n      descEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(descEl);\n      descEl.textContent = description;\n      contentWrapper.appendChild(descEl);\n    }\n\n    container.appendChild(contentWrapper);\n\n    // Add Ad Choices icon if provided\n    if (adChoicesUrl) {\n      container.appendChild(createAdChoicesIcon(adChoicesUrl, provider));\n    }\n  } else if (width === 320 && height === 100) {\n    container.style.flexDirection = 'row';\n\n    const useTightTitleClamp = !!advertiser && (title?.length ?? 0) > 72;\n\n    const imgWrapper = document.createElement('div');\n    imgWrapper.style.width = `${LAYOUT_TOKENS.banner.imageWidth}px`;\n    imgWrapper.style.height = '100%';\n    imgWrapper.style.flexShrink = '0';\n    imgWrapper.style.backgroundColor = '#f1f5f9';\n\n    const img = document.createElement('img');\n    img.src = imageUrl;\n    img.alt = imageAlt || 'Advertisement';\n    img.style.width = '100%';\n    img.style.height = '100%';\n    img.style.objectFit = 'cover';\n    img.style.display = 'block';\n\n    imgWrapper.appendChild(img);\n    container.appendChild(imgWrapper);\n\n    const contentWrapper = document.createElement('div');\n    contentWrapper.style.padding = LAYOUT_TOKENS.banner.contentPadding;\n    contentWrapper.style.display = 'flex';\n    contentWrapper.style.flexDirection = 'column';\n    contentWrapper.style.justifyContent = 'center';\n    contentWrapper.style.gap = LAYOUT_TOKENS.banner.contentGap;\n    contentWrapper.style.flexGrow = '1';\n    contentWrapper.style.overflow = 'hidden';\n    contentWrapper.style.minWidth = '0';\n    contentWrapper.style.minHeight = '0';\n    applyTextOverflowSafety(contentWrapper);\n\n    if (advertiser) {\n      const advertiserEl = document.createElement('div');\n      advertiserEl.style.fontSize = '10px';\n      advertiserEl.style.fontWeight = '600';\n      advertiserEl.style.lineHeight = '1.15';\n      advertiserEl.style.color = '#64748b';\n      advertiserEl.style.textTransform = 'uppercase';\n      advertiserEl.style.whiteSpace = 'nowrap';\n      advertiserEl.style.textOverflow = 'ellipsis';\n      advertiserEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(advertiserEl);\n      advertiserEl.textContent = 'SPONSORED';\n      contentWrapper.appendChild(advertiserEl);\n    }\n\n    if (title) {\n      const titleEl = document.createElement('div');\n      titleEl.style.fontSize = '12px';\n      titleEl.style.fontWeight = '700';\n      titleEl.style.lineHeight = '1.2';\n      titleEl.style.display = '-webkit-box';\n      titleEl.style.webkitLineClamp = useTightTitleClamp ? '2' : '3';\n      titleEl.style.webkitBoxOrient = 'vertical';\n      titleEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(titleEl);\n      titleEl.textContent = title;\n      contentWrapper.appendChild(titleEl);\n    }\n\n    if (description) {\n      const descEl = document.createElement('div');\n      descEl.style.fontSize = '11px';\n      descEl.style.lineHeight = '1.2';\n      descEl.style.color = '#475569';\n      descEl.style.display = '-webkit-box';\n      descEl.style.webkitLineClamp = '1';\n      descEl.style.webkitBoxOrient = 'vertical';\n      descEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(descEl);\n      descEl.textContent = description;\n      contentWrapper.appendChild(descEl);\n    }\n\n    container.appendChild(contentWrapper);\n\n    // Add Ad Choices icon if provided\n    if (adChoicesUrl) {\n      container.appendChild(createAdChoicesIcon(adChoicesUrl, provider));\n    }\n  } else if (width === 320 && height === 50) {\n    container.style.flexDirection = 'row';\n\n    const imgWrapper = document.createElement('div');\n    imgWrapper.style.width = `${LAYOUT_TOKENS.bar.imageWidth}px`;\n    imgWrapper.style.height = '100%';\n    imgWrapper.style.flexShrink = '0';\n    imgWrapper.style.backgroundColor = '#f1f5f9';\n\n    const img = document.createElement('img');\n    img.src = imageUrl;\n    img.alt = imageAlt || 'Advertisement';\n    img.style.width = '100%';\n    img.style.height = '100%';\n    img.style.objectFit = 'cover';\n    img.style.display = 'block';\n\n    imgWrapper.appendChild(img);\n    container.appendChild(imgWrapper);\n\n    const contentWrapper = document.createElement('div');\n    contentWrapper.style.padding = LAYOUT_TOKENS.bar.contentPadding;\n    contentWrapper.style.display = 'flex';\n    contentWrapper.style.flexDirection = 'column';\n    contentWrapper.style.justifyContent = 'center';\n    contentWrapper.style.gap = LAYOUT_TOKENS.bar.contentGap;\n    contentWrapper.style.flexGrow = '1';\n    contentWrapper.style.overflow = 'hidden';\n    contentWrapper.style.minWidth = '0';\n    contentWrapper.style.minHeight = '0';\n    applyTextOverflowSafety(contentWrapper);\n\n    if (title) {\n      const titleEl = document.createElement('div');\n      titleEl.style.fontSize = '13px';\n      titleEl.style.fontWeight = '700';\n      titleEl.style.lineHeight = '1.2';\n      titleEl.style.whiteSpace = 'nowrap';\n      titleEl.style.textOverflow = 'ellipsis';\n      titleEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(titleEl);\n      titleEl.textContent = title;\n      contentWrapper.appendChild(titleEl);\n    }\n\n    if (advertiser) {\n      const advertiserEl = document.createElement('div');\n      advertiserEl.style.fontSize = '10px';\n      advertiserEl.style.fontWeight = '600';\n      advertiserEl.style.lineHeight = '1.1';\n      advertiserEl.style.color = '#64748b';\n      advertiserEl.style.textTransform = 'uppercase';\n      advertiserEl.style.whiteSpace = 'nowrap';\n      advertiserEl.style.textOverflow = 'ellipsis';\n      advertiserEl.style.overflow = 'hidden';\n      applyTextOverflowSafety(advertiserEl);\n      advertiserEl.textContent = 'SPONSORED';\n      contentWrapper.appendChild(advertiserEl);\n    }\n\n    container.appendChild(contentWrapper);\n\n    // Add Ad Choices icon if provided\n    if (adChoicesUrl) {\n      container.appendChild(createAdChoicesIcon(adChoicesUrl, provider));\n    }\n  } else {\n    const img = document.createElement('img');\n    img.src = imageUrl;\n    img.alt = imageAlt || 'Advertisement';\n    img.style.width = '100%';\n    img.style.height = '100%';\n    img.style.objectFit = 'cover';\n    img.style.display = 'block';\n    container.appendChild(img);\n\n    // Add Ad Choices icon if provided\n    if (adChoicesUrl) {\n      container.appendChild(createAdChoicesIcon(adChoicesUrl, provider));\n    }\n  }\n}\n\n/**\n * Tracks the available event (ad rendered to DOM) immediately.\n * This is Taboola-specific and fires before the ad becomes visible.\n *\n * @param creative The ad creative that was rendered.\n */\nasync function trackAdAvailable(creative: AdCreative): Promise<void> {\n  // Only track available event if provider supports it (currently only Taboola)\n  if (!creative.availableHash || !creative.provider) {\n    return;\n  }\n\n  try {\n    await sendToBackground({\n      type: MessageType.TRACK_AVAILABLE,\n      payload: {\n        impressionId: creative.impressionId,\n        provider: creative.provider,\n        availableHash: creative.availableHash,\n      },\n    });\n  } catch (error) {\n    logger.error('Failed to track available event:', error);\n  }\n}\n\n/**\n * Sets up viewport-based impression tracking for an ad element.\n *\n * Fires a single impression event when the ad element becomes visible in the viewport\n * (>= 50% visible). Uses IntersectionObserver when available.\n *\n * Safeguards:\n * - Disconnects any prior observer registered for this element (prevents late-firing\n *   observers from earlier creatives after refresh).\n * - Skips tracking if the same impressionId has already been registered for this element.\n *\n * @param element The rendered ad container element.\n * @param creative The ad creative that should be tracked when visible.\n */\nfunction setupViewportImpressionTracking(\n  element: HTMLElement,\n  creative: AdCreative\n): void {\n  const { impressionId } = creative;\n\n  const lastImpressionId = lastImpressionIdByElement.get(element);\n  if (lastImpressionId === impressionId) {\n    return;\n  }\n\n  lastImpressionIdByElement.set(element, impressionId);\n\n  const priorObserver = impressionObserverByElement.get(element);\n  if (priorObserver) {\n    priorObserver.disconnect();\n    impressionObserverByElement.delete(element);\n  }\n\n  const track = () => {\n    trackImpression(impressionId, {\n      type: 'image',\n      provider: creative.provider,\n      viewHash: creative.viewHash,\n      impressionHash: creative.impressionHash,\n    });\n  };\n\n  if (typeof IntersectionObserver === 'undefined') {\n    // Fallback: track shortly after render\n    setTimeout(track, 100);\n    return;\n  }\n\n  let tracked = false;\n  const observer = new IntersectionObserver(\n    (entries) => {\n      if (tracked) return;\n      const entry = entries[0];\n      if (!entry) return;\n      if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {\n        tracked = true;\n        observer.disconnect();\n        impressionObserverByElement.delete(element);\n        track();\n      }\n    },\n    { threshold: [0.5] }\n  );\n\n  impressionObserverByElement.set(element, observer);\n  observer.observe(element);\n}\n\n/**\n * Creates a ready-to-append HTML div element from structured ad creative data.\n *\n * This function handles the complete ad rendering process:\n * - Creates DOM elements programmatically (no innerHTML)\n * - Builds an image-based ad with optional title/description\n * - Sets up automatic impression tracking\n * - Configures click tracking with the click URL\n * - Returns a fully configured HTMLDivElement ready for DOM insertion\n *\n * @param creative - Structured ad creative data from the backend API\n * @returns AdResult object containing the rendered div element, impression ID, and click URL\n *\n * @throws {Error} When imageUrl is not provided in the creative\n *\n * @example\n * ```typescript\n * const { element, impressionId } = createAdElement(creative);\n * document.getElementById('ad-slot')!.appendChild(element);\n * ```\n *\n * @internal This function is used internally by the SDK and not exposed to developers\n */\nexport function createAdElement(creative: AdCreative): AdResult {\n  const { impressionId, clickUrl, width, height, imageUrl } = creative;\n\n  if (!imageUrl) {\n    throw new Error('No imageUrl provided in ad creative');\n  }\n\n  const element = buildAdElement(creative);\n\n  // Set up click tracking\n  setupClickTracking(element, impressionId, clickUrl, creative.provider);\n\n  return {\n    element,\n    impressionId,\n    clickUrl,\n  };\n}\n\n/**\n * Builds an ad container element using DOM APIs (no innerHTML).\n *\n * This function creates a div container with:\n * - Image element with the ad creative\n * - Optional title and description text\n * - Fixed dimensions to prevent layout shifts\n * - Hidden overflow to contain content within bounds\n * - Immediate impression tracking\n * - Data attributes for debugging and analytics\n *\n * @param creative - Structured ad creative data\n * @returns Configured HTMLDivElement with ad content\n *\n * @example\n * ```typescript\n * const container = buildAdElement(creative);\n * document.body.appendChild(container);\n * ```\n *\n * @internal Used internally by createAdElement\n */\nfunction buildAdElement(creative: AdCreative): HTMLDivElement {\n  const { impressionId } = creative;\n\n  // Create container\n  const container = document.createElement('div');\n  container.setAttribute('data-playayield-id', impressionId);\n\n  populateAdContainer(container, creative);\n\n  // Track available event immediately (Taboola only)\n  trackAdAvailable(creative);\n\n  // Track impression when ad is visible in viewport\n  setupViewportImpressionTracking(container, creative);\n\n  return container;\n}\n\n/**\n * Configures click tracking and navigation behavior for ad elements.\n *\n * This function sets up comprehensive click handling for ad elements:\n * - Visual cursor indicator (pointer) to show element is clickable\n * - Click event interception to prevent default browser behavior\n * - Automatic click tracking with impression ID and click URL\n * - Secure navigation to click URL in new tab with security flags\n * - Prevents event bubbling to avoid conflicts with parent elements\n *\n * The function ensures that all ad clicks are properly tracked before\n * redirecting users to the advertiser's landing page.\n *\n * @param element - The HTML element to attach click tracking to\n * @param impressionId - Unique identifier for the ad impression being tracked\n * @param clickUrl - The destination URL to navigate to when clicked\n * @returns void - Modifies the element in place\n *\n * @example\n * ```typescript\n * const adElement = document.createElement('div');\n * setupClickTracking(adElement, 'imp_123', 'https://advertiser.example.com/landing');\n * document.body.appendChild(adElement);\n * ```\n *\n * @internal Used internally by createAdElement when clickUrl is provided\n */\nfunction setupClickTracking(\n  element: HTMLElement,\n  impressionId: string,\n  clickUrl: string,\n  provider?: string\n): void {\n  element.style.cursor = 'pointer';\n\n  element.onclick = (e) => {\n    e.preventDefault();\n    e.stopPropagation();\n\n    // Track click\n    trackClick(impressionId, {\n      clickUrl,\n      provider,\n      referrer: document.referrer,\n    });\n\n    // Open click URL in new tab\n    window.open(clickUrl, '_blank', 'noopener,noreferrer');\n  };\n}\n\n/**\n * Updates an existing ad element with new creative data.\n * Used by refreshable ads to swap content without destroying the DOM element.\n *\n * This function:\n * - Clears the existing ad content\n * - Rebuilds the ad with new creative data\n * - Maintains the same container element (preserves DOM position)\n * - Re-attaches click tracking for the new creative\n * - Updates data attributes\n * - Tracks new impression\n *\n * @param element - The existing ad container element to update\n * @param creative - New ad creative data to display\n *\n * @example\n * ```typescript\n * const { element } = createAdElement(oldCreative);\n * document.body.appendChild(element);\n *\n * // Later, refresh with new creative:\n * updateAdElement(element, newCreative);\n * ```\n *\n * @internal Used internally by refreshable ads\n */\nexport function updateAdElement(\n  element: HTMLDivElement,\n  creative: AdCreative\n): void {\n  const { impressionId, clickUrl, width, height, imageUrl } = creative;\n\n  if (!imageUrl) {\n    throw new Error('No imageUrl provided in ad creative');\n  }\n\n  // Clear existing content but keep the element reference\n  element.setAttribute('data-playayield-id', impressionId);\n\n  populateAdContainer(element, creative);\n\n  // Re-attach click tracking for the refreshed creative\n  setupClickTracking(element, impressionId, clickUrl, creative.provider);\n\n  // Track available event immediately (Taboola only)\n  trackAdAvailable(creative);\n\n  // Track new impression when refreshed ad is visible\n  setupViewportImpressionTracking(element, creative);\n}\n","import { logger } from './logger';\nimport { ConfigError } from './types';\n\n/**\n * Generate a UUID v4\n */\nexport function generateUUID(): string {\n  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n    const r = (Math.random() * 16) | 0;\n    const v = c === 'x' ? r : (r & 0x3) | 0x8;\n    return v.toString(16);\n  });\n}\n\n/**\n * Sleep utility\n */\nexport function sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Check if running in Chrome extension context\n */\nexport function isExtensionContext(): boolean {\n  return (\n    typeof chrome !== 'undefined' && !!chrome.runtime && !!chrome.runtime.id\n  );\n}\n\n/**\n * Safe JSON parse with fallback\n */\nexport function safeJsonParse<T>(json: string, fallback: T): T {\n  try {\n    return JSON.parse(json);\n  } catch {\n    return fallback;\n  }\n}\n\n/**\n * Detects if the code is executing in a content script context.\n *\n * @remarks\n * - Uses `window.location.protocol !== 'chrome-extension:'` to infer content scripts\n *   (content scripts run on http/https/file pages, not chrome-extension pages).\n * - Returns `false` when `window` is unavailable (e.g., background/service worker),\n *   so background and offscreen documents will be treated as extension contexts.\n */\nexport function isContentScript(): boolean {\n  if (typeof window === 'undefined') return false;\n  // Content scripts run on http/https/file pages\n  // Extension pages (popup, sidepanel) run on chrome-extension:\n  return window.location.protocol !== 'chrome-extension:';\n}\n\n/**\n * Validate that the requested placement matches the actual execution context.\n *\n * @param placement Placement identifier to verify against the current context\n *\n * @throws {ConfigError} When the placement does not match the detected context.\n *\n * @notes\n * - Content scripts MUST use placement `'content_script'`. Any other placement\n *   from a content script is rejected to prevent developers from misreporting\n *   where ads are displayed.\n * - Extension pages (popup, sidepanel, internal) are validated against the current\n *   URL when `window` is available.\n * - Background/service worker code will never throw because `window` is absent.\n */\nexport function validatePlacementContext(placement?: string): void {\n  // Content scripts must use the 'content_script' placement\n  if (isContentScript()) {\n    if (placement && placement !== 'content_script') {\n      throw new ConfigError(\n        `Placement mismatch: '${placement}' requested but running in a content script context. Use 'content_script' placement for content scripts.`\n      );\n    }\n    return;\n  }\n\n  // Extension page URL-based verification\n  if (typeof window !== 'undefined' && placement) {\n    const url = window.location.href.toLowerCase();\n\n    if (placement === 'popup' && !url.includes('popup')) {\n      logger.warn(\n        `Placement mismatch: 'popup' requested but running on ${window.location.pathname}`\n      );\n    }\n\n    if (placement === 'sidepanel' && !url.includes('sidepanel')) {\n      logger.warn(\n        `Placement mismatch: 'sidepanel' requested but running on ${window.location.pathname}`\n      );\n    }\n  }\n}\n\n/**\n * Constants\n */\nexport const DEFAULT_BASE_URL = 'https://www.playayield.com';\nexport const AD_REQUEST_ENDPOINT = '/api/ads';\nexport const TRACK_IMPRESSION_ENDPOINT = '/api/ads/track-impression';\nexport const REQUEST_TIMEOUT = 5000;\n","import type {\n  BackgroundMessage,\n  BackgroundResponse,\n  AdCreative,\n  TrackingEvent,\n  SDKConfig,\n  SessionData,\n} from './types';\nimport { MessageType, ConfigError, TrackingEventType } from './types';\nimport {\n  DEFAULT_BASE_URL,\n  AD_REQUEST_ENDPOINT,\n  TRACK_IMPRESSION_ENDPOINT,\n  REQUEST_TIMEOUT,\n  generateUUID,\n} from './utils';\nimport { logger, setDebugMode } from './logger';\n\nconst TRACK_CLICK_ENDPOINT = '/api/ads/track-click';\nconst TRACK_AVAILABLE_ENDPOINT = '/api/ads/track-available';\n\n// Global config stored in background worker\nlet globalConfig: SDKConfig | null = null;\n\n// Guard to ensure the onMessage listener is registered at most once per worker lifetime\nlet listenerRegistered = false;\n\n// Constants for session management\nconst SESSION_STORAGE_KEY = 'playaYieldSession';\nconst DEFAULT_MAX_IMPRESSIONS = 3;\nconst DEFAULT_SESSION_WINDOW_MS = 30 * 60 * 1000;\n\n// Module-level in-memory session cache (persists across calls within same service worker)\nlet inMemorySession: SessionData | null = null;\n\n// In-memory tracking of active refreshable ads (cleared on service worker restart)\nconst activeRefreshableAds = new Map<\n  string,\n  { timerId: ReturnType<typeof setInterval> }\n>();\n\n/**\n * Initialize PlayaYield SDK in the background service worker\n * This sets up the message handler and stores your configuration globally\n *\n * Call this once in your background service worker with your API key and settings.\n * Content scripts and popups can then use createAd() without needing to initialize.\n *\n * @param config SDK configuration including API key\n * @throws {ConfigError} If configuration is invalid\n *\n * @example\n * ```ts\n * // background.ts\n * import { initializePlayaYield } from '@playanext/playa-yield-sdk';\n *\n * initializePlayaYield({\n *   apiKey: 'your-api-key'\n * });\n * ```\n */\nexport function initializePlayaYield(config: SDKConfig): void {\n  // Validate config\n  if (!config.apiKey) {\n    throw new ConfigError('apiKey is required');\n  }\n\n  // Store globally\n  globalConfig = {\n    ...config,\n  };\n\n  setDebugMode(globalConfig.debug ?? false);\n\n  // Register the message listener exactly once per service worker lifetime.\n  // If the worker restarts, the entire module re-executes and the flag resets\n  // to false, so a fresh listener is registered. But if initializePlayaYield()\n  // is called multiple times within the same lifetime (e.g. hot-reload, or\n  // accidental double-call), we skip re-registration to avoid duplicate handlers.\n  if (!listenerRegistered) {\n    chrome.runtime.onMessage.addListener(\n      (\n        message: any,\n        sender: chrome.runtime.MessageSender,\n        sendResponse: (response: BackgroundResponse) => void\n      ) => {\n        // Only handle PlayaYield messages - check if message has expected structure\n        if (!isPlayaYieldMessage(message)) {\n          return false; // Let other listeners handle this message\n        }\n\n        (async () => {\n          try {\n            // Handle async operations for PlayaYield messages\n            const data = await handleMessage(message, sender);\n            sendResponse({ success: true, data });\n          } catch (error: unknown) {\n            logger.error('Unhandled background message error:', error);\n            const errorMessage =\n              error instanceof Error ? error.message : String(error);\n            sendResponse({\n              success: false,\n              error: errorMessage || 'Unknown error',\n            });\n          }\n        })();\n\n        // IMPORTANT (MV3): must return synchronously to keep the message channel open\n        return true;\n      }\n    );\n\n    // AFTER initializePlayaYield() is automatically wrapped to skip SDK messages.\n    // This means developers don't need to guard their own listeners manually.\n    const originalAddListener = chrome.runtime.onMessage.addListener.bind(\n      chrome.runtime.onMessage\n    );\n    chrome.runtime.onMessage.addListener = (listener: any) => {\n      const wrapped = (\n        message: any,\n        sender: chrome.runtime.MessageSender,\n        sendResponse: (response: any) => void\n      ) => {\n        // If this is a PlayaYield message, skip — our listener above handles it\n        if (isPlayaYieldMessage(message)) {\n          return false;\n        }\n        return listener(message, sender, sendResponse);\n      };\n      originalAddListener(wrapped);\n    };\n\n    listenerRegistered = true;\n  }\n\n  logger.log('SDK initialized in background', {\n    debug: globalConfig.debug ?? false,\n  });\n}\n\n/**\n * Returns the active SDK configuration set via {@link initializePlayaYield}.\n *\n * @throws {ConfigError} when the SDK has not been initialized in the background.\n */\nfunction getConfig(): SDKConfig {\n  if (!globalConfig) {\n    throw new ConfigError(\n      'SDK not initialized. Call initializePlayaYield() in your background script first.'\n    );\n  }\n  return globalConfig;\n}\n\n/**\n * Type guard to confirm a runtime message belongs to the PlayaYield SDK.\n *\n * @param message Arbitrary message received by the background listener.\n * @returns True when the message type matches a known {@link MessageType}.\n */\nfunction isPlayaYieldMessage(message: any): message is BackgroundMessage {\n  return (\n    message &&\n    typeof message === 'object' &&\n    typeof message.type === 'string' &&\n    Object.values(MessageType).includes(message.type as MessageType)\n  );\n}\n\n/**\n * Dispatches background requests based on {@link MessageType}.\n *\n * @param message The parsed PlayaYield background message.\n * @param sender The Chrome runtime sender metadata.\n * @returns A message-specific payload or void, wrapped by the onMessage responder.\n */\nasync function handleMessage(\n  message: BackgroundMessage,\n  sender: chrome.runtime.MessageSender\n): Promise<any> {\n  switch (message.type) {\n    case MessageType.AD_REQUEST:\n      return handleAdRequest(message.payload);\n\n    case MessageType.TRACK_EVENT:\n      return handleTrackEvent(message.payload);\n\n    case MessageType.TRACK_AVAILABLE:\n      return handleTrackAvailable(message.payload);\n\n    case MessageType.GET_CONFIG:\n      return getConfig();\n\n    case MessageType.PING:\n      return { pong: true };\n\n    case MessageType.GET_SESSION_DATA:\n      return getSessionData();\n\n    case MessageType.UPDATE_SESSION_IMPRESSION:\n      return updateSessionImpression(message.payload);\n\n    case MessageType.STOP_REFRESHABLE_AD:\n      return stopRefreshableAd(message.payload);\n\n    default:\n      throw new Error(`Unknown message type: ${message.type}`);\n  }\n}\n\n/**\n * Issues an ad request to the backend on behalf of a content/UI script.\n *\n * @param payload.options Ad request options (placement, size, metadata, etc.).\n * @returns Resolved {@link AdCreative} from the backend.\n * @throws Error when the HTTP request fails or times out.\n */\nasync function handleAdRequest(payload: { options: any }): Promise<AdCreative> {\n  const { options } = payload;\n  const config = getConfig();\n  const baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n\n  // Build query params - apiKey goes in query to avoid CORS preflight\n  const params = new URLSearchParams({\n    apiKey: config.apiKey,\n    extensionId: chrome.runtime.id,\n    placement: options.placement,\n    width: String(options.size?.width ?? options.width ?? 300),\n    height: String(options.size?.height ?? options.height ?? 250),\n  });\n\n  // Add optional categories\n  if (options.categories?.length) {\n    params.set('categories', options.categories.join(','));\n  }\n\n  // Add metadata as URL-encoded JSON\n  const metadata = { ...options };\n  delete metadata.placement;\n  delete metadata.size;\n  delete metadata.categories;\n  if (Object.keys(metadata).length > 0) {\n    params.set('metadata', encodeURIComponent(JSON.stringify(metadata)));\n  }\n\n  const url = new URL(AD_REQUEST_ENDPOINT, baseUrl);\n  url.search = params.toString();\n\n  const controller = new AbortController();\n  const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);\n\n  try {\n    const response = await fetch(url, {\n      method: 'GET',\n      signal: controller.signal,\n    });\n\n    clearTimeout(timeoutId);\n\n    if (!response.ok) {\n      throw new Error(`Ad request failed: ${response.status}`);\n    }\n\n    return await response.json();\n  } catch (error: any) {\n    clearTimeout(timeoutId);\n    throw new Error(`Ad request failed: ${error.message}`);\n  }\n}\n\n/**\n * Tracks supported events (currently impressions) server-side.\n *\n * @param payload.event Tracking event containing impression metadata.\n * @remarks Clicks are handled client-side via navigation; failures are logged but not thrown.\n */\nasync function handleTrackEvent(payload: {\n  event: TrackingEvent;\n}): Promise<void> {\n  const { event } = payload;\n  const config = getConfig();\n  const baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n\n  if (event.type === TrackingEventType.IMPRESSION) {\n    const url = new URL(TRACK_IMPRESSION_ENDPOINT, baseUrl);\n\n    // Extract metadata from event\n    const { provider, viewHash, impressionHash } = event.metadata || {};\n\n    // Don't track if no provider (shouldn't happen for valid ads)\n    if (!provider) {\n      logger.warn('Missing provider in impression event', event);\n      return;\n    }\n\n    try {\n      const body = {\n        impressionId: event.impressionId,\n        provider,\n        viewHash,\n        impressionHash,\n      };\n\n      await fetch(url, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify(body),\n      });\n\n      logger.log('Impression tracked successfully', {\n        impressionId: event.impressionId,\n        provider,\n      });\n    } catch (error) {\n      logger.error('Failed to track impression:', error);\n      // We don't throw here to avoid disrupting the extension flow\n    }\n\n    return;\n  }\n\n  if (event.type === TrackingEventType.CLICK) {\n    const url = new URL(TRACK_CLICK_ENDPOINT, baseUrl);\n\n    const { provider, clickUrl, referrer } = event.metadata || {};\n\n    try {\n      await fetch(url, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          impressionId: event.impressionId,\n          provider,\n          clickUrl,\n          referrer,\n          timestamp: event.timestamp,\n        }),\n      });\n    } catch (error) {\n      logger.error('Failed to track click:', error);\n    }\n  }\n}\n\n/**\n * Tracks available events (ad rendered to DOM) server-side.\n * This is Taboola-specific and fires before the ad becomes visible.\n *\n * @param payload Available event data including impressionId, provider, and availableHash.\n */\nasync function handleTrackAvailable(payload: {\n  impressionId: string;\n  provider: string;\n  availableHash?: string;\n}): Promise<void> {\n  const config = getConfig();\n  const baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n  const url = new URL(TRACK_AVAILABLE_ENDPOINT, baseUrl);\n\n  if (!payload.provider) {\n    logger.warn('Missing provider in available event', payload);\n    return;\n  }\n\n  try {\n    const body = {\n      impressionId: payload.impressionId,\n      provider: payload.provider,\n      availableHash: payload.availableHash,\n    };\n\n    await fetch(url, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify(body),\n    });\n\n    logger.log('Available event tracked successfully', {\n      impressionId: payload.impressionId,\n      provider: payload.provider,\n    });\n  } catch (error) {\n    logger.error('Failed to track available event:', error);\n  }\n}\n\n/**\n * Loads or initializes per-session data stored in `chrome.storage.session` with an\n * in-memory fallback. Sessions are cleared when the browser closes or the service\n * worker stops.\n *\n * @returns The current {@link SessionData} (cached for reuse).\n */\nasync function getSessionData(): Promise<SessionData> {\n  // Check in-memory cache first (persists across calls when storage unavailable)\n  if (inMemorySession) {\n    logger.log('Session loaded from in-memory cache', {\n      impressionCount: inMemorySession.impressionCount,\n      sessionId: inMemorySession.sessionId,\n    });\n    return inMemorySession;\n  }\n\n  // Check if chrome.storage.session is available\n  if (chrome.storage?.session) {\n    const result = await chrome.storage.session.get(SESSION_STORAGE_KEY);\n    if (result[SESSION_STORAGE_KEY]) {\n      logger.log('Session loaded from storage', {\n        impressionCount: result[SESSION_STORAGE_KEY].impressionCount,\n        sessionId: result[SESSION_STORAGE_KEY].sessionId,\n      });\n      // Cache in memory too\n      inMemorySession = result[SESSION_STORAGE_KEY] as SessionData;\n      return inMemorySession;\n    }\n  } else {\n    // Fallback: session storage not available, use in-memory\n    logger.warn('Session storage not available, using in-memory fallback');\n  }\n\n  // Initialize new session\n  const newSession: SessionData = {\n    sessionId: generateUUID(),\n    startTime: Date.now(),\n    windowStartTime: Date.now(),\n    impressionCount: 0,\n    activeRefreshableAds: [],\n  };\n\n  // Cache in memory\n  inMemorySession = newSession;\n\n  logger.log('New session created', {\n    sessionId: newSession.sessionId,\n  });\n\n  if (chrome.storage?.session) {\n    await chrome.storage.session.set({ [SESSION_STORAGE_KEY]: newSession });\n  } else {\n    logger.log('Failed to persist new session (storage unavailable)');\n  }\n\n  return newSession;\n}\n\n/**\n * Increments the session impression counter and tracks active refreshable ads.\n *\n * @param payload.adId Identifier for the ad being counted.\n * @param payload.maxImpressions Optional per-session cap; defaults to {@link DEFAULT_MAX_IMPRESSIONS}.\n * @param payload.sessionWindowMs Optional window duration in ms; defaults to {@link DEFAULT_SESSION_WINDOW_MS}.\n * @returns Object with allowance flag, remaining quota, and total impressions.\n */\nasync function updateSessionImpression(payload: {\n  adId: string;\n  maxImpressions?: number;\n  sessionWindowMs?: number;\n}): Promise<{ allowed: boolean; remaining: number; total: number }> {\n  const maxImpressions = payload.maxImpressions ?? DEFAULT_MAX_IMPRESSIONS;\n  const sessionWindowMs = payload.sessionWindowMs ?? DEFAULT_SESSION_WINDOW_MS;\n  const session = await getSessionData();\n\n  const now = Date.now();\n  const windowStartTime = session.windowStartTime ?? session.startTime;\n  const windowExpired = now - windowStartTime >= sessionWindowMs;\n\n  const currentCount = windowExpired ? 0 : session.impressionCount;\n  const newCount = currentCount + 1;\n  const allowed = newCount <= maxImpressions;\n  const remaining = Math.max(0, maxImpressions - newCount);\n\n  logger.log('Session impression check', {\n    adId: payload.adId,\n    currentCount,\n    newCount,\n    maxImpressions,\n    sessionWindowMs,\n    allowed,\n    remaining,\n    sessionId: session.sessionId,\n    windowExpired,\n  });\n\n  if (allowed) {\n    const updatedSession: SessionData = {\n      ...session,\n      windowStartTime: windowExpired ? now : windowStartTime,\n      impressionCount: newCount,\n      activeRefreshableAds: session.activeRefreshableAds.includes(payload.adId)\n        ? session.activeRefreshableAds\n        : [...session.activeRefreshableAds, payload.adId],\n    };\n\n    // Update in-memory cache\n    inMemorySession = updatedSession;\n\n    if (chrome.storage?.session) {\n      await chrome.storage.session.set({\n        [SESSION_STORAGE_KEY]: updatedSession,\n      });\n      logger.log('Session updated, impression count:', newCount);\n    } else {\n      // Session storage not available\n      logger.log(\n        'Session updated in memory only (storage unavailable), count:',\n        newCount\n      );\n    }\n  } else {\n    logger.log('Max impressions reached, blocking ad display');\n  }\n\n  return { allowed, remaining, total: newCount };\n}\n\n/**\n * Stops a refreshable ad by clearing its timer and removing it from session tracking.\n *\n * @param payload.adId Identifier of the refreshable ad to stop.\n */\nasync function stopRefreshableAd(payload: { adId: string }): Promise<void> {\n  const { adId } = payload;\n\n  // Clear the timer if it exists in this worker lifetime.\n  // After a service worker restart the Map is empty, which is expected —\n  // the actual refresh timers live in the UI context (popup/sidepanel),\n  // not in the background.\n  const ad = activeRefreshableAds.get(adId);\n  if (ad) {\n    clearInterval(ad.timerId);\n    activeRefreshableAds.delete(adId);\n  }\n\n  // Remove from session tracking\n  const session = await getSessionData();\n  const updatedActiveAds = session.activeRefreshableAds.filter(\n    (id) => id !== adId\n  );\n\n  const updatedSession: SessionData = {\n    ...session,\n    activeRefreshableAds: updatedActiveAds,\n  };\n\n  // Sync in-memory cache so subsequent reads within this worker lifetime\n  // see the updated list without hitting storage again\n  inMemorySession = updatedSession;\n\n  if (chrome.storage?.session) {\n    await chrome.storage.session.set({\n      [SESSION_STORAGE_KEY]: updatedSession,\n    });\n  }\n}\n","/**\n * @playanext/playa-yield-sdk - Chrome Extension Ad Monetization SDK\n * Manifest V3 compliant ad SDK for Chrome extensions\n */\n\nimport type {\n  AdOptions,\n  AdResult,\n  ManagedRefreshableAdOptions,\n  ManagedRefreshableAdResult,\n  AdCreative,\n} from './types';\nimport { ALLOWED_AD_SIZES, ConfigError, MessageType } from './types';\nimport { getConfig, requestAd } from './request';\nimport { createAdElement, updateAdElement } from './ad-renderer';\nimport { sendToBackground } from './messaging';\nimport { generateUUID, validatePlacementContext } from './utils';\nimport { logger } from './logger';\n\nconst managedAdCleanupByContainer = new WeakMap<HTMLElement, () => void>();\n\n// Re-export types and initialization function for consumers\nexport type {\n  SDKConfig,\n  AdOptions,\n  AdResult,\n  Size,\n  Placement,\n  ManagedRefreshableAdOptions,\n  ManagedRefreshableAdResult,\n} from './types';\nexport { ALLOWED_AD_SIZES } from './types';\nexport { MessageType } from './types';\nexport { initializePlayaYield } from './background-handler';\n\nfunction isAllowedAdSize(width: number, height: number): boolean {\n  return ALLOWED_AD_SIZES.some(\n    (size) => size.width === width && size.height === height\n  );\n}\n\nfunction validateAdSize(options: AdOptions): void {\n  if (!options.size || !options.size.width || !options.size.height) {\n    throw new ConfigError('size with width and height is required');\n  }\n\n  if (!isAllowedAdSize(options.size.width, options.size.height)) {\n    throw new ConfigError(\n      'Unsupported ad size. Allowed sizes are 300x250, 320x50, and 320x100.'\n    );\n  }\n}\n\n/**\n * Request and create an ad element\n * Returns a ready-to-append div element containing the ad HTML\n *\n * No initialization needed in content scripts - just call this function!\n * Make sure initializePlayaYield() is called in your background script.\n *\n * @param options Ad request options\n * @returns Promise resolving to AdResult with div element and metadata\n * @throws {ConfigError} If SDK not initialized in background\n * @throws {NetworkError} If ad request fails\n *\n * @example\n * ```ts\n * import { createAd } from '@playanext/playa-yield-sdk';\n *\n * const { element, impressionId } = await createAd({\n *   placement: 'internal',\n *   size: { width: 300, height: 250 },\n *   categories: ['tech', 'gaming']\n * });\n *\n * document.getElementById('ad-slot')!.appendChild(element);\n * ```\n */\nexport async function createAd(options: AdOptions): Promise<AdResult> {\n  // Validate options first\n  if (!options.placement) {\n    throw new ConfigError('placement is required');\n  }\n\n  validateAdSize(options);\n\n  // Validate execution context (placement must match where the code is running)\n  validatePlacementContext(options.placement);\n\n  // Get config from background (verifies SDK is initialized)\n  await getConfig();\n\n  // Request ad from backend (backend uses placement to authorize the request)\n  const creative = await requestAd(options);\n\n  // Create and return ad element\n  const result = createAdElement(creative);\n\n  logger.log('Ad displayed', {\n    placement: options.placement,\n    impressionId: result.impressionId,\n  });\n\n  return result;\n}\n\n/**\n * Create a fully managed refreshable ad\n *\n * The SDK handles:\n * - Appending the ad to your container\n * - Auto-cleanup when the container is removed from DOM\n * - All refresh logic internally\n *\n * @param options Configuration including container element or CSS selector\n * @returns Simple control object with stop() method\n *\n * @example\n * ```ts\n * // Simplest usage - just provide container\n * await createManagedRefreshableAd({\n *   container: '#ad-slot',\n *   placement: 'sidepanel',\n *   size: { width: 300, height: 250 }\n * });\n *\n * // Or with element reference\n * await createManagedRefreshableAd({\n *   container: document.getElementById('ad-slot'),\n *   placement: 'sidepanel',\n *   size: { width: 300, height: 250 }\n * });\n * ```\n */\nexport async function createManagedRefreshableAd(\n  options: ManagedRefreshableAdOptions\n): Promise<ManagedRefreshableAdResult> {\n  // Resolve container\n  const resolvedContainer =\n    typeof options.container === 'string'\n      ? document.querySelector(options.container)\n      : options.container;\n\n  if (!(resolvedContainer instanceof HTMLElement)) {\n    throw new ConfigError(\n      `Container not found: ${\n        typeof options.container === 'string'\n          ? options.container\n          : 'provided element'\n      }`\n    );\n  }\n\n  const container = resolvedContainer;\n\n  // Create the refreshable ad (internal function)\n  // Remove container from options to avoid serialization issues when sending to background\n  const { container: _, ...adOptions } = options;\n  const refreshable = await createRefreshableAdInternal(adOptions);\n\n  const existingCleanup = managedAdCleanupByContainer.get(container);\n  if (existingCleanup) {\n    existingCleanup();\n  }\n\n  Array.from(container.children).forEach((child) => {\n    if (\n      child instanceof HTMLElement &&\n      child.hasAttribute('data-playayield-id')\n    ) {\n      child.remove();\n    }\n  });\n\n  // Append to container\n  container.appendChild(refreshable.element);\n\n  logger.log('Managed ad appended to container', {\n    placement: options.placement,\n    container:\n      typeof options.container === 'string'\n        ? options.container\n        : options.container.id || 'element',\n  });\n\n  // Set up MutationObserver to detect when element is removed from DOM\n  let observer: MutationObserver | null = null;\n\n  const checkIfRemoved = () => {\n    if (!refreshable.element.isConnected) {\n      logger.log('Ad removed from DOM, auto-stopping refresh');\n      refreshable.stop();\n      observer?.disconnect();\n    }\n  };\n\n  observer = new MutationObserver(checkIfRemoved);\n  observer.observe(document.body, {\n    childList: true,\n    subtree: true,\n  });\n\n  // Also check periodically as a fallback\n  const checkInterval = setInterval(checkIfRemoved, 1000);\n\n  const stopManagedAd = () => {\n    refreshable.stop();\n    observer?.disconnect();\n    clearInterval(checkInterval);\n\n    if (managedAdCleanupByContainer.get(container) === stopManagedAd) {\n      managedAdCleanupByContainer.delete(container);\n    }\n  };\n\n  managedAdCleanupByContainer.set(container, stopManagedAd);\n\n  // Return simple control interface\n  return {\n    stop: stopManagedAd,\n    isActive: () => refreshable.isActive(),\n  };\n}\n\n/**\n * Internal version of refreshable ad - not exposed to developers\n * SDK handles all refresh logic internally without callbacks\n * Refresh config is dynamically controlled by backend via AdCreative\n */\nasync function createRefreshableAdInternal(options: AdOptions): Promise<{\n  element: HTMLDivElement;\n  ad: AdCreative;\n  stop: () => void;\n  isActive: () => boolean;\n}> {\n  // Validate options first\n  if (!options.placement) {\n    throw new ConfigError('placement is required');\n  }\n\n  validateAdSize(options);\n\n  // Validate execution context (placement must match where the code is running)\n  validatePlacementContext(options.placement);\n\n  // Get config from background (verifies SDK is initialized)\n  await getConfig();\n\n  // Default constants (fallbacks if backend doesn't provide config)\n  const DEFAULT_REFRESH_INTERVAL_MS = 40000;\n  const DEFAULT_MAX_IMPRESSIONS_PER_SESSION = 29;\n\n  // Generate unique ID for this refreshable ad instance\n  const adInstanceId = generateUUID();\n\n  logger.log('Fetching initial ad...', {\n    placement: options.placement,\n    adInstanceId,\n  });\n\n  // Request first ad without config (we'll get it from the ad response)\n  const initialCreative = await requestAd(options);\n\n  // Extract refresh config from backend response, use defaults as fallback\n  const refreshConfig = initialCreative.refreshConfig;\n  const refreshIntervalMs =\n    refreshConfig?.intervalMs ?? DEFAULT_REFRESH_INTERVAL_MS;\n  const maxImpressionsPerSession =\n    refreshConfig?.maxImpressionsPerSession ??\n    DEFAULT_MAX_IMPRESSIONS_PER_SESSION;\n  const sessionWindowMs = refreshConfig?.sessionWindowMs ?? 30 * 60 * 1000;\n\n  logger.log('Refresh config received from backend', {\n    refreshIntervalMs,\n    maxImpressionsPerSession,\n    sessionWindowMs,\n    backendProvided: !!refreshConfig,\n  });\n\n  // Check session limits with backend-provided max and window\n  const sessionCheck = await sendToBackground<{\n    allowed: boolean;\n    remaining: number;\n    total: number;\n  }>({\n    type: MessageType.UPDATE_SESSION_IMPRESSION,\n    payload: {\n      adId: adInstanceId,\n      maxImpressions: maxImpressionsPerSession,\n      sessionWindowMs,\n    },\n  });\n\n  logger.log('Session check result', {\n    allowed: sessionCheck.data?.allowed,\n    totalImpressions: sessionCheck.data?.total,\n    remaining: sessionCheck.data?.remaining,\n  });\n\n  if (!sessionCheck.data?.allowed) {\n    logger.log('Initial ad blocked: max impressions reached for session');\n    throw new ConfigError(\n      'Cannot display ad: max impressions reached for this session'\n    );\n  }\n\n  logger.log('Initial ad fetched successfully', {\n    impressionId: initialCreative.impressionId,\n    provider: initialCreative.advertiser || 'unknown',\n  });\n\n  // Create the ad element\n  const result = createAdElement(initialCreative);\n  let currentCreative = initialCreative;\n  let isActive = true;\n\n  // Visibility tracking for smart refresh\n  let isTabVisible = !document.hidden;\n  let isAdInViewport = false;\n  let visibilityObserver: IntersectionObserver | null = null;\n\n  // Page Visibility API - track when tab is hidden/minimized\n  const handleVisibilityChange = () => {\n    isTabVisible = !document.hidden;\n    logger.log('Tab visibility changed:', { isTabVisible });\n  };\n  document.addEventListener('visibilitychange', handleVisibilityChange);\n\n  // IntersectionObserver - track when ad is actually in viewport\n  if (typeof IntersectionObserver !== 'undefined') {\n    visibilityObserver = new IntersectionObserver(\n      (entries) => {\n        const entry = entries[0];\n        isAdInViewport = entry.isIntersecting && entry.intersectionRatio >= 0.5;\n        logger.log('Ad viewport visibility:', {\n          isAdInViewport,\n          ratio: entry.intersectionRatio,\n        });\n      },\n      { threshold: [0, 0.5, 1] }\n    );\n    visibilityObserver.observe(result.element);\n  } else {\n    // Fallback: assume visible if observer not available\n    isAdInViewport = true;\n  }\n\n  // Set up the refresh interval using backend-provided config\n  logger.log('Starting refresh timer', {\n    refreshIntervalMs,\n    nextRefreshIn: `${refreshIntervalMs / 1000}s`,\n    source: refreshConfig ? 'backend' : 'default',\n  });\n\n  const timerId = setInterval(async () => {\n    if (!isActive) return;\n\n    // Only refresh if tab is visible AND ad is in viewport\n    if (!isTabVisible || !isAdInViewport) {\n      logger.log('Refresh skipped: not visible', {\n        isTabVisible,\n        isAdInViewport,\n      });\n      return;\n    }\n\n    logger.log('Refresh triggered (visible), fetching new ad...');\n\n    try {\n      // Request new ad and check session limits with backend-provided config\n      const newCreative = await requestAd(options);\n\n      // Extract refresh config from new ad response\n      const newRefreshConfig = newCreative.refreshConfig;\n      const newMaxImpressions =\n        newRefreshConfig?.maxImpressionsPerSession ?? maxImpressionsPerSession;\n      const newSessionWindowMs =\n        newRefreshConfig?.sessionWindowMs ?? sessionWindowMs;\n\n      // Check session limits with possibly updated config\n      const newSessionCheck = await sendToBackground<{\n        allowed: boolean;\n        remaining: number;\n        total: number;\n      }>({\n        type: MessageType.UPDATE_SESSION_IMPRESSION,\n        payload: {\n          adId: adInstanceId,\n          maxImpressions: newMaxImpressions,\n          sessionWindowMs: newSessionWindowMs,\n        },\n      });\n\n      if (!newSessionCheck.data?.allowed) {\n        logger.log(\n          'Refresh blocked: max impressions reached (will retry on next interval)'\n        );\n        return;\n      }\n\n      logger.log('New ad fetched for refresh', {\n        impressionId: newCreative.impressionId,\n        provider: newCreative.advertiser || 'unknown',\n      });\n\n      // Update the existing ad element with new creative\n      updateAdElement(result.element, newCreative);\n      currentCreative = newCreative;\n\n      logger.log('Ad refreshed successfully', {\n        placement: options.placement,\n        impressionId: newCreative.impressionId,\n      });\n    } catch (error) {\n      logger.error('Failed to refresh ad:', error);\n      // Continue trying on next interval - don't stop on transient errors\n    }\n  }, refreshIntervalMs);\n\n  logger.log('Refreshable ad created', {\n    adInstanceId,\n    placement: options.placement,\n    refreshInterval: refreshIntervalMs,\n    maxImpressions: maxImpressionsPerSession,\n    refreshSource: refreshConfig ? 'backend' : 'default',\n  });\n\n  return {\n    element: result.element,\n    ad: currentCreative,\n    stop: () => {\n      if (!isActive) return;\n      isActive = false;\n      clearInterval(timerId);\n\n      // Clean up visibility tracking\n      document.removeEventListener('visibilitychange', handleVisibilityChange);\n      visibilityObserver?.disconnect();\n\n      // Notify background to cleanup session tracking\n      sendToBackground({\n        type: MessageType.STOP_REFRESHABLE_AD,\n        payload: { adId: adInstanceId },\n      }).catch(() => {}); // Ignore errors on cleanup\n\n      logger.log('Refreshable ad stopped', { adInstanceId });\n    },\n    isActive: () => isActive,\n  };\n}\n"]}