admesh-ui-sdk 1.0.37 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/logger.ts","../src/utils/viewabilityTracker.ts","../src/hooks/useViewabilityTracker.ts","../src/components/AdMeshViewabilityTracker.tsx","../src/components/AdMeshCompactCard.tsx","../src/components/AdMeshLayout.tsx","../src/sdk/AdMeshTracker.ts","../src/context/AdMeshContext.ts","../src/utils/extractHeadings.ts","../src/utils/acieApi.ts","../src/utils/pageContextApi.ts","../src/context/AdMeshProvider.tsx","../src/sdk/AdMeshRenderer.tsx","../src/sdk/AdMeshSDK.ts","../src/sdk/WeaveResponseProcessor.ts","../src/hooks/useAdMesh.ts","../src/components/AdMeshFollowup.tsx","../src/components/AdMeshRecommendations.tsx","../src/components/WeaveFallbackRecommendations.tsx","../src/context/WeaveAdFormatContext.tsx","../src/components/AdMeshTailAd.tsx","../src/components/AdMeshLinkTracker.tsx","../../node_modules/classnames/index.js","../src/components/AdMeshBadge.tsx","../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js","../../node_modules/lucide-react/dist/esm/defaultAttributes.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js","../../node_modules/lucide-react/dist/esm/Icon.js","../../node_modules/lucide-react/dist/esm/createLucideIcon.js","../../node_modules/lucide-react/dist/esm/icons/maximize-2.js","../../node_modules/lucide-react/dist/esm/icons/minimize-2.js","../../node_modules/lucide-react/dist/esm/icons/send.js","../../node_modules/lucide-react/dist/esm/icons/thumbs-down.js","../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js","../../node_modules/lucide-react/dist/esm/icons/x.js","../src/utils/styleInjection.ts","../src/hooks/useAdMeshStyles.ts","../src/components/AdMeshIntentAssistant.tsx","../src/utils/streamingEvents.ts","../src/utils/inlineExposureTracker.ts","../src/components/WeaveAdFormatContainer.tsx","../src/hooks/useWeaveAdFormat.ts","../src/index.ts"],"sourcesContent":["/**\n * Logger utility for AdMesh UI SDK\n * Disables all logs in production environment\n */\n\n// Check for production environment\n// Supports both Vite (import.meta.env) and standard Node.js (process.env)\nlet isProduction = false;\ntry {\n // Check for Vite's import.meta.env (only available in ESM modules)\n if (typeof (globalThis as any).importMeta !== 'undefined' && (globalThis as any).importMeta.env?.PROD) {\n isProduction = true;\n }\n} catch (e) {\n // import.meta not available, continue with other checks\n}\n\nif (!isProduction) {\n isProduction = \n (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') ||\n (typeof process !== 'undefined' && process.env.ADMESH_ENV === 'production');\n}\n\nexport const logger = {\n log: (...args: any[]) => {\n if (!isProduction) {\n console.log(...args);\n }\n },\n \n warn: (...args: any[]) => {\n if (!isProduction) {\n console.warn(...args);\n }\n },\n \n error: (...args: any[]) => {\n // Errors are always logged, even in production, as they're critical\n console.error(...args);\n },\n \n info: (...args: any[]) => {\n if (!isProduction) {\n console.info(...args);\n }\n },\n \n debug: (...args: any[]) => {\n if (!isProduction) {\n console.debug(...args);\n }\n },\n};\n\n","/**\n * AdMesh UI SDK - MRC Viewability Tracker Utilities\n * Implements Media Rating Council (MRC) viewability standards\n */\n\nimport type {\n MRCViewabilityStandards,\n DeviceType,\n ViewabilityContextMetrics,\n ViewabilityAnalyticsEvent\n} from '../types/analytics';\nimport { logger } from './logger';\n\n/**\n * Calculate MRC viewability standards based on ad size\n */\nexport function calculateMRCStandards(\n adWidth: number,\n adHeight: number,\n customStandards?: Partial<MRCViewabilityStandards>\n): MRCViewabilityStandards {\n const adPixels = adWidth * adHeight;\n const isLargeAd = adPixels > 242500; // MRC threshold for large ads\n\n const defaults: MRCViewabilityStandards = {\n visibilityThreshold: isLargeAd ? 0.3 : 0.5, // 30% for large, 50% for standard\n minimumDuration: 1000, // 1 second in milliseconds\n isLargeAd\n };\n\n return { ...defaults, ...customStandards };\n}\n\n/**\n * Detect device type based on viewport width\n */\nexport function detectDeviceType(viewportWidth: number): DeviceType {\n if (viewportWidth < 768) return 'mobile';\n if (viewportWidth < 1024) return 'tablet';\n return 'desktop';\n}\n\n/**\n * Calculate visibility percentage of element in viewport\n */\nexport function calculateVisibilityPercentage(element: HTMLElement): number {\n const rect = element.getBoundingClientRect();\n const viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n const viewportWidth = window.innerWidth || document.documentElement.clientWidth;\n\n // Element dimensions\n const elementHeight = rect.height;\n const elementWidth = rect.width;\n\n if (elementHeight === 0 || elementWidth === 0) return 0;\n\n // Calculate visible portion\n const visibleTop = Math.max(0, rect.top);\n const visibleBottom = Math.min(viewportHeight, rect.bottom);\n const visibleLeft = Math.max(0, rect.left);\n const visibleRight = Math.min(viewportWidth, rect.right);\n\n const visibleHeight = Math.max(0, visibleBottom - visibleTop);\n const visibleWidth = Math.max(0, visibleRight - visibleLeft);\n\n const visibleArea = visibleHeight * visibleWidth;\n const totalArea = elementHeight * elementWidth;\n\n return totalArea > 0 ? (visibleArea / totalArea) : 0;\n}\n\n/**\n * Calculate current scroll depth as percentage\n */\nexport function calculateScrollDepth(): number {\n const windowHeight = window.innerHeight;\n const documentHeight = document.documentElement.scrollHeight;\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n\n const scrollableHeight = documentHeight - windowHeight;\n if (scrollableHeight <= 0) return 100;\n\n return Math.min(100, (scrollTop / scrollableHeight) * 100);\n}\n\n/**\n * Get element position on page\n */\nexport function getElementPosition(element: HTMLElement): { top: number; left: number } {\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;\n\n return {\n top: rect.top + scrollTop,\n left: rect.left + scrollLeft\n };\n}\n\n/**\n * Collect context metrics\n */\nexport function collectContextMetrics(element: HTMLElement): ViewabilityContextMetrics {\n const rect = element.getBoundingClientRect();\n const position = getElementPosition(element);\n const viewportWidth = window.innerWidth || document.documentElement.clientWidth;\n const viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n\n // Detect dark mode\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n\n return {\n pageUrl: window.location.href,\n pageTitle: document.title,\n referrer: document.referrer,\n deviceType: detectDeviceType(viewportWidth),\n viewportWidth,\n viewportHeight,\n adWidth: rect.width,\n adHeight: rect.height,\n adPositionTop: position.top,\n adPositionLeft: position.left,\n isDarkMode,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone\n };\n}\n\n/**\n * Generate unique session ID for INTERNAL viewability tracking only.\n * \n * IMPORTANT: This is NOT the main sessionId used for recommendations.\n * This is only used internally by the viewability tracker for tracking\n * viewability events. The main sessionId MUST be provided by the platform\n * and passed to AdMeshProvider and SDK methods.\n */\nexport function generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * Generate unique batch ID\n */\nexport function generateBatchId(): string {\n return `batch_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * Check if ad meets MRC viewability threshold\n */\nexport function meetsViewabilityThreshold(\n visibilityPercentage: number,\n visibleDuration: number,\n standards: MRCViewabilityStandards\n): boolean {\n return (\n visibilityPercentage >= standards.visibilityThreshold &&\n visibleDuration >= standards.minimumDuration\n );\n}\n\n/**\n * Format timestamp to ISO 8601\n */\nexport function formatTimestamp(date: Date = new Date()): string {\n return date.toISOString();\n}\n\n/**\n * Calculate average from array of numbers\n */\nexport function calculateAverage(numbers: number[]): number {\n if (numbers.length === 0) return 0;\n const sum = numbers.reduce((acc, num) => acc + num, 0);\n return sum / numbers.length;\n}\n\n/**\n * Debounce function for performance optimization\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: NodeJS.Timeout | null = null;\n\n return function executedFunction(...args: Parameters<T>) {\n const later = () => {\n timeout = null;\n func(...args);\n };\n\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n}\n\n/**\n * Throttle function for performance optimization\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle: boolean;\n\n return function executedFunction(...args: Parameters<T>) {\n if (!inThrottle) {\n func(...args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\n/**\n * Send analytics event to API\n *\n * NOTE: If apiEndpoint is empty, the event is silently discarded (no error).\n * This allows the SDK to collect analytics without sending them to a backend.\n */\nexport async function sendAnalyticsEvent(\n event: ViewabilityAnalyticsEvent,\n apiEndpoint: string,\n retryAttempts: number = 3,\n retryDelay: number = 1000\n): Promise<boolean> {\n // If no endpoint is configured, silently skip sending\n if (!apiEndpoint || apiEndpoint.trim() === '') {\n return true;\n }\n\n for (let attempt = 0; attempt < retryAttempts; attempt++) {\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(event),\n keepalive: true\n });\n\n if (response.ok) {\n return true;\n }\n\n // Log error details for debugging\n await response.text().catch(() => '');\n } catch (error) {\n // Error caught, will retry\n }\n\n // Wait before retry (exponential backoff)\n if (attempt < retryAttempts - 1) {\n await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));\n }\n }\n\n logger.error('[AdMesh Viewability] Failed to send analytics event');\n return false;\n}\n\n/**\n * Send batched analytics events to API\n *\n * NOTE: If apiEndpoint is empty, the batch is silently discarded (no error).\n * This allows the SDK to collect analytics without sending them to a backend.\n */\nexport async function sendAnalyticsBatch(\n events: ViewabilityAnalyticsEvent[],\n sessionId: string,\n apiEndpoint: string,\n retryAttempts: number = 3,\n retryDelay: number = 1000\n): Promise<boolean> {\n if (events.length === 0) return true;\n\n // If no endpoint is configured, silently skip sending\n if (!apiEndpoint || apiEndpoint.trim() === '') {\n return true;\n }\n\n const batch = {\n batchId: generateBatchId(),\n sessionId,\n createdAt: formatTimestamp(),\n events,\n eventCount: events.length\n };\n\n for (let attempt = 0; attempt < retryAttempts; attempt++) {\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(batch),\n keepalive: true\n });\n\n if (response.ok) {\n return true;\n }\n\n // Log error details for debugging\n await response.text().catch(() => '');\n } catch (error) {\n // Error caught, will retry\n }\n\n // Wait before retry (exponential backoff)\n if (attempt < retryAttempts - 1) {\n await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));\n }\n }\n\n logger.error('[AdMesh Viewability] Failed to send analytics batch');\n return false;\n}\n\n/**\n * Sanitize URL to remove PII (query parameters, fragments)\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n // Remove query parameters and hash\n return `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;\n } catch {\n return url;\n }\n}\n\n/**\n * Check if element is in viewport\n */\nexport function isElementInViewport(element: HTMLElement): boolean {\n const rect = element.getBoundingClientRect();\n return (\n rect.top < (window.innerHeight || document.documentElement.clientHeight) &&\n rect.bottom > 0 &&\n rect.left < (window.innerWidth || document.documentElement.clientWidth) &&\n rect.right > 0\n );\n}\n","/**\n * AdMesh UI SDK - MRC Viewability Tracker Hook\n * React hook for tracking ad viewability according to MRC standards\n */\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { logger } from '../utils/logger';\nimport type {\n ViewabilityTrackerConfig,\n ViewabilityTrackerState,\n ViewabilityAnalyticsEvent,\n ViewabilityEventType,\n MRCViewabilityStandards\n} from '../types/analytics';\nimport {\n calculateMRCStandards,\n calculateVisibilityPercentage,\n calculateScrollDepth,\n collectContextMetrics,\n generateSessionId,\n meetsViewabilityThreshold,\n formatTimestamp,\n calculateAverage,\n throttle\n} from '../utils/viewabilityTracker';\n\n// Default configuration\nconst DEFAULT_CONFIG: ViewabilityTrackerConfig = {\n enabled: true,\n // Analytics endpoint disabled - no analytics will be sent\n apiEndpoint: '', // Empty string disables analytics sending\n enableBatching: false, // Disabled since no endpoint\n batchSize: 10,\n batchTimeout: 5000, // 5 seconds\n debug: false,\n enableRetry: false,\n maxRetries: 3,\n retryDelay: 1000\n};\n\n// Global config that can be set by consuming application\nlet globalConfig: ViewabilityTrackerConfig = DEFAULT_CONFIG;\n\n// TEMPORARY: Global flag to disable all analytics sending\n// Set this to true to prevent any viewability analytics from being sent to the backend\n// This is a temporary measure and can be easily reverted by setting to false\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nlet ANALYTICS_DISABLED = false;\n\nexport const setViewabilityTrackerConfig = (config: Partial<ViewabilityTrackerConfig>) => {\n globalConfig = { ...globalConfig, ...config };\n};\n\n/**\n * TEMPORARY: Disable/enable all viewability analytics sending\n * @param disabled - Set to true to disable analytics, false to enable\n *\n * Usage:\n * disableViewabilityAnalytics(true); // Disable all analytics\n * disableViewabilityAnalytics(false); // Re-enable analytics\n */\nexport const disableViewabilityAnalytics = (disabled: boolean) => {\n ANALYTICS_DISABLED = disabled;\n if (disabled) {\n logger.warn('[AdMesh Viewability] Analytics sending is DISABLED - no data will be sent to backend');\n } else {\n logger.log('[AdMesh Viewability] Analytics sending is ENABLED');\n }\n};\n\ninterface UseViewabilityTrackerProps {\n /** Product ID */\n productId?: string;\n /** Offer ID */\n offerId?: string;\n /** Agent ID */\n agentId?: string;\n /** Recommendation ID (from recommendations collection) */\n recommendationId: string;\n /** HTML element to track */\n elementRef: React.RefObject<HTMLElement>;\n /** Custom configuration */\n config?: Partial<ViewabilityTrackerConfig>;\n}\n\nexport function useViewabilityTracker({\n productId,\n offerId,\n agentId,\n recommendationId,\n elementRef,\n config: customConfig\n}: UseViewabilityTrackerProps): ViewabilityTrackerState {\n const config = { ...globalConfig, ...customConfig };\n\n // Session ID (persists for component lifetime)\n const sessionId = useRef(generateSessionId());\n\n // State\n const [state, setState] = useState<ViewabilityTrackerState>({\n isVisible: false,\n isViewable: false,\n visibilityPercentage: 0,\n timeMetrics: {\n loadedAt: formatTimestamp(),\n totalVisibleDuration: 0,\n totalViewableDuration: 0,\n totalHoverDuration: 0,\n totalFocusDuration: 0\n },\n engagementMetrics: {\n currentScrollDepth: 0,\n viewportEnterCount: 0,\n viewportExitCount: 0,\n hoverCount: 0,\n wasClicked: false,\n maxVisibilityPercentage: 0,\n averageVisibilityPercentage: 0\n },\n isTracking: config.enabled\n });\n\n // Refs for tracking\n const mrcStandards = useRef<MRCViewabilityStandards | null>(null);\n const visibilityStartTime = useRef<number | null>(null);\n const viewableStartTime = useRef<number | null>(null);\n const hoverStartTime = useRef<number | null>(null);\n const focusStartTime = useRef<number | null>(null);\n const visibilityPercentages = useRef<number[]>([]);\n const eventBatch = useRef<ViewabilityAnalyticsEvent[]>([]);\n const batchTimeout = useRef<NodeJS.Timeout | null>(null);\n\n // Log helper\n const log = useCallback((message: string) => {\n if (config.debug) {\n logger.log(`[AdMesh Viewability] ${message}`);\n }\n }, [config.debug]);\n\n // Send event (analytics disabled - no events sent to backend)\n // Viewability tracking still works for exposure pixels (handled separately)\n const sendEvent = useCallback(async (eventType: ViewabilityEventType, additionalData?: Record<string, unknown>) => {\n if (!config.enabled || ANALYTICS_DISABLED || !elementRef.current || !mrcStandards.current) return;\n\n // Analytics disabled - no events sent to backend\n // Viewability tracking still works internally for exposure pixel firing\n log(`Analytics disabled - skipping event: ${eventType}`);\n \n // Call custom callback if provided (for local tracking)\n if (config.onEvent) {\n const contextMetrics = collectContextMetrics(elementRef.current);\n const event: ViewabilityAnalyticsEvent = {\n eventType,\n timestamp: formatTimestamp(),\n sessionId: sessionId.current,\n productId,\n offerId,\n agentId,\n recommendationId,\n timeMetrics: state.timeMetrics,\n engagementMetrics: state.engagementMetrics,\n contextMetrics,\n mrcStandards: mrcStandards.current,\n isViewable: state.isViewable,\n metadata: additionalData\n };\n config.onEvent(event);\n }\n }, [config, productId, offerId, agentId, recommendationId, elementRef, state, log]);\n\n // Flush event batch (disabled - analytics not sent)\n const flushBatch = useCallback(async () => {\n if (eventBatch.current.length === 0) return;\n\n // Analytics disabled - clear batch without sending\n log('Analytics disabled - clearing batch without sending');\n eventBatch.current = [];\n if (batchTimeout.current) {\n clearTimeout(batchTimeout.current);\n batchTimeout.current = null;\n }\n return;\n }, [log]);\n\n // Update visibility\n const updateVisibility = useCallback(throttle(() => {\n if (!elementRef.current) return;\n\n const visibilityPercentage = calculateVisibilityPercentage(elementRef.current);\n const now = Date.now();\n const loadTime = new Date(state.timeMetrics.loadedAt).getTime();\n\n setState(prev => {\n const newState = { ...prev };\n\n // Track visibility percentages for average calculation\n if (visibilityPercentage > 0) {\n visibilityPercentages.current.push(visibilityPercentage);\n }\n\n // Update visibility state\n const wasVisible = prev.isVisible;\n const isNowVisible = visibilityPercentage > 0;\n\n if (isNowVisible && !wasVisible) {\n // Became visible\n visibilityStartTime.current = now;\n newState.engagementMetrics.viewportEnterCount++;\n\n if (!newState.timeMetrics.timeToFirstVisible) {\n newState.timeMetrics.timeToFirstVisible = now - loadTime;\n newState.engagementMetrics.scrollDepthAtFirstVisible = calculateScrollDepth();\n sendEvent('ad_visible');\n }\n } else if (!isNowVisible && wasVisible) {\n // Became hidden\n if (visibilityStartTime.current) {\n const visibleDuration = now - visibilityStartTime.current;\n newState.timeMetrics.totalVisibleDuration += visibleDuration;\n visibilityStartTime.current = null;\n }\n newState.engagementMetrics.viewportExitCount++;\n sendEvent('ad_hidden');\n } else if (isNowVisible && wasVisible && visibilityStartTime.current) {\n // Still visible, update duration\n const visibleDuration = now - visibilityStartTime.current;\n newState.timeMetrics.totalVisibleDuration += visibleDuration;\n visibilityStartTime.current = now;\n }\n\n newState.isVisible = isNowVisible;\n newState.visibilityPercentage = visibilityPercentage;\n\n // Update max visibility\n if (visibilityPercentage > newState.engagementMetrics.maxVisibilityPercentage) {\n newState.engagementMetrics.maxVisibilityPercentage = visibilityPercentage;\n }\n\n // Update average visibility\n if (visibilityPercentages.current.length > 0) {\n newState.engagementMetrics.averageVisibilityPercentage = calculateAverage(visibilityPercentages.current);\n }\n\n // Check MRC viewability threshold\n if (mrcStandards.current) {\n const wasViewable = prev.isViewable;\n const isNowViewable = meetsViewabilityThreshold(\n visibilityPercentage,\n newState.timeMetrics.totalVisibleDuration,\n mrcStandards.current\n );\n\n if (isNowViewable && !wasViewable) {\n // Met viewability threshold\n newState.isViewable = true;\n newState.timeMetrics.timeToViewable = now - loadTime;\n viewableStartTime.current = now;\n sendEvent('ad_viewable');\n } else if (isNowViewable && wasViewable && viewableStartTime.current) {\n // Still viewable, update duration\n const viewableDuration = now - viewableStartTime.current;\n newState.timeMetrics.totalViewableDuration += viewableDuration;\n viewableStartTime.current = now;\n }\n }\n\n // Update scroll depth\n newState.engagementMetrics.currentScrollDepth = calculateScrollDepth();\n\n return newState;\n });\n }, 100), [elementRef, state.timeMetrics.loadedAt, sendEvent]);\n\n // Initialize MRC standards\n useEffect(() => {\n if (!elementRef.current) return;\n\n const rect = elementRef.current.getBoundingClientRect();\n mrcStandards.current = calculateMRCStandards(rect.width, rect.height, config.mrcStandards);\n\n log('Initialized MRC standards');\n sendEvent('ad_loaded');\n }, [elementRef, config.mrcStandards, log, sendEvent]);\n\n // Set up Intersection Observer\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach(() => {\n updateVisibility();\n });\n },\n {\n threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],\n rootMargin: '0px'\n }\n );\n\n observer.observe(elementRef.current);\n\n return () => {\n observer.disconnect();\n };\n }, [config.enabled, elementRef, updateVisibility]);\n\n // Track scroll events\n useEffect(() => {\n if (!config.enabled) return;\n\n const handleScroll = throttle(() => {\n updateVisibility();\n }, 100);\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, [config.enabled, updateVisibility]);\n\n // Track hover events\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const element = elementRef.current;\n\n const handleMouseEnter = () => {\n hoverStartTime.current = Date.now();\n setState(prev => ({\n ...prev,\n engagementMetrics: {\n ...prev.engagementMetrics,\n hoverCount: prev.engagementMetrics.hoverCount + 1\n }\n }));\n sendEvent('ad_hover_start');\n };\n\n const handleMouseLeave = () => {\n if (hoverStartTime.current) {\n const hoverDuration = Date.now() - hoverStartTime.current;\n setState(prev => ({\n ...prev,\n timeMetrics: {\n ...prev.timeMetrics,\n totalHoverDuration: prev.timeMetrics.totalHoverDuration + hoverDuration\n }\n }));\n hoverStartTime.current = null;\n sendEvent('ad_hover_end', { hoverDuration });\n }\n };\n\n element.addEventListener('mouseenter', handleMouseEnter);\n element.addEventListener('mouseleave', handleMouseLeave);\n\n return () => {\n element.removeEventListener('mouseenter', handleMouseEnter);\n element.removeEventListener('mouseleave', handleMouseLeave);\n };\n }, [config.enabled, elementRef, sendEvent]);\n\n // Track focus events\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const element = elementRef.current;\n\n const handleFocus = () => {\n focusStartTime.current = Date.now();\n sendEvent('ad_focus');\n };\n\n const handleBlur = () => {\n if (focusStartTime.current) {\n const focusDuration = Date.now() - focusStartTime.current;\n setState(prev => ({\n ...prev,\n timeMetrics: {\n ...prev.timeMetrics,\n totalFocusDuration: prev.timeMetrics.totalFocusDuration + focusDuration\n }\n }));\n focusStartTime.current = null;\n sendEvent('ad_blur', { focusDuration });\n }\n };\n\n element.addEventListener('focus', handleFocus);\n element.addEventListener('blur', handleBlur);\n\n return () => {\n element.removeEventListener('focus', handleFocus);\n element.removeEventListener('blur', handleBlur);\n };\n }, [config.enabled, elementRef, sendEvent]);\n\n // Track click events\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const element = elementRef.current;\n\n const handleClick = () => {\n setState(prev => ({\n ...prev,\n engagementMetrics: {\n ...prev.engagementMetrics,\n wasClicked: true\n }\n }));\n sendEvent('ad_click');\n };\n\n element.addEventListener('click', handleClick);\n\n return () => {\n element.removeEventListener('click', handleClick);\n };\n }, [config.enabled, elementRef, sendEvent]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n // Calculate session duration\n const now = Date.now();\n const loadTime = new Date(state.timeMetrics.loadedAt).getTime();\n const sessionDuration = now - loadTime;\n\n setState(prev => ({\n ...prev,\n timeMetrics: {\n ...prev.timeMetrics,\n sessionDuration\n }\n }));\n\n // Send final event\n sendEvent('ad_unloaded', { sessionDuration });\n\n // Flush any remaining batched events\n flushBatch();\n };\n }, []);\n\n return state;\n}\n","/**\n * AdMesh Viewability Tracker Component\n * Wraps any ad component with MRC viewability tracking\n */\n\nimport { useRef, useEffect, type CSSProperties, type FC, type ReactNode, type RefObject } from 'react';\nimport { logger } from '../utils/logger';\nimport { useViewabilityTracker } from '../hooks/useViewabilityTracker';\nimport type { ViewabilityTrackerConfig } from '../types/analytics';\n\nexport interface AdMeshViewabilityTrackerProps {\n /** Product ID */\n productId?: string;\n /** Offer ID */\n offerId?: string;\n /** Agent ID */\n agentId?: string;\n /** Recommendation ID (for exposure tracking) */\n recommendationId: string;\n /** Exposure URL (for MRC-compliant exposure pixel firing) */\n exposureUrl?: string;\n /** Session ID (for exposure tracking) */\n sessionId?: string;\n /** Whether to fire exposure URL when ad becomes viewable (defaults to true) */\n triggerExposureUrl?: boolean;\n /** Children to wrap with viewability tracking */\n children: ReactNode;\n /** Custom viewability tracker configuration */\n config?: Partial<ViewabilityTrackerConfig>;\n /** CSS class name */\n className?: string;\n /** Inline styles */\n style?: CSSProperties;\n /** Callback when viewability state changes */\n onViewabilityChange?: (isViewable: boolean) => void;\n /** Callback when ad becomes visible */\n onVisible?: () => void;\n /** Callback when ad becomes viewable (meets MRC threshold) */\n onViewable?: () => void;\n /** Callback when ad is clicked */\n onClick?: () => void;\n}\n\n/**\n * AdMeshViewabilityTracker Component\n * \n * Wraps ad components with comprehensive MRC viewability tracking.\n * Automatically tracks:\n * - Viewability (50% visible for 1 second)\n * - Time metrics (time to viewable, total visible duration, etc.)\n * - Engagement metrics (hover, focus, clicks, scroll depth)\n * - Context metrics (device type, viewport size, ad position)\n * \n * @example\n * ```tsx\n * <AdMeshViewabilityTracker\n * recommendationId=\"rec_123\"\n * productId=\"prod_456\"\n * offerId=\"offer_789\"\n * onViewable={() => logger.log('Ad is viewable!')}\n * >\n * <YourAdComponent />\n * </AdMeshViewabilityTracker>\n * ```\n */\nexport const AdMeshViewabilityTracker: FC<AdMeshViewabilityTrackerProps> = ({\n productId,\n offerId,\n agentId,\n recommendationId,\n exposureUrl,\n sessionId,\n triggerExposureUrl = true,\n children,\n config,\n className,\n style,\n onViewabilityChange,\n onVisible,\n onViewable,\n onClick\n}) => {\n const elementRef = useRef<HTMLElement>(null);\n const exposureFired = useRef(false);\n\n // Use viewability tracker hook\n const viewabilityState = useViewabilityTracker({\n productId,\n offerId,\n agentId,\n recommendationId,\n elementRef: elementRef as RefObject<HTMLElement>,\n config\n });\n\n // Track viewability changes and fire exposure pixel\n const previousViewable = useRef(viewabilityState.isViewable);\n\n useEffect(() => {\n exposureFired.current = false;\n previousViewable.current = false;\n }, [exposureUrl, recommendationId, sessionId]);\n\n useEffect(() => {\n if (viewabilityState.isViewable !== previousViewable.current) {\n previousViewable.current = viewabilityState.isViewable;\n\n if (onViewabilityChange) {\n onViewabilityChange(viewabilityState.isViewable);\n }\n\n if (viewabilityState.isViewable && onViewable) {\n onViewable();\n }\n\n // Fire exposure pixel when ad becomes viewable (MRC-compliant)\n // Only fire if we have the required data and haven't fired yet\n if (viewabilityState.isViewable && !exposureFired.current && triggerExposureUrl) {\n logger.log('[AdMeshViewabilityTracker] 🎯 Ad is viewable, checking exposure pixel requirements:', {\n exposureUrl: exposureUrl ? 'present' : 'MISSING',\n sessionId: sessionId ? 'present' : 'MISSING',\n recommendationId\n });\n\n if (exposureUrl && sessionId) {\n exposureFired.current = true;\n\n logger.log('[AdMeshViewabilityTracker] 🔥 Firing exposure pixel:', exposureUrl);\n\n // Fire the exposure pixel using fetch with keepalive\n fetch(exposureUrl, { method: 'GET', keepalive: true })\n .then(() => {\n logger.log('[AdMesh] ✅ Exposure pixel fired successfully');\n })\n .catch((error) => {\n logger.warn('[AdMesh] ⚠️ Failed to fire exposure pixel:', error);\n // Reset flag to allow retry\n exposureFired.current = false;\n });\n } else {\n logger.warn('[AdMeshViewabilityTracker] ⚠️ Cannot fire exposure pixel - missing required data:', {\n hasExposureUrl: !!exposureUrl,\n hasSessionId: !!sessionId\n });\n }\n }\n }\n }, [viewabilityState.isViewable, onViewabilityChange, onViewable, exposureUrl, sessionId, recommendationId, triggerExposureUrl]);\n\n // Track visibility changes\n const previousVisible = useRef(viewabilityState.isVisible);\n \n useEffect(() => {\n if (viewabilityState.isVisible !== previousVisible.current) {\n previousVisible.current = viewabilityState.isVisible;\n \n if (viewabilityState.isVisible && onVisible) {\n onVisible();\n }\n }\n }, [viewabilityState.isVisible, onVisible]);\n\n // Handle click\n const handleClick = () => {\n if (onClick) {\n onClick();\n }\n \n // Allow event to propagate to children\n };\n\n return (\n <div\n ref={elementRef as RefObject<HTMLDivElement>}\n className={className}\n style={style}\n onClick={handleClick}\n data-admesh-viewability-tracker\n data-recommendation-id={recommendationId}\n data-is-viewable={viewabilityState.isViewable}\n data-is-visible={viewabilityState.isVisible}\n data-visibility-percentage={viewabilityState.visibilityPercentage.toFixed(2)}\n >\n {children}\n </div>\n );\n};\n\nAdMeshViewabilityTracker.displayName = 'AdMeshViewabilityTracker';\n","import { useEffect, useRef, useState, type FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { DelegationActivationPayload } from '../types/index';\nimport { AdMeshViewabilityTracker } from './AdMeshViewabilityTracker';\nimport type { AdMeshTailAdProps } from './AdMeshTailAd';\n\nconst isValidUrl = (url: string): boolean => {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n};\n\nconst getDisplayText = (value: unknown): string => {\n if (typeof value === 'string') {\n return value.trim();\n }\n if (typeof value === 'number') {\n return String(value);\n }\n return '';\n};\n\nconst asOptionalString = (value: unknown): string | undefined => {\n const text = getDisplayText(value);\n return text || undefined;\n};\n\nconst getCTALabel = (ctaLabel?: string): string => {\n if (ctaLabel && ctaLabel.trim()) {\n return ctaLabel.trim();\n }\n return '';\n};\n\nconst formatProductPrice = (price: unknown, currency?: string): string => {\n if (price === null || price === undefined || price === '') {\n return '';\n }\n\n if (typeof price === 'number') {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: 2,\n }).format(price);\n } catch {\n return String(price);\n }\n }\n\n return getDisplayText(price);\n};\n\nexport const AdMeshCompactCard: FC<AdMeshTailAdProps> = ({\n recommendations,\n theme,\n className = '',\n style = {},\n sessionId,\n triggerExposureUrl = true,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n}) => {\n if (!recommendations || recommendations.length === 0) {\n logger.log('[AdMesh Compact Tail Ad] No recommendations provided - not rendering');\n return null;\n }\n\n const firstRecommendation = recommendations[0];\n const recommendation = firstRecommendation?.recommendation;\n const creative = recommendation?.creative;\n const tracking = firstRecommendation?.tracking;\n const delegation = firstRecommendation?.delegation;\n\n const recommendationId = firstRecommendation?.recommendation_id || '';\n const productId = recommendation?.offerId || '';\n const brandName = creative?.brand_name || '';\n const headline = creative?.headline || '';\n const description = creative?.description || '';\n const logoUrl = creative?.logo_url || '';\n const clickUrl = tracking?.click_url || creative?.landing_page_url || '';\n const exposureUrl = tracking?.exposure_url || '';\n const disclosure = recommendation?.disclosure || 'Sponsored';\n const relatedProducts = creative?.products || [];\n const visibleProducts = relatedProducts.slice(0, 4);\n const hasProductRail = relatedProducts.length > 1;\n const recommendationFormat = recommendation?.format || 'tail';\n const isBridgeRecommendation = recommendationFormat === 'bridge';\n const hasDelegation = delegation?.available === true;\n const shouldShowDelegationButton = isBridgeRecommendation && hasDelegation;\n const delegationBrandName = delegation?.brand_name || brandName;\n const delegationCtaText = 'Talk to Agent';\n const ctaLabel = getCTALabel(creative?.cta_text);\n const shouldShowPrimaryCta = !hasProductRail && !!ctaLabel && !!clickUrl;\n\n if (!brandName && !headline && !description) {\n logger.log('[AdMesh Compact Tail Ad] No valid recommendation data provided - not rendering', {\n recommendationId,\n });\n return null;\n }\n\n const compactTitle = headline && headline !== brandName ? headline : brandName;\n const compactSummary = description;\n const normalizedBrandName = brandName.trim().toLowerCase();\n const normalizedCompactTitle = compactTitle.trim().toLowerCase();\n const shouldShowBrandEyebrow = Boolean(brandName) && normalizedBrandName !== normalizedCompactTitle;\n\n const requestDefaultConsent = (): boolean => {\n return true;\n };\n\n const [showConsentPrompt, setShowConsentPrompt] = useState(false);\n const consentResolverRef = useRef<((value: boolean) => void) | null>(null);\n\n useEffect(() => {\n return () => {\n if (consentResolverRef.current) {\n consentResolverRef.current(false);\n consentResolverRef.current = null;\n }\n };\n }, []);\n\n const resolveConsentPrompt = (value: boolean) => {\n consentResolverRef.current?.(value);\n consentResolverRef.current = null;\n setShowConsentPrompt(false);\n };\n\n const requestConsent = async (): Promise<boolean> => {\n if (onDelegationConsent) {\n return await onDelegationConsent(firstRecommendation);\n }\n if (!requestDefaultConsent()) {\n return false;\n }\n return await new Promise<boolean>((resolve) => {\n consentResolverRef.current = resolve;\n setShowConsentPrompt(true);\n });\n };\n\n const handleContainerClick = (source: string, e?: React.MouseEvent) => {\n if (e) {\n e.stopPropagation();\n }\n\n if (typeof window !== 'undefined' && (window as any).admeshTracker) {\n (window as any).admeshTracker.trackClick({\n recommendationId,\n productId,\n clickUrl,\n source,\n }).catch(() => {\n logger.error(`[AdMesh] Failed to track ${source} click`);\n });\n }\n };\n\n const handleCardClick = () => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n handleContainerClick('compact_tail_ad_card');\n if (typeof window !== 'undefined') {\n window.open(clickUrl, '_blank', 'noopener,noreferrer');\n }\n };\n\n const handleCardKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleCardClick();\n }\n };\n\n const trackDelegationEngagement = async () => {\n if (!(recommendationId && sessionId)) {\n return;\n }\n\n try {\n const apiBaseUrl =\n (typeof window !== 'undefined' && (window as any).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n\n const response = await fetch(`${apiBaseUrl}/click/bridge-engagement`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n recommendation_id: recommendationId,\n session_id: sessionId,\n is_test: false,\n }),\n });\n\n if (!response.ok) {\n logger.warn('[AdMesh Compact Tail Ad] Delegation engagement tracking failed:', response.statusText);\n }\n } catch (error) {\n logger.error('[AdMesh Compact Tail Ad] Error tracking delegation engagement:', error);\n }\n };\n\n const handleDelegationClick = async (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (!firstRecommendation || !shouldShowDelegationButton) {\n return;\n }\n\n handleContainerClick('compact_tail_ad_delegation_cta');\n await trackDelegationEngagement();\n\n const consentGranted = await requestConsent();\n if (!consentGranted) {\n return;\n }\n\n const delegationPayload: DelegationActivationPayload | null =\n delegation?.available\n ? {\n recommendation_id: firstRecommendation.recommendation_id,\n brand_id: asOptionalString(delegation.brand_id),\n brand_name: asOptionalString(delegation.brand_name || creative?.brand_name),\n eligibility_reason: asOptionalString(delegation.eligibility_reason),\n delegate_reason: asOptionalString(delegation.delegate_reason),\n session_goal: asOptionalString(delegation.session_goal),\n desired_outcome_type: delegation.desired_outcome_type,\n required_user_inputs: Array.isArray(delegation.required_user_inputs)\n ? delegation.required_user_inputs.filter((value): value is string => typeof value === 'string')\n : [],\n required_consent_types: Array.isArray(delegation.required_consent_types)\n ? delegation.required_consent_types.filter((value): value is string => typeof value === 'string')\n : [],\n success_outcome: asOptionalString(delegation.success_outcome),\n fallback_message: asOptionalString(delegation.fallback_message),\n session_mode: asOptionalString(delegation.session_mode),\n status: asOptionalString(delegation.status),\n capabilities: delegation.capabilities || [],\n allowed_data_types: delegation.allowed_data_types || [],\n consent_requirements: delegation.consent_requirements || [],\n auth_model: asOptionalString(delegation.auth_model),\n handoff_protocol:\n delegation.handoff_protocol && typeof delegation.handoff_protocol === 'object'\n ? delegation.handoff_protocol\n : undefined,\n supported_actions: delegation.supported_actions || [],\n metadata:\n delegation.metadata && typeof delegation.metadata === 'object'\n ? delegation.metadata\n : undefined,\n platform_response: firstRecommendation,\n }\n : null;\n\n if (onDelegationActivated && delegationPayload) {\n await onDelegationActivated(delegationPayload);\n return;\n }\n\n if (onStartDelegation) {\n await onStartDelegation(firstRecommendation);\n return;\n }\n\n };\n\n const [logoError, setLogoError] = useState(false);\n\n const isDarkMode =\n theme?.mode === 'dark' ||\n (typeof window !== 'undefined' &&\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches);\n\n const cardBackground =\n theme?.surfaceColor ||\n theme?.components?.card?.backgroundColor ||\n (isDarkMode ? '#111827' : '#ffffff');\n const cardBorder =\n theme?.borderColor ||\n theme?.components?.card?.borderColor ||\n (isDarkMode ? 'rgba(255, 255, 255, 0.10)' : 'rgba(15, 23, 42, 0.08)');\n const cardShadow =\n theme?.shadows?.medium ||\n theme?.components?.card?.boxShadow ||\n (isDarkMode\n ? '0 8px 18px rgba(0, 0, 0, 0.28)'\n : '0 8px 18px rgba(15, 23, 42, 0.08)');\n const accentColor = '#2563eb';\n const mutedText = isDarkMode ? '#9ca3af' : '#6b7280';\n const bodyText = isDarkMode ? '#e5e7eb' : '#374151';\n const titleText = isDarkMode ? '#f9fafb' : '#0f172a';\n const railCardBackground = isDarkMode ? 'rgba(255, 255, 255, 0.04)' : '#f8fafc';\n const textColumnOffset = '50px';\n const footerAction =\n shouldShowDelegationButton || shouldShowPrimaryCta ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flexWrap: 'wrap' }}>\n {shouldShowDelegationButton ? (\n <button\n type=\"button\"\n onClick={handleDelegationClick}\n style={{\n background: 'none',\n border: 'none',\n padding: 0,\n color: accentColor,\n fontSize: '0.68rem',\n fontWeight: 500,\n cursor: 'pointer',\n textDecoration: 'none',\n }}\n >\n {delegationCtaText}\n </button>\n ) : null}\n {shouldShowPrimaryCta ? (\n <a\n href={clickUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(e) => handleContainerClick('compact_tail_ad_cta', e)}\n style={{\n color: accentColor,\n fontSize: '0.68rem',\n fontWeight: 600,\n textDecoration: 'none',\n }}\n >\n {ctaLabel}\n </a>\n ) : null}\n </div>\n ) : null;\n\n return (\n <AdMeshViewabilityTracker\n productId={productId}\n recommendationId={recommendationId}\n exposureUrl={exposureUrl}\n sessionId={sessionId}\n triggerExposureUrl={triggerExposureUrl}\n className={`admesh-compact-tail-ad ${className}`}\n style={{\n fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n ...style,\n }}\n >\n <style>{`\n .admesh-compact-line-clamp-1 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 1;\n }\n\n .admesh-compact-line-clamp-2 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n }\n\n .admesh-compact-tail-scroll {\n -ms-overflow-style: none;\n scrollbar-width: none;\n }\n\n .admesh-compact-tail-scroll::-webkit-scrollbar {\n display: none;\n }\n `}</style>\n <div\n role={!hasProductRail && clickUrl ? 'link' : undefined}\n tabIndex={!hasProductRail && clickUrl ? 0 : undefined}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '10px',\n padding: '12px',\n borderRadius: theme?.borderRadius || theme?.components?.card?.borderRadius || '14px',\n border: `1px solid ${cardBorder}`,\n background: cardBackground,\n boxShadow: cardShadow,\n minWidth: 0,\n cursor: !hasProductRail && clickUrl ? 'pointer' : undefined,\n }}\n onClick={handleCardClick}\n onKeyDown={handleCardKeyDown}\n >\n <div style={{ display: 'flex', gap: '10px', alignItems: 'flex-start', minWidth: 0 }}>\n <div\n style={{\n width: '40px',\n height: '40px',\n borderRadius: '10px',\n flexShrink: 0,\n overflow: 'hidden',\n background: isDarkMode ? '#1f2937' : '#eff6ff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {!logoError && logoUrl && isValidUrl(logoUrl) ? (\n <img\n src={logoUrl}\n alt={`${brandName} logo`}\n style={{\n width: '100%',\n height: '100%',\n objectFit: 'contain',\n padding: '6px',\n background: '#ffffff',\n }}\n onError={() => setLogoError(true)}\n />\n ) : (\n <span style={{ fontSize: '0.85rem', fontWeight: 700, color: mutedText }}>\n {(brandName || 'A').charAt(0).toUpperCase()}\n </span>\n )}\n </div>\n\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n marginBottom: '4px',\n }}\n >\n <div className=\"admesh-compact-line-clamp-1\" style={{ fontSize: '0.68rem', color: mutedText }}>\n {shouldShowBrandEyebrow ? brandName : ''}\n </div>\n <div\n style={{\n flexShrink: 0,\n fontSize: '0.62rem',\n color: mutedText,\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n }}\n >\n {disclosure}\n </div>\n </div>\n\n {!hasProductRail && (\n <div\n className=\"admesh-compact-line-clamp-2\"\n style={{\n fontSize: '0.84rem',\n lineHeight: 1.3,\n fontWeight: 700,\n color: titleText,\n marginBottom: '4px',\n }}\n title={compactTitle}\n >\n {compactTitle}\n </div>\n )}\n\n {compactSummary && (\n <p\n className=\"admesh-compact-line-clamp-2\"\n style={{\n margin: 0,\n fontSize: '0.7rem',\n lineHeight: 1.35,\n color: bodyText,\n }}\n title={compactSummary}\n >\n {compactSummary}\n </p>\n )}\n </div>\n </div>\n\n {hasProductRail && (\n <div\n className=\"admesh-compact-tail-scroll\"\n style={{\n display: 'flex',\n gap: '8px',\n overflowX: 'auto',\n paddingBottom: '2px',\n }}\n >\n {visibleProducts.map((product) => {\n const productName = getDisplayText(product.product_name) || 'Product';\n const productLink =\n getDisplayText(product.product_link) ||\n getDisplayText(product.product_url) ||\n clickUrl ||\n '#';\n const productPrice = formatProductPrice(product.product_price, product.product_currency);\n const productImageUrl = getDisplayText(product.product_image_url);\n const displayImage = productImageUrl && isValidUrl(productImageUrl) ? productImageUrl : '';\n const hasProductLink = productLink !== '#';\n\n return (\n <a\n key={product.product_id || `${recommendationId}-${productName}`}\n href={productLink}\n target={hasProductLink ? '_blank' : undefined}\n rel={hasProductLink ? 'noopener noreferrer' : undefined}\n onClick={(e) => handleContainerClick(`compact_tail_ad_product_${product.product_id || 'item'}`, e)}\n style={{\n minWidth: '220px',\n maxWidth: '220px',\n display: 'block',\n textDecoration: 'none',\n color: 'inherit',\n border: `1px solid ${cardBorder}`,\n borderRadius: '12px',\n background: railCardBackground,\n padding: '8px',\n flexShrink: 0,\n }}\n >\n <div style={{ display: 'flex', gap: '8px', alignItems: 'flex-start' }}>\n <div\n style={{\n width: '34px',\n height: '34px',\n borderRadius: '8px',\n overflow: 'hidden',\n flexShrink: 0,\n background: isDarkMode ? '#374151' : '#e5e7eb',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: mutedText,\n fontSize: '0.75rem',\n fontWeight: 700,\n }}\n >\n {displayImage ? (\n <img src={displayImage} alt={productName} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />\n ) : (\n productName.charAt(0).toUpperCase()\n )}\n </div>\n\n <div style={{ minWidth: 0, flex: 1 }}>\n <div\n style={{\n fontSize: '0.68rem',\n lineHeight: 1.25,\n fontWeight: 600,\n color: titleText,\n marginBottom: '4px',\n whiteSpace: 'normal',\n wordBreak: 'break-word',\n }}\n title={productName}\n >\n {productName}\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'wrap' }}>\n {productPrice && (\n <span style={{ fontSize: '0.66rem', fontWeight: 700, color: titleText }}>\n {productPrice}\n </span>\n )}\n </div>\n </div>\n </div>\n </a>\n );\n })}\n </div>\n )}\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n flexWrap: 'wrap',\n marginLeft: hasProductRail ? 0 : textColumnOffset,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px', minWidth: 0, flexWrap: 'wrap' }}>\n {footerAction}\n </div>\n\n {hasProductRail && relatedProducts.length > visibleProducts.length ? (\n <span style={{ fontSize: '0.62rem', color: mutedText }}>\n +{relatedProducts.length - visibleProducts.length} more\n </span>\n ) : null}\n </div>\n\n {showConsentPrompt ? (\n <div\n style={{\n marginTop: '2px',\n border: `1px solid ${cardBorder}`,\n borderRadius: '12px',\n background: railCardBackground,\n padding: '12px',\n display: 'flex',\n flexDirection: 'column',\n gap: '10px',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <div\n style={{\n fontSize: '0.65rem',\n fontWeight: 700,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n color: accentColor,\n }}\n >\n Confirm Agent Access\n </div>\n <div style={{ fontSize: '0.74rem', lineHeight: 1.4, color: titleText, fontWeight: 600 }}>\n Allow {delegationBrandName || 'this brand'} to start a delegated session?\n </div>\n <div style={{ fontSize: '0.68rem', lineHeight: 1.45, color: bodyText }}>\n The agent will only use the details you choose to share for this request.\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(false);\n }}\n style={{\n borderRadius: '10px',\n border: `1px solid ${cardBorder}`,\n background: cardBackground,\n color: titleText,\n fontSize: '0.68rem',\n fontWeight: 600,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Not now\n </button>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(true);\n }}\n style={{\n borderRadius: '10px',\n border: 'none',\n background: accentColor,\n color: '#ffffff',\n fontSize: '0.68rem',\n fontWeight: 700,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Allow agent\n </button>\n </div>\n </div>\n ) : null}\n </div>\n </AdMeshViewabilityTracker>\n );\n};\n\nexport default AdMeshCompactCard;\n","import type { FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { AdMeshLayoutProps } from '../types/index';\nimport { AdMeshCompactCard } from './AdMeshCompactCard';\n\nexport const AdMeshLayout: FC<AdMeshLayoutProps> = ({\n recommendations,\n theme,\n className,\n style,\n sessionId,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n}) => {\n const validRecs = recommendations.filter(\n (rec) => rec && typeof rec === 'object' && typeof rec.recommendation_id === 'string' && rec.recommendation_id.length > 0,\n );\n\n // Validate that valid recommendations are provided\n if (!validRecs || validRecs.length === 0) {\n logger.log('[AdMeshLayout] Empty or invalid recommendations array - not rendering anything');\n return null;\n }\n\n logger.log(`[AdMeshLayout] Rendering with ${validRecs.length} valid recommendations`);\n\n // Render based on layout type (default to tail)\n const renderContent = () => {\n if (validRecs.length > 0) {\n const firstRec = validRecs[0];\n const preferredFormat = firstRec.recommendation?.format;\n \n logger.log('[AdMeshLayout] 🔍 Checking format:', {\n preferredFormat,\n recommendationKeys: Object.keys(firstRec || {})\n });\n\n if (preferredFormat === 'product_card' || preferredFormat === 'weave' || preferredFormat === 'bridge') {\n logger.warn(`[AdMeshLayout] ${preferredFormat} format requested, falling back to tail for canonical render payload`);\n }\n }\n\n return (\n <AdMeshCompactCard\n recommendations={validRecs}\n theme={theme}\n sessionId={sessionId}\n onDelegationConsent={onDelegationConsent}\n onDelegationActivated={onDelegationActivated}\n onStartDelegation={onStartDelegation}\n />\n );\n };\n\n return (\n <div\n className={`admesh-layout ${className}`}\n style={{\n fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n ...style\n }}\n >\n {renderContent()}\n </div>\n );\n};\n\nexport default AdMeshLayout;\n","/**\n * AdMesh Tracker\n *\n * Handles MRC-compliant exposure tracking for recommendations\n *\n * MRC Viewability Standards:\n * - Display Ads: 50% of pixels visible for at least 1 continuous second\n * - Large Display Ads (>242,500 pixels): 30% of pixels visible for at least 1 continuous second\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface TrackerConfig {\n apiKey: string;\n debug?: boolean;\n}\n\n/**\n * MRC Viewability threshold configuration\n */\ninterface MRCThreshold {\n visibilityPercentage: number; // 50% for standard ads, 30% for large ads\n minimumDurationMs: number; // 1000ms (1 second)\n}\n\nexport class AdMeshTracker {\n private firedExposures: Set<string> = new Set();\n private debug: boolean = false;\n private mrcThreshold: MRCThreshold = {\n visibilityPercentage: 50,\n minimumDurationMs: 1000\n };\n\n constructor(config: TrackerConfig) {\n this.debug = config.debug || false;\n }\n\n /**\n * Fire an exposure tracking pixel with MRC viewability compliance\n *\n * This method should be called when an ad element becomes viewable according to MRC standards.\n * The caller is responsible for ensuring the ad meets the MRC threshold before calling this method.\n *\n * Prevents duplicate firing for the same ad in the same session.\n *\n * @param exposureUrl - The tracking pixel URL to fire\n * @param recommendationId - The recommendation ID for deduplication\n * @param sessionId - The session ID for deduplication\n */\n fireExposure(exposureUrl: string, recommendationId: string, sessionId: string): void {\n const key = `${sessionId}_${recommendationId}`;\n\n // Prevent duplicate exposures\n if (this.firedExposures.has(key)) {\n if (this.debug) {\n logger.log('[Tracker] Exposure already fired');\n }\n return;\n }\n\n this.firedExposures.add(key);\n\n try {\n // Fire the exposure pixel\n // Note: The caller should ensure MRC compliance before calling this method\n fetch(exposureUrl, { method: 'GET', keepalive: true }).catch(() => {\n if (this.debug) {\n logger.warn('[Tracker] Failed to fire exposure');\n }\n });\n\n if (this.debug) {\n logger.log('[Tracker] Fired MRC-compliant exposure');\n }\n } catch (error) {\n if (this.debug) {\n logger.error('[Tracker] Error firing exposure');\n }\n }\n }\n\n /**\n * Fire an exposure pixel with MRC viewability verification\n *\n * This method monitors an element for MRC viewability compliance before firing the exposure pixel.\n * It uses Intersection Observer API to track visibility and ensures the ad meets the threshold\n * (50% visible for 1 continuous second) before firing.\n *\n * @param exposureUrl - The tracking pixel URL to fire\n * @param recommendationId - The recommendation ID for deduplication\n * @param sessionId - The session ID for deduplication\n * @param element - The DOM element to monitor for viewability\n * @returns Promise that resolves when exposure is fired or timeout occurs\n */\n async fireExposureWithMRCCompliance(\n exposureUrl: string,\n recommendationId: string,\n sessionId: string,\n element: HTMLElement\n ): Promise<void> {\n const key = `${sessionId}_${recommendationId}`;\n\n // Prevent duplicate exposures\n if (this.firedExposures.has(key)) {\n if (this.debug) {\n logger.log('[Tracker] MRC exposure already fired');\n }\n return;\n }\n\n return new Promise((resolve) => {\n let viewableStartTime: number | null = null;\n let timeoutId: NodeJS.Timeout | null = null;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const visibilityPercentage = (entry.intersectionRatio * 100);\n\n if (visibilityPercentage >= this.mrcThreshold.visibilityPercentage) {\n // Ad is visible enough\n if (viewableStartTime === null) {\n // Start tracking viewable duration\n viewableStartTime = Date.now();\n\n if (this.debug) {\n logger.log('[Tracker] Ad reached MRC visibility threshold');\n }\n\n // Set timeout to fire exposure after minimum duration\n timeoutId = setTimeout(() => {\n // Fire the exposure pixel\n this.fireExposure(exposureUrl, recommendationId, sessionId);\n observer.disconnect();\n resolve();\n }, this.mrcThreshold.minimumDurationMs);\n }\n } else {\n // Ad visibility dropped below threshold\n if (viewableStartTime !== null) {\n // Reset tracking\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n viewableStartTime = null;\n\n if (this.debug) {\n logger.log('[Tracker] Ad visibility dropped below MRC threshold');\n }\n }\n }\n });\n },\n {\n threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],\n rootMargin: '0px'\n }\n );\n\n observer.observe(element);\n\n // Cleanup on unmount or after reasonable timeout\n const maxWaitTime = 30000; // 30 seconds max wait\n const cleanupTimeout = setTimeout(() => {\n observer.disconnect();\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n resolve();\n }, maxWaitTime);\n\n // Store cleanup function for manual cleanup if needed\n (element as any).__admeshTrackerCleanup = () => {\n observer.disconnect();\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n clearTimeout(cleanupTimeout);\n };\n });\n }\n\n /**\n * Clear fired exposures (useful for testing or session reset)\n */\n clearFiredExposures(): void {\n this.firedExposures.clear();\n }\n\n /**\n * Get MRC threshold configuration\n */\n getMRCThreshold(): MRCThreshold {\n return { ...this.mrcThreshold };\n }\n\n /**\n * Set custom MRC threshold (for testing or special cases)\n */\n setMRCThreshold(threshold: Partial<MRCThreshold>): void {\n this.mrcThreshold = {\n ...this.mrcThreshold,\n ...threshold\n };\n }\n\n /**\n * Fire exposure pixel for sponsored followup\n * Uses same logic as regular exposure tracking\n * \n * @param exposureUrl - The tracking pixel URL to fire (can use regular exposure_url)\n * @param recommendationId - The recommendation ID for deduplication\n * @param sessionId - The session ID for deduplication\n */\n fireFollowupExposure(\n exposureUrl: string,\n recommendationId: string,\n sessionId: string\n ): void {\n // Reuse existing fireExposure() method\n this.fireExposure(exposureUrl, recommendationId, sessionId);\n }\n\n /**\n * Fire engagement tracking for sponsored followup\n * \n * @param engagementUrl - The engagement tracking URL to fire\n * @param recommendationId - The recommendation ID\n * @param sessionId - The session ID (sent in POST body for analytics joining)\n * @returns Promise that resolves when engagement is fired\n */\n fireFollowupEngagement(\n engagementUrl: string,\n _recommendationId: string,\n sessionId: string\n ): Promise<void> {\n // Use fetch with keepalive and POST method\n // Always resolve the promise even on error to prevent unhandled rejections\n return fetch(engagementUrl, {\n method: 'POST',\n keepalive: true,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ session_id: sessionId })\n }).catch((error) => {\n // Log error silently (only in debug mode) - network errors are expected and shouldn't break the flow\n if (this.debug) {\n logger.warn('[Tracker] Failed to fire followup engagement (non-critical):', error);\n }\n // Return undefined to resolve the promise successfully\n // This prevents the error from propagating to callers\n return undefined;\n }).then(() => {\n // Ensure promise always resolves with void (no return value)\n // This makes the return type consistent: Promise<void>\n });\n }\n}\n","import { createContext, useContext } from 'react';\nimport { AdMeshSDK } from '../sdk/AdMeshSDK';\nimport type { AdMeshTheme, PlatformResponse, ActiveDelegationSession } from '../types/index';\nimport type { Suggestion } from '../components/AdMeshIntentAssistant';\n\n/**\n * Context value provided by AdMeshProvider\n */\nexport interface AdMeshContextValue {\n // SDK instance\n sdk: AdMeshSDK | null;\n\n // Configuration\n apiKey: string;\n sessionId: string;\n theme?: AdMeshTheme;\n\n // Canonical AIP PlatformRequest inputs (optional, passed from frontend)\n language?: string; // User language in BCP 47 format (e.g., \"en-US\")\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string; // Anonymous hashed user ID\n model?: string; // AI model identifier (e.g., \"gpt-4o\")\n messages?: Array<{ role: string; content: string; id?: string }>; // Conversation history\n\n // Tracking state\n processedMessageIds: Set<string>;\n recommendationResults: Map<string, PlatformResponse | null>;\n activeDelegationSession: ActiveDelegationSession | null;\n\n // Suggestion state\n suggestions: Suggestion[];\n isAnalyzingIntent: boolean;\n intentError: string | null;\n\n // Methods\n markMessageAsProcessed: (messageId: string) => void;\n isMessageProcessed: (messageId: string) => boolean;\n setRecommendationResult: (messageId: string, result: PlatformResponse | null) => void;\n getRecommendationResult: (messageId: string) => PlatformResponse | null | undefined;\n hasRecommendationResult: (messageId: string) => boolean;\n setActiveDelegationSession: (session: ActiveDelegationSession | null) => void;\n getActiveDelegationSession: () => ActiveDelegationSession | null;\n hasActiveDelegationSession: () => boolean;\n refreshDelegationActivity: (eventType?: string, metadata?: Record<string, unknown>) => Promise<void>;\n stopDelegationSession: (reason?: string, metadata?: Record<string, unknown>) => Promise<void>;\n retryIntentAnalysis: () => Promise<void>;\n}\n\n/**\n * React Context for AdMesh SDK\n * \n * Provides SDK instance and tracking state to all child components\n */\nexport const AdMeshContext = createContext<AdMeshContextValue | undefined>(\n undefined\n);\n\n/**\n * Hook to access AdMesh context\n * \n * @throws Error if used outside of AdMeshProvider\n * @returns AdMeshContextValue\n */\nexport function useAdMeshContext(): AdMeshContextValue {\n const context = useContext(AdMeshContext);\n \n if (!context) {\n throw new Error(\n 'useAdMeshContext must be used within an <AdMeshProvider>. ' +\n 'Make sure your component is wrapped with <AdMeshProvider>.'\n );\n }\n \n return context;\n}\n","/**\n * Extract headings directly from web pages without external scripts\n * This utility function can be used by anyone who integrates the AdMesh UI SDK\n */\n\nexport interface HeadingsExtractionResult {\n title: string;\n headings: string[];\n article_text?: string;\n url: string;\n domain: string;\n extracted_at: string;\n}\n\nfunction titleFromPath(pathname: string): string {\n const segments = pathname.split('/').filter(Boolean);\n const raw = segments[segments.length - 1] || segments[segments.length - 2] || '';\n const withoutExtension = raw.replace(/\\.[a-z0-9]+$/i, '');\n const cleaned = withoutExtension.replace(/[-_]+/g, ' ').replace(/\\s+/g, ' ').trim();\n return cleaned\n ? cleaned.replace(/\\b\\w/g, (char) => char.toUpperCase())\n : 'This page';\n}\n\n/**\n * Extract headings directly from the current web page\n * Bypasses CSP restrictions by using direct DOM access\n * \n * @returns {HeadingsExtractionResult | null} Object containing title, headings, and metadata\n */\nexport function extractHeadingsDirectly(): HeadingsExtractionResult | null {\n try {\n console.log('[AdMesh] Starting direct headings extraction...');\n \n // Clean and normalize text content\n const cleanText = (text: string) => text.replace(/\\s+/g, \" \").trim();\n\n const getArticleText = () => {\n const selectors = [\n 'article',\n 'main article',\n 'main',\n '[role=\"main\"]',\n '[data-admesh-article]',\n '.article-content',\n '.post-content',\n '.entry-content',\n '.content',\n ];\n\n const ignoredSelector = [\n 'script',\n 'style',\n 'noscript',\n 'svg',\n 'canvas',\n 'iframe',\n 'nav',\n 'header',\n 'footer',\n 'aside',\n '[aria-hidden=\"true\"]',\n '[data-admesh-ignore]',\n '.admesh-publisher-assistant-root',\n '.admesh-publisher-assistant-reactMount',\n '.admesh-publisher-assistant-floating',\n '.admesh-publisher-assistant-inline',\n ].join(',');\n\n const candidates = selectors\n .map((selector) => document.querySelector(selector))\n .filter((element): element is Element => Boolean(element));\n\n const sourceElement = candidates\n .map((element) => {\n const clone = element.cloneNode(true) as Element;\n clone.querySelectorAll(ignoredSelector).forEach((node) => node.remove());\n const text = cleanText(clone.textContent || '');\n return { element, text };\n })\n .filter((candidate) => candidate.text.length >= 200)\n .sort((a, b) => b.text.length - a.text.length)[0]?.element || document.body;\n\n const clone = sourceElement.cloneNode(true) as Element;\n clone.querySelectorAll(ignoredSelector).forEach((node) => node.remove());\n\n const paragraphs = Array.from(clone.querySelectorAll('h1, h2, h3, p, li, blockquote'))\n .map((element) => cleanText(element.textContent || ''))\n .filter((text) => text.length >= 24);\n\n const articleText = paragraphs.length > 0\n ? paragraphs.join('\\n')\n : cleanText(clone.textContent || '');\n\n return articleText.slice(0, 6000);\n };\n \n const fallbackTitle = titleFromPath(window.location.pathname || '/');\n \n // Extract title\n const title = cleanText(document.title || '') || fallbackTitle;\n \n // Extract all headings by selector and combine into single array\n const getAllHeadings = () => {\n const allHeadings: string[] = [];\n \n // Get all heading elements (h1 through h6)\n const headingElements = document.querySelectorAll('h1, h2, h3, h4, h5, h6');\n \n // Convert NodeList to array and extract text\n Array.from(headingElements).forEach(element => {\n const text = cleanText(element.textContent || '');\n if (text.length > 0) {\n allHeadings.push(text);\n }\n });\n \n return allHeadings;\n };\n \n // Extract all headings in desired format\n const headings = getAllHeadings();\n const resolvedHeadings = headings.length > 0 ? headings : [title || fallbackTitle];\n \n // Create the simplified output format\n const result: HeadingsExtractionResult = {\n title: title,\n headings: resolvedHeadings,\n article_text: getArticleText(),\n url: window.location.href,\n domain: window.location.hostname,\n extracted_at: new Date().toISOString()\n };\n \n console.log('[AdMesh] Extracted headings:', {\n title: result.title,\n headingsCount: result.headings.length,\n articleTextLength: result.article_text?.length || 0,\n domain: result.domain\n });\n \n return result;\n } catch (error) {\n console.error('[AdMesh] Error in direct headings extraction:', error);\n return null;\n }\n}\n","/**\n * ACIE (AdMesh Commercial Intent Engine) API integration\n * Provides intent analysis functionality for the AdMesh UI SDK\n */\n\nimport type { AdMeshSDKConfig } from '../sdk/AdMeshSDK';\nimport type { Suggestion } from '../components/AdMeshIntentAssistant';\nimport type { PlatformResponse } from '../types/index';\n\nexport interface CommercialIntentRequest {\n url: string;\n title?: string;\n headings?: string[];\n article_text?: string;\n domain: string;\n article_slug?: string;\n agent_id?: string;\n cpx_floor?: number;\n source: string;\n api_key: string;\n user_id?: string;\n}\n\nexport interface CommercialIntentResult {\n url: string;\n domain: string;\n suggestions: Suggestion[];\n}\n\ntype AcieRecommendationProduct = {\n product_id?: string;\n product_link?: string;\n product_click_url?: string;\n product_name?: string;\n product_description?: string;\n product_price?: string | number | null;\n product_discount?: string | number | null;\n product_currency?: string;\n product_discount_type?: string;\n product_cta_label?: string;\n product_image_url?: string;\n product_features?: string[];\n};\n\ntype AcieRecommendationPayload = {\n recommendation_id?: string;\n title?: string;\n url?: string;\n click_url?: string;\n exposure_url?: string;\n follow_up_suggestion?: string;\n followup_engagement_url?: string;\n followup_exposure_url?: string;\n preferred_format?: string;\n products?: AcieRecommendationProduct[];\n creative_input?: {\n brand_name?: string;\n product_name?: string;\n short_description?: string;\n long_description?: string;\n cta_label?: string;\n cta_url?: string;\n assets?: {\n image_urls?: string[];\n logo_url?: string;\n };\n };\n};\n\nfunction isPlatformResponse(value: unknown): value is PlatformResponse {\n return Boolean(\n value &&\n typeof value === 'object' &&\n 'recommendation_id' in value &&\n 'status' in value\n );\n}\n\nfunction normalizeAcieRecommendation(value: unknown): PlatformResponse | undefined {\n if (!value || typeof value !== 'object') {\n return undefined;\n }\n\n if (isPlatformResponse(value)) {\n return value;\n }\n\n const recommendation = value as AcieRecommendationPayload;\n if (!recommendation.recommendation_id) {\n return undefined;\n }\n\n const products = (recommendation.products || []).map((product) => ({\n product_id: product.product_id || '',\n product_link: product.product_link || product.product_click_url || recommendation.click_url || recommendation.url || '',\n product_name: product.product_name || recommendation.title || recommendation.creative_input?.product_name || '',\n product_description: product.product_description || '',\n product_price: product.product_price ?? undefined,\n product_discount: product.product_discount ?? undefined,\n product_currency: product.product_currency,\n product_discount_type: product.product_discount_type,\n product_cta_label: product.product_cta_label || recommendation.creative_input?.cta_label,\n product_image_url: product.product_image_url,\n product_features: product.product_features,\n }));\n\n return {\n spec_version: '1.0',\n recommendation_id: recommendation.recommendation_id,\n timestamp: new Date().toISOString(),\n status: 'generated',\n ttl_ms: 300000,\n recommendation: {\n format: (recommendation.preferred_format as NonNullable<PlatformResponse['recommendation']>['format']) || 'tail',\n disclosure: 'Sponsored',\n creative: {\n brand_name: recommendation.creative_input?.brand_name || '',\n headline: recommendation.title || recommendation.creative_input?.product_name || '',\n description:\n recommendation.creative_input?.short_description ||\n recommendation.creative_input?.long_description ||\n '',\n cta_text: recommendation.creative_input?.cta_label || products[0]?.product_cta_label || 'Learn more',\n follow_up_suggestion: recommendation.follow_up_suggestion,\n logo_url: recommendation.creative_input?.assets?.logo_url,\n image_urls: recommendation.creative_input?.assets?.image_urls || [],\n landing_page_url: recommendation.url || recommendation.click_url || recommendation.creative_input?.cta_url || '',\n products,\n },\n },\n tracking: {\n exposure_url: recommendation.exposure_url,\n click_url: recommendation.click_url,\n followup_exposure_url: recommendation.followup_exposure_url,\n followup_engagement_url: recommendation.followup_engagement_url,\n },\n };\n}\n\nfunction normalizeCommercialIntentResult(result: CommercialIntentResult): CommercialIntentResult {\n return {\n ...result,\n suggestions: (result.suggestions || []).map((suggestion) => ({\n ...suggestion,\n recommendation: normalizeAcieRecommendation(suggestion.recommendation),\n })),\n };\n}\n\n/**\n * Extract article slug from URL for publisher API keys\n */\nfunction extractArticleSlug(url: string): string | undefined {\n try {\n const urlObj = new URL(url);\n const pathSegments = urlObj.pathname.split('/').filter(segment => segment.length > 0);\n const articleSlug = pathSegments[pathSegments.length - 1];\n return articleSlug || undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Call ACIE analyze-intent endpoint to analyze commercial intent of a page\n * \n * @param headingsData - Page data including title, headings, URL, and domain\n * @param config - AdMesh SDK configuration containing API base URL and API key\n * @returns Promise<CommercialIntentResult | null> - Intent analysis results or null on error\n */\nexport async function callAnalyzeIntentEndpoint(\n headingsData: {\n url: string;\n title?: string;\n headings?: string[];\n article_text?: string;\n domain: string;\n },\n config: AdMeshSDKConfig\n): Promise<CommercialIntentResult | null> {\n try {\n console.log('[AdMesh SDK] Starting ACIE analyze-intent call...', { url: headingsData.url });\n \n // Combine all headings into content for analysis\n const allHeadings = Array.isArray(headingsData.headings) ? headingsData.headings : [];\n const pathTopic = extractArticleSlug(headingsData.url)\n ?.replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n const fallbackHeading = pathTopic\n ? pathTopic.replace(/\\b\\w/g, (char) => char.toUpperCase())\n : undefined;\n \n // Extract article slug for publisher API keys\n const articleSlug = config.apiKey.toLowerCase().startsWith('pub_') \n ? extractArticleSlug(headingsData.url)\n : undefined;\n\n const normalizedSource = config.extension ? 'extension' : 'admesh_ui_sdk';\n const normalizedDomain = (\n headingsData.domain ||\n (typeof window !== 'undefined' ? window.location.hostname : '')\n ).trim().toLowerCase();\n \n // Prepare request payload matching CommercialIntentRequest model\n const payload: CommercialIntentRequest = {\n url: headingsData.url,\n title: headingsData.title || undefined,\n headings: allHeadings.length > 0 ? allHeadings : fallbackHeading ? [fallbackHeading] : undefined,\n article_text: headingsData.article_text?.trim() || undefined,\n domain: normalizedDomain,\n article_slug: articleSlug,\n agent_id: undefined, // Optional - can be added later if needed\n cpx_floor: undefined, // Optional - can be added later if needed\n source: normalizedSource,\n api_key: config.apiKey, // Add API key from config\n user_id: config.userId || undefined\n };\n \n console.log('[AdMesh SDK] Payload prepared:', {\n url: payload.url,\n titleLength: payload.title?.length || 0,\n headingsCount: payload.headings?.length || 0,\n articleTextLength: payload.article_text?.length || 0,\n domain: payload.domain,\n article_slug: payload.article_slug,\n source: payload.source,\n has_user_id: !!payload.user_id\n });\n \n const apiUrl = `${config.apiBaseUrl}/acie/analyze-intent`;\n console.log('[AdMesh SDK] Calling ACIE API:', apiUrl);\n \n // Make API call to ACIE endpoint\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`\n },\n body: JSON.stringify(payload)\n });\n \n console.log('[AdMesh SDK] ACIE API response received:', {\n status: response.status,\n statusText: response.statusText,\n ok: response.ok\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n console.error('[AdMesh SDK] ACIE API error:', {\n status: response.status,\n statusText: response.statusText,\n errorText: errorText\n });\n throw new Error(`ACIE API error: ${response.status} - ${errorText}`);\n }\n \n const rawAnalysisResult = await response.json();\n const analysisResult = normalizeCommercialIntentResult(rawAnalysisResult as CommercialIntentResult);\n \n console.log('[AdMesh SDK] ACIE analysis completed:', {\n url: headingsData.url,\n suggestionsCount: analysisResult.suggestions.length\n });\n \n // Return the analysis result\n return analysisResult;\n \n } catch (err) {\n console.error('[AdMesh SDK] Error calling ACIE analyze-intent endpoint:', err);\n return null;\n }\n}\n","/**\n * Fetch virtual page context for GAM/Xandr ad-slot creatives.\n */\n\nimport type { HeadingsExtractionResult } from './extractHeadings';\n\nexport type PageContextSource = 'cache' | 'index' | 'httpx' | 'firecrawl' | 'degraded';\n\nexport interface PageContextApiConfig {\n apiKey: string;\n apiBaseUrl: string;\n agentDisplayId?: string;\n publisherId?: string;\n}\n\nexport interface PageContextResponse {\n context: HeadingsExtractionResult & { degraded?: boolean };\n source: PageContextSource;\n cache_hit: boolean;\n}\n\nexport async function fetchPageContext(\n url: string,\n config: PageContextApiConfig,\n): Promise<PageContextResponse> {\n const base = (config.apiBaseUrl || 'https://api.useadmesh.com').replace(/\\/$/, '');\n const params = new URLSearchParams({ url: url.trim() });\n if (config.agentDisplayId?.trim()) {\n params.set('agent_display_id', config.agentDisplayId.trim());\n }\n if (config.publisherId?.trim()) {\n params.set('publisher_id', config.publisherId.trim());\n }\n\n const response = await fetch(`${base}/publisher-assistant/page-context?${params.toString()}`, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new Error(`Page context request failed (${response.status}): ${body || response.statusText}`);\n }\n\n return (await response.json()) as PageContextResponse;\n}\n","'use client';\n\nimport { useEffect, useState, useCallback, useRef, type ReactNode, type FC } from 'react';\nimport { logger } from '../utils/logger';\nimport { AdMeshSDK } from '../sdk/AdMeshSDK';\nimport { AdMeshContext, type AdMeshContextValue } from './AdMeshContext';\nimport type { AdMeshTheme, PlatformResponse, ActiveDelegationSession } from '../types/index';\nimport { extractHeadingsDirectly, type HeadingsExtractionResult } from '../utils/extractHeadings';\nimport { callAnalyzeIntentEndpoint } from '../utils/acieApi';\nimport { fetchPageContext } from '../utils/pageContextApi';\nimport type { Suggestion } from '../components/AdMeshIntentAssistant';\n\nexport type PageContextMode = 'page' | 'ad-slot' | 'auto';\n\nfunction isInIframe(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n try {\n return window.self !== window.top;\n } catch {\n return true;\n }\n}\n\nfunction getUsableWindowHref(): string | null {\n if (typeof window === 'undefined') {\n return null;\n }\n try {\n const href = window.location.href?.trim();\n if (isResolvedArticleUrl(href)) {\n return href;\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction isResolvedArticleUrl(value?: string): boolean {\n const trimmed = value?.trim();\n if (!trimmed || /%%[^%]+%%/.test(trimmed)) {\n return false;\n }\n try {\n const parsed = new URL(trimmed);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction titleFromUrlPath(url: string): string {\n try {\n const parsed = new URL(url);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const raw = segments[segments.length - 1] || segments[segments.length - 2] || parsed.hostname;\n const cleaned = raw\n .replace(/\\.[a-z0-9]+$/i, '')\n .replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n return cleaned ? cleaned.replace(/\\b\\w/g, (char) => char.toUpperCase()) : parsed.hostname;\n } catch {\n return 'This page';\n }\n}\n\nfunction buildUrlFallbackContext(url: string): HeadingsExtractionResult {\n const parsed = new URL(url);\n const title = titleFromUrlPath(url);\n return {\n title,\n headings: [title],\n article_text: `Article URL: ${url}\\nArticle topic inferred from URL path: ${title}`,\n url,\n domain: parsed.hostname,\n extracted_at: new Date().toISOString(),\n };\n}\n\nfunction resolveArticleUrlForContext(articleUrl?: string): string | null {\n const currentHref = getUsableWindowHref();\n if (currentHref) {\n return currentHref;\n }\n const trimmed = articleUrl?.trim();\n if (isResolvedArticleUrl(trimmed)) {\n return trimmed;\n }\n return null;\n}\n\nexport interface AdMeshProviderProps {\n /** AdMesh API key (required) */\n apiKey: string;\n\n /** Session ID (required) */\n sessionId: string;\n\n /** Optional: Whether this provider is being used by the extension (optional) */\n extension?: boolean;\n\n /** Optional theme configuration */\n theme?: AdMeshTheme;\n\n /** Optional API base URL (defaults to production) */\n apiBaseUrl?: string;\n\n /** Optional user language in BCP 47 format (e.g., \"en-US\") */\n language?: string;\n\n /** Optional detailed user location */\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n\n /** Optional anonymous hashed user ID */\n userId?: string;\n\n /** Optional AI model identifier (e.g., \"gpt-4o\") - forwarded as platform software version metadata */\n model?: string;\n\n /** Optional conversation history - forwarded in classification_input.interaction.input.messages */\n messages?: Array<{ role: string; content: string; id?: string }>;\n\n /** Pre-resolved page context (skips client/server extract) */\n pageContext?: HeadingsExtractionResult | null;\n\n /** Article URL for ad-slot / GAM (e.g. %%PAGE_URL%% macro) */\n articleUrl?: string;\n\n /** How to obtain page context: page DOM, ad-slot API, or auto-detect iframe */\n contextMode?: PageContextMode;\n\n /** Agent display id for optional content-index lookup */\n agentDisplayId?: string;\n\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * AdMeshProvider - Simplified SDK integration for React applications\n *\n * Handles:\n * - SDK initialization and lifecycle management\n * - Message deduplication tracking\n * - Session and message ID management\n * - Error handling and logging\n *\n * @example\n * ```tsx\n * <AdMeshProvider\n * apiKey={process.env.NEXT_PUBLIC_ADMESH_API_KEY}\n * sessionId=\"custom-session-id\"\n * >\n * <Chat messages={messages} />\n * </AdMeshProvider>\n * \n * // Extension usage (skips intent analysis)\n * <AdMeshProvider \n * apiKey=\"pub_extension_key\"\n * sessionId=\"extension-session-id\"\n * extension={true}\n * >\n * <AdMeshIntentAssistant autoOpen={true} />\n * </AdMeshProvider>\n * ```\n */\nexport const AdMeshProvider: FC<AdMeshProviderProps> = ({\n apiKey,\n sessionId,\n extension,\n theme,\n apiBaseUrl,\n language,\n location,\n userId,\n model,\n messages,\n pageContext,\n articleUrl,\n contextMode = 'auto',\n agentDisplayId,\n children,\n}) => {\n const [sdk, setSdk] = useState<AdMeshSDK | null>(null);\n const [processedMessageIds, setProcessedMessageIds] = useState<Set<string>>(\n new Set()\n );\n const [recommendationResults, setRecommendationResults] = useState<\n Map<string, PlatformResponse | null>\n >(new Map());\n const [activeDelegationSession, setActiveDelegationSessionState] = useState<ActiveDelegationSession | null>(null);\n\n // Suggestion state\n const [suggestions, setSuggestions] = useState<Suggestion[]>([]);\n const [isAnalyzingIntent, setIsAnalyzingIntent] = useState(false);\n const [intentError, setIntentError] = useState<string | null>(null);\n const [isResolvingPageContext, setIsResolvingPageContext] = useState(false);\n const hasAttemptedInitialAnalysisRef = useRef(false);\n\n const usesAdSlotContext =\n Boolean(pageContext) ||\n contextMode === 'ad-slot' ||\n (contextMode === 'auto' && (Boolean(articleUrl?.trim()) || isInIframe()));\n\n const resolveHeadingsForAnalysis = useCallback(async (): Promise<HeadingsExtractionResult | null> => {\n if (pageContext) {\n return pageContext;\n }\n\n if (!usesAdSlotContext) {\n return extractHeadingsDirectly();\n }\n\n const targetUrl = resolveArticleUrlForContext(articleUrl);\n if (!targetUrl) {\n logger.warn('[AdMeshProvider] Ad-slot context mode requires a real article URL');\n setIntentError('Article URL is required for ad-slot context');\n return null;\n }\n\n if (!apiKey || !apiBaseUrl) {\n logger.warn('[AdMeshProvider] Cannot fetch page context: missing API key or base URL');\n return buildUrlFallbackContext(targetUrl);\n }\n\n try {\n setIsResolvingPageContext(true);\n const response = await fetchPageContext(targetUrl, {\n apiKey,\n apiBaseUrl: apiBaseUrl || 'https://api.useadmesh.com',\n agentDisplayId,\n });\n logger.log('[AdMeshProvider] Page context resolved', {\n source: response.source,\n cache_hit: response.cache_hit,\n domain: response.context.domain,\n });\n return response.context;\n } catch (error) {\n logger.error('[AdMeshProvider] Failed to fetch page context:', error);\n logger.warn('[AdMeshProvider] Falling back to URL-path context for suggestions');\n return buildUrlFallbackContext(targetUrl);\n } finally {\n setIsResolvingPageContext(false);\n }\n }, [\n agentDisplayId,\n apiBaseUrl,\n apiKey,\n articleUrl,\n pageContext,\n usesAdSlotContext,\n ]);\n\n const prependSponsoredSuggestion = useCallback(\n (currentSuggestions: Suggestion[], sponsoredSuggestion: Suggestion): Suggestion[] => {\n const organicSuggestions = currentSuggestions.filter((suggestion) => !suggestion.is_sponsored).slice(0, 3);\n return [sponsoredSuggestion, ...organicSuggestions];\n },\n [],\n );\n\n const mergeOrganicSuggestions = useCallback((currentSuggestions: Suggestion[], organicSuggestions: Suggestion[]) => {\n const sponsoredSuggestion = currentSuggestions.find((suggestion) => suggestion.is_sponsored);\n const nextOrganicSuggestions = organicSuggestions.filter((suggestion) => !suggestion.is_sponsored).slice(0, 3);\n return sponsoredSuggestion ? [sponsoredSuggestion, ...nextOrganicSuggestions] : nextOrganicSuggestions;\n }, []);\n\n // Validate that sessionId is provided by platform\n useEffect(() => {\n if (!sessionId || sessionId.trim() === '') {\n logger.error('[AdMeshProvider] ❌ sessionId is required and must be provided by the platform. Use AdMeshSDK.generateSessionIdFromUrl() for URL-based detection.');\n return;\n }\n \n logger.log('[AdMeshProvider] ✅ Session ID available:', sessionId);\n }, [sessionId]);\n\n // Initialize SDK once on mount\n useEffect(() => {\n if (!apiKey) {\n logger.warn('[AdMeshProvider] ⚠️ AdMesh API key not configured');\n return;\n }\n\n if (!sessionId || sessionId.trim() === '') {\n logger.error('[AdMeshProvider] ❌ Cannot initialize SDK: sessionId is required. Use AdMeshSDK.generateSessionIdFromUrl() for URL-based detection.');\n return;\n }\n\n try {\n const sdkInstance = new AdMeshSDK({\n apiKey,\n theme,\n apiBaseUrl,\n extension,\n });\n setSdk(sdkInstance);\n logger.log('[AdMeshProvider] ✅ AdMesh SDK initialized with session:', sessionId);\n if (apiBaseUrl) {\n logger.log('[AdMeshProvider] 📍 Using custom API base URL');\n }\n } catch (error) {\n logger.error('[AdMeshProvider] ❌ Failed to initialize AdMesh SDK:', error);\n }\n\n // Cleanup on unmount\n return () => {\n logger.log('[AdMeshProvider] 🧹 Provider unmounted');\n };\n }, [apiKey, theme, apiBaseUrl, sessionId, extension]);\n\n // Intent analysis function\n const performIntentAnalysis = useCallback(async (prefetchedHeadingsData?: HeadingsExtractionResult | null) => {\n if (!apiKey || !apiBaseUrl) {\n logger.warn('[AdMeshProvider] ⚠️ Cannot perform intent analysis: missing API key or base URL');\n return;\n }\n\n // Skip intent analysis if called from extension\n if (extension) {\n logger.log('[AdMeshProvider] ℹ️ Extension mode: allowing intent analysis for any API key');\n // Don't return - continue to intent analysis for extension\n } else {\n // For non-extension usage, only allow pub_ API keys\n if (!apiKey.toLowerCase().startsWith('pub_')) {\n logger.log('[AdMeshProvider] ℹ️ Skipping auto intent analysis: API key does not start with \"pub_\"');\n return;\n }\n }\n\n try {\n setIsAnalyzingIntent(true);\n setIntentError(null);\n \n logger.log('[AdMeshProvider] 🔄 Starting automatic intent analysis...');\n \n const headingsData = prefetchedHeadingsData ?? (await resolveHeadingsForAnalysis());\n if (!headingsData) {\n logger.warn('[AdMeshProvider] ⚠️ Failed to extract headings for intent analysis');\n setIntentError('Failed to extract page content');\n return;\n }\n \n logger.log('[AdMeshProvider] 📄 Extracted headings:', {\n title: headingsData.title,\n headingsCount: headingsData.headings.length,\n articleTextLength: headingsData.article_text?.length || 0,\n domain: headingsData.domain\n });\n \n // Call ACIE API for intent analysis\n const config = {\n apiKey,\n apiBaseUrl: apiBaseUrl || 'https://api.useadmesh.com',\n extension,\n userId\n };\n \n const analysisResult = await callAnalyzeIntentEndpoint(headingsData, config);\n \n if (analysisResult) {\n logger.log('[AdMeshProvider] ✅ Intent analysis completed:', {\n suggestionsCount: analysisResult.suggestions.length,\n suggestions: (analysisResult.suggestions || []).map((suggestion) => ({\n id: suggestion.id,\n text: suggestion.text,\n is_sponsored: suggestion.is_sponsored,\n recommendationId: suggestion.recommendation?.recommendation_id || null,\n })),\n });\n \n setSuggestions((currentSuggestions) =>\n mergeOrganicSuggestions(currentSuggestions, analysisResult.suggestions || [])\n );\n } else {\n logger.warn('[AdMeshProvider] ⚠️ Intent analysis returned null');\n setIntentError('Intent analysis failed');\n setSuggestions((current) => {\n if (current.length > 0) {\n logger.log('[AdMeshProvider] ℹ️ Preserving existing suggestions after null intent analysis result');\n return current;\n }\n return [\n {\n id: \"fallback-1\",\n text: \"What are your questions about this content?\",\n type: \"information\" as const,\n is_sponsored: false,\n recommendation: undefined,\n }\n ];\n });\n }\n } catch (error) {\n logger.error('[AdMeshProvider] ❌ Error in intent analysis:', error);\n setIntentError('Intent analysis error');\n setSuggestions((current) => {\n if (current.length > 0) {\n logger.log('[AdMeshProvider] ℹ️ Preserving existing suggestions after intent analysis error');\n return current;\n }\n return [\n {\n id: \"error-fallback-1\",\n text: \"Ask me questions about this page\",\n type: \"information\" as const,\n is_sponsored: false,\n recommendation: undefined,\n }\n ];\n });\n } finally {\n setIsAnalyzingIntent(false);\n }\n }, [apiKey, apiBaseUrl, extension, userId, mergeOrganicSuggestions, resolveHeadingsForAnalysis]);\n\n const prefetchSponsoredSuggestion = useCallback(\n async (prefetchedHeadingsData?: HeadingsExtractionResult | null) => {\n if (!sdk || !apiKey) {\n return;\n }\n\n if (!apiKey.toLowerCase().startsWith('pub_')) {\n return;\n }\n\n const headingsData = prefetchedHeadingsData ?? (await resolveHeadingsForAnalysis());\n if (!headingsData) {\n logger.warn('[AdMeshProvider] ⚠️ Failed to extract page content for sponsored suggestion prefetch');\n return;\n }\n\n const query = headingsData.headings?.[0]?.trim() || headingsData.title?.trim();\n if (!query) {\n logger.warn('[AdMeshProvider] ⚠️ Skipping sponsored suggestion prefetch: no usable page query');\n return;\n }\n\n try {\n logger.log('[AdMeshProvider] 🔄 Prefetching sponsored suggestion from /aip/context...');\n const platformResult = await sdk.fetchPlatformResponse({\n query,\n sessionId,\n messageId: AdMeshSDK.createMessageId(sessionId),\n platformSurface: 'embedded_assistant',\n model,\n messages: [],\n language,\n location,\n userId,\n });\n\n const suggestionText = platformResult.recommendation?.creative?.follow_up_suggestion?.trim();\n const recommendationId = platformResult.recommendation_id;\n if (!suggestionText || !recommendationId) {\n logger.log('[AdMeshProvider] ℹ️ No sponsored follow-up suggestion returned from /aip/context');\n return;\n }\n\n const sponsoredSuggestion: Suggestion = {\n id: recommendationId,\n text: suggestionText,\n type: 'action',\n is_sponsored: true,\n recommendation: platformResult,\n metadata: {\n source: 'aip_context_prefetch',\n recommendation_id: recommendationId,\n },\n };\n\n setSuggestions((currentSuggestions) =>\n prependSponsoredSuggestion(currentSuggestions, sponsoredSuggestion)\n );\n\n logger.log('[AdMeshProvider] ✅ Sponsored suggestion prefetched from /aip/context', {\n recommendationId,\n suggestionText,\n });\n } catch (error) {\n logger.warn('[AdMeshProvider] ⚠️ Sponsored suggestion prefetch failed (non-blocking):', error);\n }\n },\n [apiKey, language, location, model, sdk, sessionId, userId, prependSponsoredSuggestion, resolveHeadingsForAnalysis],\n );\n\n // Retry intent analysis function\n const retryIntentAnalysis = useCallback(async () => {\n logger.log('[AdMeshProvider] 🔄 Manual retry of intent analysis');\n await performIntentAnalysis();\n }, [performIntentAnalysis]);\n\n // Auto-analyze intent once on mount for public API keys.\n // Empty ACIE/no_match responses are still valid outcomes and must not retrigger forever.\n useEffect(() => {\n if (!sdk || hasAttemptedInitialAnalysisRef.current) {\n return;\n }\n\n hasAttemptedInitialAnalysisRef.current = true;\n void (async () => {\n const headingsData = await resolveHeadingsForAnalysis();\n await Promise.allSettled([\n prefetchSponsoredSuggestion(headingsData),\n performIntentAnalysis(headingsData),\n ]);\n })();\n }, [sdk, performIntentAnalysis, prefetchSponsoredSuggestion, resolveHeadingsForAnalysis]);\n\n const isDelegationSessionActive = useCallback((session: ActiveDelegationSession | null) => {\n if (!session || session.status !== 'active') {\n return false;\n }\n\n const expiresAtMs = Date.parse(session.expires_at);\n if (Number.isNaN(expiresAtMs)) {\n return false;\n }\n\n return expiresAtMs > Date.now();\n }, []);\n\n const postDelegationEvent = useCallback(\n async (\n endpoint: string,\n eventType: string,\n metadata?: Record<string, unknown>,\n sessionOverride?: ActiveDelegationSession | null,\n ) => {\n const session = sessionOverride ?? activeDelegationSession;\n if (!session || !sdk) {\n logger.warn('[AdMeshProvider] ⚠️ Skipping delegation event because session or SDK is missing', {\n endpoint,\n eventType,\n hasSession: !!session,\n hasSdk: !!sdk,\n });\n return;\n }\n\n const timestamp = new Date().toISOString();\n logger.log('[AdMeshProvider] 📡 Sending delegation event', {\n endpoint,\n eventType,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n sessionId: session.session_id,\n });\n const response = await fetch(`${sdk.getApiBaseUrl()}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n delegation_session_id: session.delegation_session_id,\n recommendation_id: session.recommendation_id,\n session_id: session.session_id,\n event_type: eventType,\n timestamp,\n metadata: metadata || {},\n }),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n logger.error('[AdMeshProvider] ❌ Delegation event failed', {\n endpoint,\n eventType,\n status: response.status,\n errorBody,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n });\n throw new Error(`Delegation event failed (${response.status}): ${errorBody}`);\n }\n\n const result = await response.json();\n const updatedSession = result?.session as ActiveDelegationSession | undefined;\n logger.log('[AdMeshProvider] ✅ Delegation event acknowledged', {\n endpoint,\n eventType,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n returnedStatus: updatedSession?.status || result?.status,\n });\n if (updatedSession) {\n setActiveDelegationSessionState(updatedSession);\n }\n },\n [activeDelegationSession, apiKey, sdk],\n );\n\n useEffect(() => {\n if (!activeDelegationSession || !sdk) {\n return;\n }\n\n if (!isDelegationSessionActive(activeDelegationSession)) {\n setActiveDelegationSessionState((prev) =>\n prev\n ? {\n ...prev,\n status: 'expired',\n }\n : null,\n );\n return;\n }\n\n const interval = window.setInterval(() => {\n void postDelegationEvent('/aip/delegation/heartbeat', 'heartbeat').catch((error) => {\n logger.warn('[AdMeshProvider] ⚠️ Failed to send delegation heartbeat:', error);\n });\n }, 60_000);\n\n return () => {\n window.clearInterval(interval);\n };\n }, [activeDelegationSession, isDelegationSessionActive, postDelegationEvent, sdk]);\n\n // Create context value\n const contextValue: AdMeshContextValue = {\n sdk,\n apiKey,\n sessionId,\n theme,\n language,\n location,\n userId,\n model,\n messages,\n processedMessageIds,\n recommendationResults,\n activeDelegationSession,\n \n // Suggestion state\n suggestions,\n isAnalyzingIntent: isAnalyzingIntent || isResolvingPageContext,\n intentError,\n \n // Methods\n markMessageAsProcessed: (messageId: string) => {\n setProcessedMessageIds((prev) => {\n const updated = new Set(prev);\n updated.add(messageId);\n return updated;\n });\n },\n \n isMessageProcessed: (messageId: string) => {\n return processedMessageIds.has(messageId);\n },\n\n setRecommendationResult: (messageId: string, result: PlatformResponse | null) => {\n setRecommendationResults((prev) => {\n const next = new Map(prev);\n next.set(messageId, result);\n return next;\n });\n setProcessedMessageIds((prev) => {\n const updated = new Set(prev);\n updated.add(messageId);\n return updated;\n });\n },\n\n getRecommendationResult: (messageId: string) => {\n return recommendationResults.get(messageId);\n },\n\n hasRecommendationResult: (messageId: string) => {\n return recommendationResults.has(messageId);\n },\n\n setActiveDelegationSession: (session: ActiveDelegationSession | null) => {\n setActiveDelegationSessionState(session);\n },\n\n getActiveDelegationSession: () => {\n if (!isDelegationSessionActive(activeDelegationSession)) {\n return null;\n }\n return activeDelegationSession;\n },\n\n hasActiveDelegationSession: () => {\n return isDelegationSessionActive(activeDelegationSession);\n },\n\n refreshDelegationActivity: async (\n eventType: string = 'turn_completed',\n metadata?: Record<string, unknown>,\n ) => {\n await postDelegationEvent('/aip/delegation/activity', eventType, metadata);\n },\n\n stopDelegationSession: async (\n reason: string = 'user_stopped',\n metadata?: Record<string, unknown>,\n ) => {\n const session = activeDelegationSession;\n if (!session) {\n logger.warn('[AdMeshProvider] ⚠️ stopDelegationSession called without an active SDK delegation session');\n return;\n }\n\n logger.log('[AdMeshProvider] 🛑 Stopping delegation session', {\n reason,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n });\n await postDelegationEvent(\n '/aip/delegation/stop',\n 'session_stopped',\n { reason, ...(metadata || {}) },\n session,\n );\n await sdk?.trackPublisherAssistantEvent({\n event_name: 'delegation_stopped',\n timestamp: new Date().toISOString(),\n session_id: session.session_id,\n recommendation_id: session.recommendation_id,\n delegation_session_id: session.delegation_session_id,\n brand_name: session.brand_name,\n status: 'stopped',\n metadata: {\n reason,\n ...(metadata || {}),\n },\n }).catch((analyticsError) => {\n logger.warn('[AdMeshProvider] ⚠️ Failed to track delegation_stopped event:', analyticsError);\n });\n setActiveDelegationSessionState(null);\n logger.log('[AdMeshProvider] ✅ Delegation session cleared locally after stop');\n },\n \n retryIntentAnalysis,\n };\n\n return (\n <AdMeshContext.Provider value={contextValue}>\n {children}\n </AdMeshContext.Provider>\n );\n};\n\nexport default AdMeshProvider;\n","/**\n * AdMesh Renderer\n * \n * Handles rendering of recommendations in the specified container\n */\n\nimport ReactDOM from 'react-dom/client';\nimport type { AdMeshRecommendationResponse, AdMeshTheme, DelegationActivationPayload } from '../types/index';\nimport { AdMeshLayout } from '../components/AdMeshLayout';\nimport { AdMeshTracker } from './AdMeshTracker';\nimport { AdMeshProvider } from '../context/AdMeshProvider';\nimport { logger } from '../utils/logger';\n\nexport interface RenderOptions {\n containerId: string;\n followups_container_id?: string;\n response: AdMeshRecommendationResponse;\n theme?: AdMeshTheme;\n tracker: AdMeshTracker;\n sessionId: string;\n apiKey: string;\n apiBaseUrl?: string;\n language?: string;\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string;\n model?: string;\n messages?: Array<{ role: string; content: string; id?: string }>;\n onPasteToInput?: (content: string) => void;\n onDelegationConsent?: (recommendation: import('../types/index').PlatformResponse) => boolean | Promise<boolean>;\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n onStartDelegation?: (recommendation: import('../types/index').PlatformResponse) => void | Promise<void>;\n onExecuteQuery?: (query: string) => void | Promise<void>;\n}\n\nexport class AdMeshRenderer {\n private roots: Map<string, ReactDOM.Root> = new Map();\n\n constructor() {\n // No configuration needed\n }\n\n /**\n * Render recommendations in the specified container\n */\n async render(options: RenderOptions): Promise<void> {\n try {\n logger.log('[AdMeshRenderer] 🎨 Attempting to render recommendations');\n\n // Check if we have any recommendations to render\n const recommendations = options.response.recommendations || [];\n if (recommendations.length === 0) {\n logger.log('[AdMeshRenderer] ⚠️ No recommendations to render - skipping render to avoid occupying space');\n return;\n }\n\n const container = document.getElementById(options.containerId);\n\n if (!container) {\n logger.error('[AdMeshRenderer] ❌ Container not found');\n throw new Error(`Container with ID \"${options.containerId}\" not found`);\n }\n\n logger.log('[AdMeshRenderer] ✅ Container ready');\n\n // Clean up existing root if any\n const existingRoot = this.roots.get(options.containerId);\n if (existingRoot) {\n logger.log('[AdMeshRenderer] 🧹 Cleaning up existing root');\n existingRoot.unmount();\n this.roots.delete(options.containerId);\n }\n\n // Clear the container's innerHTML to ensure React can create a fresh root\n container.innerHTML = '';\n\n // Create a new root\n const root = ReactDOM.createRoot(container);\n\n logger.log('[AdMeshRenderer] 📊 Rendering recommendations');\n\n // Get onPasteToInput from options or window object (for backward compatibility)\n // Wrap components in AdMeshProvider to provide context for hooks like useAdMesh()\n root.render(\n <AdMeshProvider\n apiKey={options.apiKey}\n sessionId={options.sessionId}\n theme={options.theme}\n apiBaseUrl={options.apiBaseUrl}\n language={options.language}\n location={options.location}\n userId={options.userId}\n model={options.model}\n messages={options.messages}\n >\n <AdMeshLayout\n recommendations={recommendations}\n theme={options.theme}\n sessionId={options.sessionId}\n onDelegationConsent={options.onDelegationConsent}\n onDelegationActivated={options.onDelegationActivated}\n onStartDelegation={options.onStartDelegation}\n />\n </AdMeshProvider>\n );\n\n // Show the container now that content is rendered (prevents empty space when no ads)\n container.style.display = 'block';\n\n logger.log('[AdMeshRenderer] ✅ Recommendations rendered successfully');\n\n // Store root for cleanup\n this.roots.set(options.containerId, root);\n\n } catch (error) {\n logger.error('[AdMeshRenderer] ❌ Error rendering recommendations');\n throw error;\n }\n }\n\n /**\n * Unmount a rendered component\n */\n unmount(containerId: string): void {\n const root = this.roots.get(containerId);\n if (root) {\n root.unmount();\n this.roots.delete(containerId);\n \n // Hide the container again to prevent empty space\n const container = document.getElementById(containerId);\n if (container) {\n container.style.display = 'none';\n }\n }\n }\n\n /**\n * Unmount all rendered components\n */\n unmountAll(): void {\n for (const [, root] of this.roots.entries()) {\n root.unmount();\n }\n this.roots.clear();\n }\n}\n","/**\n * AdMesh UI SDK - Zero-Code Integration\n * \n * Provides a simple, zero-code integration experience for platforms.\n * Handles all recommendation fetching, rendering, and tracking automatically.\n */\n\nimport type {\n AdMeshTheme,\n AdMeshRecommendationResponse,\n PlatformRequest,\n PlatformResponse,\n DelegationActivationPayload,\n ActiveDelegationSession,\n} from '../types/index';\nimport { AdMeshRenderer } from './AdMeshRenderer';\nimport { AdMeshTracker } from './AdMeshTracker';\nimport { logger } from '../utils/logger';\n\nconst normalizeCountryCode = (value?: string): string | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim().toUpperCase();\n return /^[A-Z]{2}$/.test(trimmed) ? trimmed : undefined;\n};\n\nexport interface AdMeshSDKConfig {\n apiKey: string;\n theme?: AdMeshTheme;\n apiBaseUrl?: string;\n /** Set true when requests originate from the browser extension */\n extension?: boolean;\n /** Optional override for extension source domain header */\n extensionSourceDomain?: string;\n /** Optional user identifier forwarded to ACIE/aip context flows */\n userId?: string;\n}\n\nexport interface ShowRecommendationsOptions {\n query: string;\n containerId: string;\n theme?: AdMeshTheme;\n\n // Optional follow-ups container (SDK will render follow-ups here if provided and followup_suggestion is present)\n followups_container_id?: string;\n\n // Session tracking (required)\n sessionId: string;\n\n // Message tracking (required)\n // messageId MUST be provided by the platform - SDK never generates it\n messageId: string;\n\n // Platform information\n // platformId is now extracted from API key by the backend\n platformSurface?: string;\n model?: string;\n messages?: Array<{ role: string; content: string }>;\n locale?: string;\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string;\n // latency_budget_ms removed - now fetched from agent profile by backend\n // allowed_formats removed - backend fetches from platform config (configured during onboarding)\n \n /** Legacy bridge CTA callback; prefer onStartDelegation */\n onPasteToInput?: (content: string) => void;\n\n /** Called when the SDK needs host approval before starting a delegated brand flow */\n onDelegationConsent?: (recommendation: PlatformResponse) => boolean | Promise<boolean>;\n\n /** Called with normalized delegation metadata the host can use directly */\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n\n /** Called after consent is granted so the host can create/open the delegation session */\n onStartDelegation?: (recommendation: PlatformResponse) => void | Promise<void>;\n \n /** Callback to execute query when follow-up is selected (required for follow-up functionality) */\n onExecuteQuery?: (query: string) => void | Promise<void>;\n}\n\nexport type PublisherAssistantEventName =\n | 'assistant_loaded'\n | 'assistant_opened'\n | 'suggestion_exposure'\n | 'suggestion_clicked'\n | 'query_submitted'\n | 'answer_completed'\n | 'answer_failed'\n | 'source_link_clicked'\n | 'recommendation_shown'\n | 'delegation_started'\n | 'delegation_stopped'\n | 'answer_feedback';\n\nexport interface PublisherAssistantAnalyticsEvent {\n event_name: PublisherAssistantEventName;\n timestamp: string;\n session_id: string;\n message_id?: string;\n page_url?: string;\n page_path?: string;\n article_slug?: string;\n page_title?: string;\n referrer?: string;\n device_type?: 'mobile' | 'tablet' | 'desktop' | 'unknown';\n query?: string;\n suggestion_id?: string;\n suggestion_text?: string;\n suggestion_type?: string;\n suggestion_position?: number;\n is_sponsored?: boolean;\n recommendation_id?: string;\n brand_name?: string;\n delegation_session_id?: string;\n used_capability?: string;\n status?: string;\n latency_ms?: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Main AdMesh SDK class for zero-code integration\n *\n * The SDK is stateless regarding session management. Developers must provide\n * sessionId when calling showRecommendations().\n *\n * @example\n * ```typescript\n * import { AdMeshSDK } from '@admesh/ui-sdk';\n *\n * const admesh = new AdMeshSDK({ apiKey: 'your-api-key' });\n *\n * // Generate session ID on your platform\n * const sessionId = AdMeshSDK.createSession();\n *\n * await admesh.showRecommendations({\n * query: 'best CRM for small business',\n * containerId: 'admesh-recommendations',\n * sessionId: sessionId\n * });\n * ```\n */\nexport class AdMeshSDK {\n private config: AdMeshSDKConfig;\n private apiBaseUrl: string;\n private static inFlightPlatformResponses = new Map<string, Promise<PlatformResponse>>();\n\n // OPTIMIZATION: Lazy-initialized managers (only created when needed)\n private renderer: AdMeshRenderer | null = null;\n private tracker: AdMeshTracker | null = null;\n\n constructor(config: AdMeshSDKConfig) {\n if (!config.apiKey) {\n throw new Error('AdMeshSDK: apiKey is required');\n }\n\n this.config = {\n apiKey: config.apiKey,\n theme: config.theme,\n apiBaseUrl: config.apiBaseUrl,\n extension: config.extension,\n extensionSourceDomain: config.extensionSourceDomain,\n userId: config.userId,\n };\n\n // Set API base URL with priority: config > environment variable > production default\n this.apiBaseUrl = config.apiBaseUrl ||\n (typeof window !== 'undefined' && (window as unknown as { __ADMESH_API_BASE_URL__: string }).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n }\n\n /**\n * Get the API base URL\n * @returns The API base URL being used by the SDK\n */\n getApiBaseUrl(): string {\n return this.apiBaseUrl;\n }\n\n private static buildPlatformResponseCacheKey(sessionId: string, messageId: string): string {\n return `${sessionId}::${messageId}`;\n }\n\n /**\n * Resolve source domain for extension-originated requests.\n */\n private getExtensionSourceDomain(): string | undefined {\n const configuredDomain = this.config.extensionSourceDomain?.trim();\n if (configuredDomain) {\n return configuredDomain.toLowerCase();\n }\n\n if (typeof window !== 'undefined' && window.location?.hostname) {\n const hostname = window.location.hostname.trim().toLowerCase();\n return hostname || undefined;\n }\n\n return undefined;\n }\n\n /**\n * PLATFORM UTILITY: Generate a unique session ID for tracking recommendations\n * \n * IMPORTANT: This is a utility method for PLATFORMS to use. The SDK itself\n * NEVER calls this method automatically. Platforms must:\n * 1. Call this method (or generate their own sessionId)\n * 2. Store the sessionId in their own storage\n * 3. Pass sessionId to AdMeshProvider and SDK methods\n * \n * The SDK will throw an error if sessionId is not provided - it will never\n * auto-generate one.\n *\n * @returns A unique session ID (platform must store and manage this)\n */\n static createSession(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 15);\n return `session_${timestamp}_${random}`;\n }\n\n /**\n * PLATFORM UTILITY: Generate session ID from URL for digital publishers\n * \n * This utility function helps platforms generate session IDs based on URL structure.\n * Platforms can call this function on page load to get a consistent session ID.\n * \n * @param url - The URL to extract session information from (defaults to current page URL)\n * @returns A session ID in format: session_{timestamp}_{article-slug}\n * \n * @example\n * ```typescript\n * // In your React component\n * const sessionId = AdMeshSDK.generateSessionIdFromUrl();\n * \n * // Or with a specific URL\n * const sessionId = AdMeshSDK.generateSessionIdFromUrl('https://techcrunch.com/2025/12/30/ai-apps/');\n * // Returns: \"session_1739534760000_ai-apps\"\n * ```\n */\n static generateSessionIdFromUrl(url?: string): string {\n const targetUrl = url || (typeof window !== 'undefined' ? window.location.href : '');\n \n if (!targetUrl) {\n // Fallback to regular session generation\n return AdMeshSDK.createSession();\n }\n\n try {\n const urlObj = new URL(targetUrl);\n const pathSegments = urlObj.pathname.split('/').filter(segment => segment.length > 0);\n const articleSlug = pathSegments[pathSegments.length - 1];\n \n if (articleSlug) {\n const timestamp = Date.now();\n return `session_${timestamp}_${articleSlug}`;\n }\n \n // Fallback if no slug found\n return AdMeshSDK.createSession();\n } catch {\n // Fallback if URL parsing fails\n return AdMeshSDK.createSession();\n }\n }\n\n /**\n * PLATFORM UTILITY: Generate a unique message ID for tracking recommendations per message\n * @returns A unique message ID (platform must provide this to SDK methods)\n */\n static createMessageId(sessionId?: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 9);\n if (sessionId) {\n return `msg_${sessionId}_${timestamp}_${random}`;\n }\n return `msg_${timestamp}_${random}`;\n }\n\n\n /**\n * OPTIMIZATION: Lazy initialize renderer on first use\n */\n private getRenderer(): AdMeshRenderer {\n if (!this.renderer) {\n this.renderer = new AdMeshRenderer();\n }\n return this.renderer;\n }\n\n /**\n * OPTIMIZATION: Lazy initialize tracker on first use\n */\n private getTracker(): AdMeshTracker {\n if (!this.tracker) {\n this.tracker = new AdMeshTracker({\n apiKey: this.config.apiKey\n });\n }\n return this.tracker;\n }\n\n private async postDelegationEvent(\n endpoint: string,\n session: ActiveDelegationSession,\n eventType: string,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n const response = await fetch(`${this.apiBaseUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n delegation_session_id: session.delegation_session_id,\n recommendation_id: session.recommendation_id,\n session_id: session.session_id,\n event_type: eventType,\n timestamp: new Date().toISOString(),\n metadata: metadata || {},\n }),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new Error(`Delegation event failed (${response.status}): ${errorBody}`);\n }\n\n const result = await response.json();\n return (result?.session as ActiveDelegationSession | undefined) || null;\n }\n\n async reportDelegationTurnStarted(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'turn_started', metadata);\n }\n\n async reportDelegationSessionStarted(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'session_started', metadata);\n }\n\n async reportDelegationTurnCompleted(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'turn_completed', metadata);\n }\n\n async reportDelegationToolInvocation(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'tool_invoked', metadata);\n }\n\n async reportDelegationOutcome(\n session: ActiveDelegationSession,\n outcomeType: string,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/complete', session, outcomeType, metadata);\n }\n\n async stopDelegationSession(\n session: ActiveDelegationSession,\n reason: string = 'user_stopped',\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/stop', session, 'session_stopped', {\n reason,\n ...(metadata || {}),\n });\n }\n\n getActiveDelegationSession(session: ActiveDelegationSession | null): ActiveDelegationSession | null {\n if (!session || session.status !== 'active') {\n return null;\n }\n\n const expiresAtMs = Date.parse(session.expires_at);\n if (Number.isNaN(expiresAtMs) || expiresAtMs <= Date.now()) {\n return null;\n }\n\n return session;\n }\n\n hasActiveDelegationSession(session: ActiveDelegationSession | null): boolean {\n return !!this.getActiveDelegationSession(session);\n }\n\n\n\n\n /**\n * Fetch and render recommendations automatically using /aip/context endpoint\n *\n * IMPORTANT: Both sessionId and messageId MUST be provided by the platform.\n * The SDK NEVER generates these automatically. Use AdMeshSDK.createSession()\n * and AdMeshSDK.createMessageId() on your platform, or generate your own IDs.\n */\n async showRecommendations(options: ShowRecommendationsOptions): Promise<void> {\n try {\n // CRITICAL: sessionId MUST be provided by platform - SDK never generates it\n if (!options.sessionId || options.sessionId.trim() === '') {\n throw new Error('sessionId is required and must be provided by the platform. The SDK never generates sessionId automatically.');\n }\n \n // CRITICAL: messageId MUST be provided by the platform - SDK never generates it\n if (!options.messageId || options.messageId.trim() === '') {\n throw new Error('messageId is required and must be provided by the platform. The SDK never generates messageId automatically.');\n }\n \n // Fetch canonical platform result from /aip/context endpoint\n // platformId is extracted from API key by the backend\n const platformResult = await this.fetchPlatformResponse({\n query: options.query,\n sessionId: options.sessionId,\n messageId: options.messageId, // Pass messageId from platform\n platformSurface: options.platformSurface,\n model: options.model,\n messages: options.messages,\n language: options.locale, // locale maps to language\n location: options.location,\n userId: options.userId ?? this.config.userId,\n // latency_budget_ms removed - now fetched from agent profile by backend\n // allowed_formats removed - backend fetches from platform config automatically\n });\n\n const response: AdMeshRecommendationResponse = {\n sessionId: options.sessionId,\n messageId: options.messageId,\n recommendations: [platformResult]\n };\n\n // Standard rendering\n const renderer = this.getRenderer();\n const tracker = this.getTracker();\n\n await renderer.render({\n containerId: options.containerId,\n followups_container_id: options.followups_container_id,\n response,\n theme: options.theme || this.config.theme,\n tracker: tracker,\n sessionId: options.sessionId,\n apiKey: this.config.apiKey,\n apiBaseUrl: this.apiBaseUrl,\n language: options.locale,\n location: options.location,\n userId: options.userId,\n model: options.model,\n messages: options.messages,\n onPasteToInput: options.onPasteToInput,\n onDelegationConsent: options.onDelegationConsent,\n onDelegationActivated: options.onDelegationActivated,\n onStartDelegation: options.onStartDelegation,\n onExecuteQuery: options.onExecuteQuery\n });\n\n // NOTE: Exposure pixels are now fired by AdMeshViewabilityTracker component\n // when ads meet MRC viewability standards (50% visible for 1 second).\n // This ensures MRC-compliant exposure tracking and proper CPX billing.\n } catch (error) {\n logger.error('[AdMeshSDK] Error showing recommendations');\n throw error;\n }\n }\n\n /**\n * Fetch the canonical PlatformResponse from `/aip/context`.\n *\n * Use this when you want the full platform response returned by the operator,\n * including `status`, `recommendation`, `tracking`, and `delegation`.\n */\n async fetchPlatformResponse(params: {\n query: string;\n sessionId: string;\n messageId?: string;\n // platformId is now extracted from API key by the backend\n platformSurface?: string;\n model?: string;\n messages?: Array<{ role: string; content: string; id?: string }>;\n language?: string;\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string;\n // latency_budget_ms removed - now fetched from agent profile by backend\n // allowed_formats removed - backend fetches from platform config (configured during onboarding)\n }): Promise<PlatformResponse> {\n const url = `${this.apiBaseUrl}/aip/context`;\n\n logger.log('[AdMeshSDK] 📥 fetchPlatformResponse called');\n\n // CRITICAL: sessionId MUST be provided by platform - SDK never generates it\n if (!params.sessionId || params.sessionId.trim() === '') {\n const error = new Error('sessionId is required and must be provided by the platform. The SDK never generates sessionId automatically.');\n logger.error('[AdMeshSDK] ❌ sessionId not provided by platform - cannot process request');\n throw error;\n }\n\n // CRITICAL: messageId MUST be provided by the platform - SDK never generates it\n // NEVER derive from messages array - platform must pass it explicitly\n const messageId = params.messageId;\n if (!messageId || messageId.trim() === '') {\n const error = new Error('messageId is required and must be provided by the platform. The SDK never generates messageId automatically.');\n logger.error('[AdMeshSDK] ❌ messageId not provided by platform - cannot process request');\n throw error;\n }\n\n const cacheKey = AdMeshSDK.buildPlatformResponseCacheKey(params.sessionId, messageId);\n const inFlightResponse = AdMeshSDK.inFlightPlatformResponses.get(cacheKey);\n if (inFlightResponse) {\n logger.log('[AdMeshSDK] ⏳ Reusing in-flight PlatformResponse request', {\n sessionId: params.sessionId,\n messageId,\n });\n return inFlightResponse;\n }\n \n // Calculate turn_index from messages length\n const turnIndex = params.messages ? params.messages.length : 0;\n \n // Detect device platform (web by default, could be enhanced with user agent detection)\n const devicePlatform = typeof window !== 'undefined' && window.navigator ? 'web' : 'web';\n \n // Detect form factor (could be enhanced with screen size detection)\n const formFactor = typeof window !== 'undefined' && window.innerWidth \n ? (window.innerWidth < 768 ? 'mobile' : window.innerWidth < 1024 ? 'tablet' : 'desktop')\n : 'desktop';\n const countryCode = normalizeCountryCode(params.location?.countryCode) || 'US';\n const pageContext = typeof window !== 'undefined' && window.location\n ? {\n url: window.location.href,\n origin: window.location.origin,\n referrer: document.referrer || undefined,\n host: window.location.hostname,\n }\n : undefined;\n\n // Build the canonical AIP PlatformRequest payload.\n // platform.platform_id will be normalized from the API key by the backend.\n const resolvedUserId = params.userId ?? this.config.userId;\n\n const payload: PlatformRequest = {\n spec_version: '1.0',\n message_id: messageId,\n timestamp: new Date().toISOString(),\n platform: {\n platform_id: 'placeholder',\n role: 'platform',\n software: {\n name: 'admesh_ui_sdk',\n version: params.model || '1.0.0'\n }\n },\n identity: {\n namespace: 'platform_user',\n value_hash: resolvedUserId || '',\n confidence: resolvedUserId ? 1.0 : 0.0\n },\n consent: {\n status: 'granted',\n source: 'admesh_ui_sdk',\n scope: {\n intent_based_monetization: true,\n agent_participation: true,\n measurement: true\n },\n constraints: {\n allow_identity_downstream: false\n }\n },\n classification_input: {\n type: 'interaction',\n interaction: {\n session: {\n id: params.sessionId,\n turn_index: turnIndex\n },\n surface: {\n channel: params.platformSurface || 'conversation',\n interaction_mode: 'text',\n platform: devicePlatform,\n form_factor: formFactor,\n locale: params.language || 'en-US',\n country: countryCode,\n publisher: 'placeholder'\n },\n input: {\n query_text: params.query,\n messages: params.messages || []\n },\n context: {\n location: {\n city: params.location?.city || undefined,\n state: params.location?.state || undefined,\n state_code: params.location?.stateCode || undefined,\n country: params.location?.country || undefined,\n country_code: countryCode,\n zipcode: params.location?.zipcode || undefined,\n latitude: params.location?.latitude,\n longitude: params.location?.longitude,\n },\n page: pageContext,\n },\n }\n },\n monetization: {\n enabled: true,\n pricing_model: 'CPX',\n auction: {\n enabled: true,\n floor: {\n amount: 0,\n currency: 'USD'\n }\n }\n }\n };\n\n // Validate query before sending\n if (!payload.classification_input.interaction?.input.query_text?.trim()) {\n logger.warn('[AdMeshSDK] ⚠️ Warning: Sending request with empty query_text');\n }\n\n const jsonBody = JSON.stringify(payload);\n logger.log('[AdMeshSDK] 📤 Sending canonical request to /aip/context', {\n messageId: payload.message_id,\n specVersion: payload.spec_version,\n classificationType: payload.classification_input.type,\n platformId: payload.platform.platform_id,\n surfaceChannel: payload.classification_input.interaction?.surface.channel,\n sessionId: payload.classification_input.interaction?.session?.id\n });\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`\n };\n\n if (this.config.extension) {\n headers['X-AdMesh-Source'] = 'extension';\n\n const sourceDomain = this.getExtensionSourceDomain();\n if (sourceDomain) {\n headers['X-AdMesh-Source-Domain'] = sourceDomain;\n }\n }\n\n const requestPromise = (async () => {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: jsonBody\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n const errorMessage = errorData.detail || `HTTP ${response.status}`;\n throw new Error(`Failed to fetch recommendation from /aip/context: ${errorMessage}`);\n }\n\n const data: PlatformResponse = await response.json();\n\n logger.log('[AdMeshSDK] 📥 Raw response from /aip/context:', {\n status: data.status,\n recommendationId: data.recommendation_id,\n hasRecommendation: !!data.recommendation,\n hasTracking: !!data.tracking,\n hasDelegation: !!data.delegation,\n topLevelKeys: Object.keys(data)\n });\n logger.log('[AdMeshSDK] 📦 Full PlatformResponse received from /aip/context', data);\n return data as PlatformResponse;\n })();\n\n AdMeshSDK.inFlightPlatformResponses.set(cacheKey, requestPromise);\n\n try {\n return await requestPromise;\n } finally {\n AdMeshSDK.inFlightPlatformResponses.delete(cacheKey);\n }\n }\n\n async trackPublisherAssistantEvent(\n event: PublisherAssistantAnalyticsEvent | PublisherAssistantAnalyticsEvent[],\n ): Promise<void> {\n const payload = Array.isArray(event) ? { events: event } : event;\n const response = await fetch(`${this.apiBaseUrl}/analytics/publisher-assistant/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '');\n throw new Error(`Failed to track publisher assistant analytics (${response.status}): ${errorBody}`);\n }\n }\n\n /**\n * Fire exposure for sponsored followup\n * \n * @param exposureUrl - The exposure URL to fire (can use regular exposure_url)\n * @param recommendationId - The recommendation ID\n * @param sessionId - The session ID\n */\n fireFollowupExposure(exposureUrl: string, recommendationId: string, sessionId: string): void {\n const tracker = this.getTracker();\n tracker.fireFollowupExposure(exposureUrl, recommendationId, sessionId);\n }\n\n /**\n * Fire engagement for sponsored followup\n * \n * @param engagementUrl - The engagement URL to fire\n * @param recommendationId - The recommendation ID\n * @param sessionId - The session ID\n * @returns Promise that resolves when engagement is fired\n */\n async fireFollowupEngagement(engagementUrl: string, recommendationId: string, sessionId: string): Promise<void> {\n const tracker = this.getTracker();\n return tracker.fireFollowupEngagement(engagementUrl, recommendationId, sessionId);\n }\n}\n\nexport default AdMeshSDK;\n","/**\n * WeaveResponseProcessor\n * \n * Automatically detects and enhances AdMesh recommendation links in organic LLM responses.\n * Handles:\n * - Automatic link detection (AdMesh tracking URLs)\n * - Label enhancement (<sub>Ad</sub> subscript labels)\n * - Exposure pixel triggering\n * - Streaming response support (MutationObserver)\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface DetectedLink {\n element: HTMLAnchorElement;\n href: string;\n text: string;\n hasAdLabel: boolean;\n matchedRecommendation?: {\n recommendation_id: string;\n click_url: string;\n exposure_url?: string;\n };\n}\n\nexport interface ProcessorConfig {\n autoAddLabels?: boolean;\n fireExposurePixels?: boolean;\n labelStyle?: {\n fontSize?: string;\n fontWeight?: string;\n color?: string;\n marginLeft?: string;\n };\n}\n\nexport interface ExposurePixelTarget {\n exposureUrl?: string;\n recommendationId?: string;\n linkElement: HTMLAnchorElement;\n}\n\nexport class WeaveResponseProcessor {\n private autoAddLabels: boolean;\n private fireExposurePixels: boolean;\n private labelStyle: Record<string, string>;\n private processedLinks: Set<string> = new Set();\n private mutationObserver: MutationObserver | null = null;\n\n constructor(config: ProcessorConfig = {}) {\n this.autoAddLabels = config.autoAddLabels !== false; // Default: true\n this.fireExposurePixels = config.fireExposurePixels !== false; // Default: true\n this.labelStyle = {\n fontSize: config.labelStyle?.fontSize || '0.75em',\n fontWeight: config.labelStyle?.fontWeight || 'bold',\n color: config.labelStyle?.color || '#666',\n marginLeft: config.labelStyle?.marginLeft || '2px'\n };\n }\n\n /**\n * Get links to process with CSS selector optimization\n *\n * Optimized approach:\n * 1. Use CSS selector to find AdMesh links (97% faster)\n * - Matches: api.useadmesh.com/click/*, *.useadmesh.com/click/*\n * 2. Fallback to scanning all links if selector finds nothing\n * 3. Recommendation validation ensures accuracy\n */\n private getLinksToProcess(container: HTMLElement): HTMLAnchorElement[] {\n // Try optimized selector first for AdMesh links\n // Matches both api.useadmesh.com and *.useadmesh.com domains\n const optimizedSelector = 'a[href*=\"/click/\"][href*=\"admesh.com\"], a[href*=\"/click/\"][href*=\"useadmesh.com\"]';\n const optimizedLinks = container.querySelectorAll(optimizedSelector);\n\n if (optimizedLinks.length > 0) {\n return Array.from(optimizedLinks) as HTMLAnchorElement[];\n }\n\n // Fallback: scan all links\n return Array.from(container.querySelectorAll('a')) as HTMLAnchorElement[];\n }\n\n /**\n * Scan container for ALL links and process only AdMesh recommendation links\n *\n * This method:\n * 1. Scans container for all <a> tags (or uses optimized selector)\n * 2. If recommendations provided: Filters to only process links matching recommendation click_url values\n * 3. If NO recommendations: Detects links by URL pattern (api.useadmesh.com/click/*)\n * 4. Ignores non-AdMesh links (external links, documentation, etc.)\n * 5. Adds Ad labels to matching links\n * 6. Fires exposure pixels for each match\n *\n * NOTE: When recommendations array is empty, this method detects AdMesh links by URL pattern.\n * This is important for Weave Ad Format where the backend embeds links in the LLM response\n * and the frontend hook doesn't have access to the recommendations data.\n */\n scanAndProcessLinks(\n container: HTMLElement,\n recommendations: any[],\n onExposurePixel?: (target: ExposurePixelTarget) => void\n ): DetectedLink[] {\n if (!container) {\n return [];\n }\n\n const detectedLinks: DetectedLink[] = [];\n\n // If recommendations provided, use them for matching\n if (recommendations.length > 0) {\n // Get links to process (with optional optimization)\n const links = this.getLinksToProcess(container);\n\n // Build map of AdMesh click URLs for fast lookup\n const clickUrlMap = new Map(\n recommendations\n .map((r) => [r?.tracking?.click_url || r?.recommendation?.creative?.landing_page_url || '', r] as const)\n .filter(([clickUrl]) => !!clickUrl)\n );\n\n // Build map of brand URLs (redirect_url, url) for matching direct brand links\n const brandUrlMap = new Map<string, any>();\n recommendations.forEach((r: any) => {\n const redirectUrl = r?.recommendation?.creative?.landing_page_url;\n if (redirectUrl && typeof redirectUrl === 'string') {\n // Normalize URL (remove trailing slashes, query params for matching)\n const normalizedUrl = redirectUrl.trim().replace(/\\/$/, '');\n brandUrlMap.set(normalizedUrl, r);\n // Also match with trailing slash\n brandUrlMap.set(`${normalizedUrl}/`, r);\n }\n });\n\n links.forEach((link: HTMLAnchorElement) => {\n const href = link.getAttribute('href') || '';\n const linkKey = `${href}`;\n\n // Skip if already processed\n if (this.processedLinks.has(linkKey)) {\n return;\n }\n\n // First, check if link matches AdMesh click URL\n let recommendation = clickUrlMap.get(href);\n let actualHref = href;\n \n // If not found, check if link matches brand URL (redirect_url or url)\n if (!recommendation) {\n const normalizedHref = href.trim().replace(/\\/$/, '');\n recommendation = brandUrlMap.get(normalizedHref) || brandUrlMap.get(`${normalizedHref}/`);\n \n // If brand URL matched, replace it with click_url\n const recommendationClickUrl =\n recommendation?.tracking?.click_url ||\n recommendation?.recommendation?.creative?.landing_page_url;\n if (recommendation && recommendationClickUrl) {\n logger.log('[WeaveResponseProcessor] 🔄 Found brand URL match, replacing with click_url:', href);\n link.setAttribute('href', recommendationClickUrl);\n actualHref = recommendationClickUrl;\n }\n }\n \n // Process link if it matches a recommendation (either by click_url or brand URL)\n if (recommendation) {\n this.processedLinks.add(linkKey);\n\n // ALWAYS set target=\"_blank\" and rel=\"noopener noreferrer\" for AdMesh tracking links\n // This ensures all click_url links open in a new tab\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n\n const detectedLink: DetectedLink = {\n element: link,\n href: actualHref, // Use actual href (may be updated click_url)\n text: link.textContent || '',\n hasAdLabel: this.hasAdLabel(link),\n matchedRecommendation: {\n recommendation_id: recommendation?.recommendation_id || '',\n click_url:\n recommendation?.tracking?.click_url ||\n recommendation?.recommendation?.creative?.landing_page_url ||\n '',\n exposure_url: recommendation?.tracking?.exposure_url\n }\n };\n\n // Add label if not present\n if (this.autoAddLabels && !detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] 🏷️ Adding Ad label to matched recommendation link:', actualHref);\n this.addAdLabel(link);\n detectedLink.hasAdLabel = true;\n } else if (!this.autoAddLabels) {\n logger.log('[WeaveResponseProcessor] ℹ️ autoAddLabels is disabled, skipping label');\n } else if (detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link already has label, skipping');\n }\n\n // Fire exposure pixel\n const exposureUrl = recommendation?.tracking?.exposure_url;\n if (this.fireExposurePixels && exposureUrl && onExposurePixel && detectedLink.matchedRecommendation) {\n onExposurePixel({\n exposureUrl,\n recommendationId: detectedLink.matchedRecommendation.recommendation_id,\n linkElement: link\n });\n }\n\n detectedLinks.push(detectedLink);\n }\n });\n } else {\n // No recommendations provided - detect AdMesh links by URL pattern\n // This is used for Weave Ad Format where backend embeds links in LLM response\n // Links can be in formats like:\n // - https://api.useadmesh.com/click/...\n // - https://api.useadmesh.com/click/...\n // - https://useadmesh.com/click/...\n // - https://admesh.com/click/...\n // Get ALL links in container and filter programmatically\n const allLinks = Array.from(container.querySelectorAll('a')) as HTMLAnchorElement[];\n\n \n\n allLinks.forEach((link: HTMLAnchorElement) => {\n const href = link.getAttribute('href') || '';\n const linkKey = `${href}`;\n\n // Skip if already processed\n if (this.processedLinks.has(linkKey)) {\n return;\n }\n\n // Check if this is an AdMesh link by examining the URL\n const isAdMeshLink = this.isAdMeshLink(href);\n\n if (isAdMeshLink) {\n\n this.processedLinks.add(linkKey);\n\n const detectedLink: DetectedLink = {\n element: link,\n href,\n text: link.textContent || '',\n hasAdLabel: this.hasAdLabel(link),\n matchedRecommendation: undefined\n };\n\n // Set target=\"_blank\" and rel=\"noopener noreferrer\" for security\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n\n // Add label if not present\n if (this.autoAddLabels && !detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] 🏷️ Adding Ad label to pattern-matched AdMesh link:', href);\n this.addAdLabel(link);\n detectedLink.hasAdLabel = true;\n } else if (!this.autoAddLabels) {\n logger.log('[WeaveResponseProcessor] ℹ️ autoAddLabels is disabled, skipping label');\n } else if (detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link already has label, skipping');\n }\n\n // Fire exposure tracking with converted exposure URL\n // For Weave Ad Format: LLM embeds click URLs in response text, so we convert to exposure URL\n if (this.fireExposurePixels && onExposurePixel) {\n const exposureUrl = this.convertClickUrlToExposureUrl(href);\n onExposurePixel({\n exposureUrl,\n recommendationId: this.extractRecommendationIdFromUrl(href),\n linkElement: link\n });\n }\n\n detectedLinks.push(detectedLink);\n }\n });\n\n \n }\n\n return detectedLinks;\n }\n\n /**\n * Check if link already has Ad label\n *\n * This method checks for Ad labels on BOTH sides of the link:\n * - Previous sibling (left side): Ad link text\n * - Next sibling (right side): link text Ad\n * - Inside the link itself (as a child element)\n *\n * This prevents duplicate label rendering when the LLM response\n * already contains Ad labels in any position.\n */\n private hasAdLabel(link: HTMLAnchorElement): boolean {\n // First, check if link itself contains Ad in its text content or as a child\n const linkText = link.textContent || '';\n if (linkText.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link text contains Ad label');\n return true;\n }\n\n // Check for Ad label as a direct child element (e.g., <a>text<sub>Ad</sub></a>)\n const childElements = link.querySelectorAll('sub, span');\n for (const child of Array.from(childElements)) {\n if (child.textContent?.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link has Ad label as child element');\n return true;\n }\n }\n\n // Check PREVIOUS sibling (left side) for Ad label\n let prevNode = link.previousSibling;\n\n // Skip text nodes that are just whitespace\n while (prevNode && prevNode.nodeType === Node.TEXT_NODE) {\n const text = prevNode.textContent || '';\n if (text.trim() === '') {\n prevNode = prevNode.previousSibling;\n continue;\n }\n // If we find non-whitespace text, check if it contains Ad\n if (text.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in previous text sibling');\n return true;\n }\n break;\n }\n\n // Check if previous element node is a <sub> or <span> with Ad label\n if (prevNode && prevNode.nodeType === Node.ELEMENT_NODE) {\n const element = prevNode as HTMLElement;\n const tagName = element.tagName.toUpperCase();\n if ((tagName === 'SUB' || tagName === 'SPAN') &&\n element.textContent?.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in previous element sibling:', tagName);\n return true;\n }\n }\n\n // Check NEXT sibling (right side) for Ad label\n let nextNode = link.nextSibling;\n\n // Skip text nodes that are just whitespace\n while (nextNode && nextNode.nodeType === Node.TEXT_NODE) {\n const text = nextNode.textContent || '';\n if (text.trim() === '') {\n nextNode = nextNode.nextSibling;\n continue;\n }\n // If we find non-whitespace text, check if it contains Ad\n if (text.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in next text sibling');\n return true;\n }\n break;\n }\n\n // Check if next element node is a <sub> or <span> with Ad label\n if (nextNode && nextNode.nodeType === Node.ELEMENT_NODE) {\n const element = nextNode as HTMLElement;\n const tagName = element.tagName.toUpperCase();\n if ((tagName === 'SUB' || tagName === 'SPAN') &&\n element.textContent?.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in next element sibling:', tagName);\n return true;\n }\n }\n\n logger.log('[WeaveResponseProcessor] ℹ️ No existing Ad label found');\n return false;\n }\n\n /**\n * Add Ad label as subscript after link with \"Why this ad?\" tooltip\n *\n * This method:\n * 1. Removes any Ad label on the LEFT side (previous sibling)\n * 2. Creates a <sub> element with Ad text\n * 3. Positions it immediately after the link (to the RIGHT)\n * 4. Adds tooltip styling with default cursor (not help cursor)\n * 5. Adds click handler for tooltip interaction\n * 6. Ensures only ONE label per link, always on the RIGHT side\n */\n private addAdLabel(link: HTMLAnchorElement): void {\n logger.log('[WeaveResponseProcessor] 🏷️ Attempting to add Ad label to link:', link.href);\n \n // Verify link is still in the DOM\n if (!link.isConnected) {\n logger.warn('[WeaveResponseProcessor] ⚠️ Link is not in DOM, cannot add label');\n return;\n }\n\n // Double-check that Ad label doesn't already exist to prevent duplicates\n if (this.hasAdLabel(link)) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link already has Ad label, skipping');\n return;\n }\n\n // Verify parent node exists before proceeding\n const parentNode = link.parentNode;\n if (!parentNode) {\n logger.error('[WeaveResponseProcessor] ❌ Link has no parent node, cannot add label');\n return;\n }\n\n // Remove any Ad label on the LEFT side (previous sibling)\n this.removeLeftAdLabel(link);\n\n // Create the Ad label as a <sub> element\n const subLabel = document.createElement('sub');\n subLabel.textContent = 'Ad';\n subLabel.style.fontSize = this.labelStyle.fontSize;\n subLabel.style.fontWeight = this.labelStyle.fontWeight;\n subLabel.style.color = this.labelStyle.color;\n subLabel.style.marginLeft = this.labelStyle.marginLeft;\n\n // Add tooltip styling with default cursor (not help cursor)\n subLabel.style.cursor = 'pointer';\n subLabel.style.borderBottom = `1px dotted ${this.labelStyle.color}`;\n subLabel.style.whiteSpace = 'nowrap';\n subLabel.title = 'Why this ad? This is a sponsored recommendation based on your search query.';\n\n // Track tooltip state for click interactions\n let isTooltipVisible = false;\n\n // Add hover effect for visual feedback\n subLabel.addEventListener('mouseenter', () => {\n subLabel.style.opacity = '0.7';\n });\n\n subLabel.addEventListener('mouseleave', () => {\n subLabel.style.opacity = '1';\n // Hide tooltip on mouse leave if it was shown by click\n if (isTooltipVisible) {\n isTooltipVisible = false;\n }\n });\n\n // Add click handler to toggle tooltip visibility\n subLabel.addEventListener('click', (event: Event) => {\n event.stopPropagation();\n isTooltipVisible = !isTooltipVisible;\n\n if (isTooltipVisible) {\n // Show tooltip by adding visual indicator\n subLabel.style.textDecoration = 'underline';\n subLabel.style.opacity = '0.7';\n } else {\n // Hide tooltip visual indicator\n subLabel.style.textDecoration = 'none';\n subLabel.style.opacity = '1';\n }\n });\n\n // Close tooltip when clicking elsewhere on the page\n const closeTooltipOnClickOutside = (event: Event) => {\n if (isTooltipVisible && event.target !== subLabel) {\n isTooltipVisible = false;\n subLabel.style.textDecoration = 'none';\n subLabel.style.opacity = '1';\n }\n };\n\n document.addEventListener('click', closeTooltipOnClickOutside);\n\n // Insert the label immediately after the link (to the right)\n // Handle edge cases: if nextSibling is null, appendChild will insert at the end\n try {\n const nextSibling = link.nextSibling;\n if (nextSibling) {\n parentNode.insertBefore(subLabel, nextSibling);\n logger.log('[WeaveResponseProcessor] ✅ Ad label inserted before next sibling');\n } else {\n // If no next sibling, append to parent (inserts after link)\n parentNode.appendChild(subLabel);\n logger.log('[WeaveResponseProcessor] ✅ Ad label appended to parent (no next sibling)');\n }\n \n // Verify label was successfully inserted\n if (subLabel.isConnected && subLabel.parentNode === parentNode) {\n logger.log('[WeaveResponseProcessor] ✅ Ad label successfully added to link:', link.href);\n } else {\n logger.error('[WeaveResponseProcessor] ❌ Ad label insertion failed - label not in DOM');\n }\n } catch (error) {\n logger.error('[WeaveResponseProcessor] ❌ Error inserting Ad label:', error);\n }\n }\n\n /**\n * Remove Ad label from the LEFT side (previous sibling) of a link\n *\n * This ensures that only ONE Ad label appears on the RIGHT side,\n * removing any duplicate labels that might be on the left.\n */\n private removeLeftAdLabel(link: HTMLAnchorElement): void {\n let prevNode = link.previousSibling;\n\n // Skip text nodes that are just whitespace\n while (prevNode && prevNode.nodeType === Node.TEXT_NODE) {\n const text = prevNode.textContent || '';\n if (text.trim() === '') {\n prevNode = prevNode.previousSibling;\n continue;\n }\n // If we find non-whitespace text containing Ad, remove it\n if (text.includes('Ad')) {\n prevNode.parentNode?.removeChild(prevNode);\n return;\n }\n break;\n }\n\n // Check if previous element node is a <sub> or <span> with Ad label\n if (prevNode && prevNode.nodeType === Node.ELEMENT_NODE) {\n const element = prevNode as HTMLElement;\n if ((element.tagName === 'SUB' || element.tagName === 'SPAN') &&\n element.textContent?.includes('Ad')) {\n element.parentNode?.removeChild(element);\n }\n }\n }\n\n /**\n * Check if a URL is an AdMesh link\n *\n * Detects AdMesh links by checking if the URL contains /click/ and matches AdMesh patterns:\n * - https://api.useadmesh.com/click/...\n * - https://api.useadmesh.com/click/...\n * - http://localhost:8000/click/... (local development)\n * - Any URL with /click/ that looks like an AdMesh tracking URL\n */\n private isAdMeshLink(href: string): boolean {\n if (!href) {\n return false;\n }\n\n // Check if URL contains /click/ (AdMesh tracking pattern)\n if (!href.includes('/click/')) {\n return false;\n }\n\n // Check for known AdMesh domains\n const admeshDomains = [\n 'useadmesh.com',\n 'admesh.com',\n 'api.useadmesh.com',\n 'api.admesh.com',\n 'localhost:8000', // Local development\n 'localhost:3000', // Local development (if proxied)\n ];\n\n const isKnownDomain = admeshDomains.some(domain => href.includes(domain));\n if (isKnownDomain) {\n return true;\n }\n\n // Fallback: if URL has /click/ and looks like a tracking URL, treat it as AdMesh\n // This handles cases where the domain might be different but the pattern matches\n try {\n const url = new URL(href);\n const pathname = url.pathname;\n\n // Check if pathname starts with /click/ (AdMesh pattern)\n if (pathname.startsWith('/click/')) {\n return true;\n }\n } catch {\n // If URL parsing fails, check string pattern\n if (href.match(/\\/click\\/[a-zA-Z0-9\\-_]+/)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Extract recommendation ID from AdMesh click URL\n *\n * URL format: https://api.useadmesh.com/click/{recommendation_id}?...\n * Returns the recommendation_id portion or empty string if extraction fails\n */\n private extractRecommendationIdFromUrl(url: string): string {\n try {\n // Try to extract from /click/{id} pattern\n const match = url.match(/\\/click\\/([^/?]+)/);\n if (match && match[1]) {\n return match[1];\n }\n // Fallback to empty string (recommendation_id should be in URL)\n return '';\n } catch {\n return url;\n }\n }\n\n /**\n * Convert AdMesh click URL to exposure URL (Weave Ad Format only)\n *\n * This is ONLY used for Weave Ad Format where the LLM embeds click URLs in the response text\n * and we need to derive the exposure URL for tracking.\n *\n * Click URL format: https://api.useadmesh.com/click/r/{aid}?aid={aid}&rid={rid}&nonce={nonce}&exp={exp}&sig={sig}\n * Exposure URL format: https://api.useadmesh.com/exposure?aid={aid}&rid={rid}&nonce={nonce}&exp={exp}&sig={sig}&cpx={cpx}\n *\n * This method:\n * 1. Parses the click URL to extract the base domain and query parameters\n * 2. Replaces the /click/r/{aid} path with /exposure\n * 3. Preserves all tracking parameters (aid, rid, nonce, exp, sig)\n * 4. Adds cpx=0 as default (actual CPX value is set server-side)\n *\n * @param clickUrl - The AdMesh click tracking URL\n * @returns The corresponding exposure tracking URL, or the original URL if conversion fails\n */\n private convertClickUrlToExposureUrl(clickUrl: string): string {\n try {\n const url = new URL(clickUrl);\n\n // Extract the base URL (protocol + host)\n const baseUrl = `${url.protocol}//${url.host}`;\n\n // Build exposure endpoint URL\n const exposureUrl = `${baseUrl}/exposure`;\n\n // Preserve all existing query parameters from click URL\n // These include: aid, rid, nonce, exp, sig\n const params = new URLSearchParams(url.search);\n\n // Add cpx parameter if not present (default to 0, actual value is set server-side)\n if (!params.has('cpx')) {\n params.set('cpx', '0');\n }\n\n // Construct final exposure URL with all parameters\n return `${exposureUrl}?${params.toString()}`;\n } catch (error) {\n // If URL parsing fails, log warning and return original URL\n logger.warn('[WeaveResponseProcessor] Failed to convert click URL to exposure URL');\n return clickUrl;\n }\n }\n\n /**\n * Watch container for new links (streaming support)\n */\n watchForNewLinks(\n container: HTMLElement,\n recommendations: any[],\n onExposurePixel?: (target: ExposurePixelTarget) => void\n ): void {\n if (!container) {\n return;\n }\n\n // Stop existing observer\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n }\n\n // Create observer for new nodes\n this.mutationObserver = new MutationObserver(() => {\n this.scanAndProcessLinks(container, recommendations, onExposurePixel);\n });\n\n this.mutationObserver.observe(container, {\n childList: true,\n subtree: true,\n characterData: false\n });\n }\n\n /**\n * Stop watching for new links\n */\n stopWatching(): void {\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n }\n\n /**\n * Clear processed links cache\n */\n clearCache(): void {\n this.processedLinks.clear();\n }\n}\n\nexport default WeaveResponseProcessor;\n","import { useAdMeshContext } from '../context/AdMeshContext';\n\n/**\n * Hook to access AdMesh SDK and tracking state\n *\n * Must be used within an <AdMeshProvider>\n *\n * @returns Object with SDK instance and tracking methods\n *\n * @example\n * ```tsx\n * const { sdk, sessionId, markMessageAsProcessed } = useAdMesh();\n *\n * // Use SDK to show recommendations\n * await sdk?.showRecommendations({\n * query: 'user query',\n * containerId: 'recommendations-container',\n * sessionId,\n * messageId\n * });\n *\n * // Mark message as processed to avoid duplicates\n * markMessageAsProcessed(messageId);\n * ```\n */\nexport function useAdMesh() {\n const context = useAdMeshContext();\n\n return {\n /** AdMesh SDK instance */\n sdk: context.sdk,\n\n /** API key */\n apiKey: context.apiKey,\n\n /** Session ID */\n sessionId: context.sessionId,\n\n /** Theme configuration */\n theme: context.theme,\n\n /** User language in BCP 47 format (e.g., \"en-US\") - from AdMeshProvider */\n language: context.language,\n\n /** Detailed user location from AdMeshProvider */\n location: context.location,\n\n /** Anonymous hashed user ID - from AdMeshProvider */\n userId: context.userId,\n\n /** AI model identifier (e.g., \"gpt-4o\") - from AdMeshProvider */\n model: context.model,\n\n /** Conversation history - from AdMeshProvider */\n messages: context.messages,\n\n /** Set of processed message IDs (for deduplication) */\n processedMessageIds: context.processedMessageIds,\n\n /** Ephemeral per-session recommendation results keyed by messageId */\n recommendationResults: context.recommendationResults,\n activeDelegationSession: context.activeDelegationSession,\n\n /** Mark a message as processed to prevent duplicate recommendations */\n markMessageAsProcessed: context.markMessageAsProcessed,\n\n /** Check if a message has already been processed */\n isMessageProcessed: context.isMessageProcessed,\n\n /** Store the recommendation result for a message within the current provider session */\n setRecommendationResult: context.setRecommendationResult,\n\n /** Read a stored recommendation result for a message within the current provider session */\n getRecommendationResult: context.getRecommendationResult,\n\n /** Check whether a recommendation result exists for a message within the current provider session */\n hasRecommendationResult: context.hasRecommendationResult,\n setActiveDelegationSession: context.setActiveDelegationSession,\n getActiveDelegationSession: context.getActiveDelegationSession,\n hasActiveDelegationSession: context.hasActiveDelegationSession,\n refreshDelegationActivity: context.refreshDelegationActivity,\n stopDelegationSession: context.stopDelegationSession,\n };\n}\n\nexport default useAdMesh;\n","'use client';\n\nimport type { FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { PlatformResponse, AdMeshTheme } from '../types/index';\nimport { AdMeshSDK } from '../sdk/AdMeshSDK';\nimport { AdMeshViewabilityTracker } from './AdMeshViewabilityTracker';\n\nexport interface AdMeshFollowupProps {\n recommendation: PlatformResponse;\n theme?: AdMeshTheme;\n sdk: AdMeshSDK;\n sessionId: string;\n onExecuteQuery?: (query: string) => void | Promise<void>;\n}\n\nconst PlusIcon = ({ className, size = 20 }: { className?: string; size?: number }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n);\n\n/**\n * AdMeshFollowup - Sponsored Follow-up Component\n * \n * Displays sponsored follow-up suggestions as optional fields on any recommendation.\n * Follow-ups use the same recommendation_id as the primary ad and are rendered separately\n * in a followups_container_id. This component handles all exposure and engagement tracking\n * internally - platforms only need to provide an onExecuteQuery hook for query execution.\n * \n * @example\n * ```tsx\n * <AdMeshFollowup\n * recommendation={recommendation}\n * sdk={sdk}\n * sessionId={sessionId}\n * theme={theme}\n * onExecuteQuery={(query) => {\n * // Platform's query execution logic\n * executeQuery(query);\n * }}\n * />\n * ```\n */\nexport const AdMeshFollowup: FC<AdMeshFollowupProps> = ({\n recommendation,\n theme: _theme,\n sdk,\n sessionId,\n onExecuteQuery,\n}) => {\n const followupSuggestion =\n recommendation.recommendation?.creative?.follow_up_suggestion &&\n recommendation.tracking?.followup_engagement_url &&\n recommendation.tracking?.followup_exposure_url\n ? {\n query: recommendation.recommendation.creative.follow_up_suggestion,\n engagement_url: recommendation.tracking.followup_engagement_url,\n exposure_url: recommendation.tracking.followup_exposure_url,\n }\n : null;\n const followupQuery = followupSuggestion?.query;\n const followupEngagementUrl = followupSuggestion?.engagement_url;\n const followupExposureUrl = followupSuggestion?.exposure_url;\n const recommendationId = recommendation.recommendation_id;\n const productId = recommendation.recommendation?.offerId || recommendationId;\n\n // Validate required fields\n if (!followupQuery || !followupEngagementUrl || !followupExposureUrl) {\n logger.log('[AdMeshFollowup] Missing followup_suggestion.query, engagement_url, or exposure_url - not rendering');\n return null;\n }\n\n // Handle follow-up click/selection\n const handleFollowupClick = async () => {\n try {\n // Fire engagement tracking (SDK handles this automatically)\n if (followupEngagementUrl && recommendationId) {\n logger.log('[AdMeshFollowup] 🎯 Firing follow-up engagement tracking');\n await sdk.fireFollowupEngagement(followupEngagementUrl, recommendationId, sessionId);\n }\n\n // Execute query via platform hook\n if (onExecuteQuery && followupQuery) {\n logger.log(`[AdMeshFollowup] 🔍 Executing query: ${followupQuery}`);\n await onExecuteQuery(followupQuery);\n } else {\n logger.warn('[AdMeshFollowup] ⚠️ onExecuteQuery not provided - cannot execute query');\n }\n } catch (error) {\n logger.error('[AdMeshFollowup] ❌ Error handling follow-up click:', error);\n }\n };\n\n // Platform-native styling (matching Perplexica's \"Related\" section)\n // We use inline styles that can be overridden, but default to blending in\n\n return (\n <AdMeshViewabilityTracker\n productId={productId}\n recommendationId={recommendationId || ''}\n exposureUrl={followupExposureUrl}\n sessionId={sessionId}\n className=\"admesh-followup-container\"\n style={{\n width: '100%',\n }}\n >\n <div className=\"flex flex-col space-y-3 text-sm admesh-followup-wrapper\">\n {/* Divider matching platform style */}\n <div className=\"h-px w-full bg-[#E5E5E5] dark:bg-[#262626] admesh-divider\" />\n\n <div\n onClick={handleFollowupClick}\n className=\"cursor-pointer flex flex-row justify-between font-medium space-x-2 items-center group\"\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n handleFollowupClick();\n }\n }}\n aria-label={`Sponsored follow-up: ${followupQuery}`}\n >\n <p className=\"transition duration-200 text-[#000] dark:text-[#FFF] hover:text-[#24A0ED] admesh-followup-text\">\n {followupQuery}\n </p>\n <div className=\"flex flex-row items-center space-x-2\">\n <span className=\"text-xs text-gray-500 dark:text-gray-400 italic admesh-ad-label\">\n Ad\n </span>\n <PlusIcon\n size={20}\n className=\"text-[#24A0ED] flex-shrink-0 admesh-plus-icon\"\n />\n </div>\n </div>\n </div>\n </AdMeshViewabilityTracker>\n );\n};\n","'use client';\n\nimport { useCallback, useEffect, useState, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useAdMesh } from '../hooks/useAdMesh';\nimport { logger } from '../utils/logger';\nimport { AdMeshCompactCard } from './AdMeshCompactCard';\nimport { AdMeshFollowup } from './AdMeshFollowup';\nimport type {\n PlatformResponse,\n DelegationActivationPayload,\n ActiveDelegationSession,\n} from '../types/index';\n\nexport interface AdMeshRecommendationsProps {\n /** Optional callback when recommendations are shown */\n onRecommendationsShown?: (messageId: string, recommendation: PlatformResponse | null) => void;\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /**\n * Message ID for per-message recommendations.\n *\n * This is the primary identifier for fetching recommendations for a specific message.\n */\n messageId?: string;\n\n /**\n * User query text for generating recommendations.\n *\n * This is the query that will be used to fetch recommendations from the backend.\n * Typically the user's question or search query.\n *\n * IMPORTANT: This should be a non-empty string. If not provided or empty,\n * the component will skip rendering to prevent 400 Bad Request errors.\n * The backend requires a valid query parameter.\n */\n query?: string;\n\n /** Legacy bridge CTA callback; prefer onStartDelegation. */\n onPasteToInput?: (content: string) => void;\n\n /** Called when the SDK needs host approval before starting a delegated brand flow. */\n onDelegationConsent?: (recommendation: PlatformResponse) => boolean | Promise<boolean>;\n\n /** Called with normalized delegation metadata after consent/engagement. */\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n\n /** Called after consent is granted so the host can create/open the delegation session. */\n onStartDelegation?: (recommendation: PlatformResponse) => void | Promise<void>;\n\n /**\n * Optional container ID for follow-up suggestions.\n * When provided and the recommendation includes a followup_suggestion,\n * the SDK will automatically render the follow-up in this container.\n */\n followups_container_id?: string;\n\n /**\n * Callback to execute query when follow-up is selected (required for follow-up functionality).\n * When a user clicks on a follow-up suggestion, this callback is invoked with the followup_suggestion.query.\n * This allows the platform to continue the conversation with the sponsored follow-up query.\n */\n onExecuteQuery?: (query: string) => void | Promise<void>;\n\n /**\n * Callback when a sponsored followup is detected.\n * This allows third-party applications to integrate the sponsored followup query into their own\n * followup suggestions UI (e.g., adding to a suggestions list, related questions section, etc.).\n * \n * When a user clicks the followup suggestion, the application should:\n * 1. Fire engagement tracking by calling the followupEngagementUrl\n * 2. Execute the followupQuery (e.g., submit it as a new user query)\n * \n * @param followupQuery - The sponsored followup query text to display to the user\n * @param followupEngagementUrl - The engagement tracking URL to call when user clicks the followup\n * @param recommendationId - The recommendation ID for tracking and correlation\n * \n * @example\n * ```tsx\n * <AdMeshRecommendations\n * onFollowupDetected={(query, engagementUrl, recId) => {\n * // Add to your suggestions list\n * setSuggestions(prev => [...prev, {\n * text: query,\n * sponsored: true,\n * engagementUrl,\n * recommendationId: recId\n * }]);\n * }}\n * />\n * ```\n */\n\n onFollowupDetected?: (\n followupSuggestion: any, // Will be updated to proper type later\n recommendationId: string,\n ) => void;\n\n /**\n * Signal indicating if the followup container is ready in the DOM.\n * \n * Useful for scenarios where the container is rendered conditionally or after a delay (e.g. streaming).\n * If provided, the component will wait until this is true before attempting to attach the portal.\n */\n isContainerReady?: boolean;\n\n /**\n * Optional user ID to override the context-provided user ID.\n * Useful for per-message or specific user tracking scenarios.\n */\n userId?: string;\n\n /**\n * Optional pre-fetched canonical platform result from an upstream backend flow.\n * When provided, the component reuses this payload and skips calling /aip/context.\n */\n initialRecommendation?: PlatformResponse;\n\n /**\n * Whether the rendered recommendation card should fire its primary exposure URL.\n * Defaults to true. Set false when the recommendation came from a sponsored follow-up click\n * and the click should only count as follow-up engagement.\n */\n triggerExposureUrl?: boolean;\n}\n\n/**\n * AdMeshRecommendations - Citation/Product Format Recommendation Display\n *\n * Displays recommendations as a separate UI component. Handles all the complexity:\n * - Uses provided messageId directly\n * - Generates container IDs for recommendations\n * - Calls SDK's showRecommendations()\n *\n * For Weave Ad Format (where AdMesh links are embedded in LLM response),\n * use WeaveAdFormatContainer component instead.\n *\n * @example\n * ```tsx\n * // Per-message recommendations with messageId\n * <AdMeshProvider apiKey={apiKey} sessionId={sessionId}>\n * {messages.map((msg) => (\n * <div key={msg.messageId}>\n * {msg.content}\n * {msg.role === 'assistant' && (\n * <AdMeshRecommendations\n * messageId={msg.messageId}\n * query={msg.userQuery}\n * />\n * )}\n * </div>\n * ))}\n * </AdMeshProvider>\n * ```\n *\n * @example\n * ```tsx\n * // Format is auto-detected from brand agent's preferred_format\n * <AdMeshProvider apiKey={apiKey} sessionId={sessionId}>\n * <Chat messages={messages} />\n * <AdMeshRecommendations\n * messageId={lastMessageId}\n * query=\"best CRM for small business\"\n * />\n * </AdMeshProvider>\n * ```\n */\nexport const AdMeshRecommendations = ({\n onRecommendationsShown,\n onError,\n messageId,\n query,\n userId: propUserId,\n initialRecommendation,\n triggerExposureUrl = true,\n followups_container_id,\n onPasteToInput,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n onExecuteQuery,\n onFollowupDetected,\n isContainerReady,\n}: AdMeshRecommendationsProps) => {\n const {\n sdk,\n sessionId,\n apiKey,\n language,\n location,\n userId: contextUserId,\n model,\n messages,\n theme,\n getRecommendationResult,\n hasRecommendationResult,\n setRecommendationResult,\n activeDelegationSession,\n setActiveDelegationSession,\n hasActiveDelegationSession,\n } = useAdMesh();\n const isFilledAuctionResponse = (\n response: PlatformResponse | null | undefined,\n ): response is PlatformResponse => {\n return !!response && response.status === 'generated' && !!response.recommendation;\n };\n \n // Use prop userId if provided, otherwise context userId\n const userId = propUserId || contextUserId;\n\n const [platformResult, setPlatformResult] = useState<PlatformResponse | null>(null);\n const [detectedFormat, setDetectedFormat] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Track fetched messageId to prevent duplicate fetches\n const fetchedMessageIdRef = useRef<string | null>(null);\n const isFetchingRef = useRef<boolean>(false);\n const reusedInitialRecommendationRef = useRef<boolean>(false);\n\n // Use refs for callbacks to avoid dependency issues\n const onRecommendationsShownRef = useRef(onRecommendationsShown);\n const onErrorRef = useRef(onError);\n\n // Update refs when callbacks change\n useEffect(() => {\n onRecommendationsShownRef.current = onRecommendationsShown;\n onErrorRef.current = onError;\n }, [onRecommendationsShown, onError]);\n\n // Reset fetched ref when messageId changes\n useEffect(() => {\n if (fetchedMessageIdRef.current !== messageId) {\n fetchedMessageIdRef.current = null;\n reusedInitialRecommendationRef.current = false;\n setPlatformResult(null);\n setDetectedFormat(null);\n }\n }, [messageId]);\n\n const hasActiveDelegatedSessionForConversation =\n hasActiveDelegationSession() &&\n activeDelegationSession?.session_id === sessionId;\n\n useEffect(() => {\n if (!messageId || !hasRecommendationResult(messageId)) {\n return;\n }\n\n if (hasActiveDelegatedSessionForConversation) {\n return;\n }\n\n const storedResult = getRecommendationResult(messageId);\n if (!storedResult) {\n logger.log('[AdMeshRecommendations] ♻️ Reusing stored no_match result from provider state');\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n return;\n }\n\n let selectedFormat: string = storedResult.recommendation?.format || 'tail';\n if (selectedFormat === 'weave' || selectedFormat === 'product_card') {\n selectedFormat = 'tail';\n }\n\n logger.log('[AdMeshRecommendations] ♻️ Reusing stored recommendation result from provider state', {\n messageId,\n recommendationId: storedResult.recommendation_id,\n format: storedResult.recommendation?.format,\n });\n setPlatformResult(storedResult);\n setDetectedFormat(selectedFormat);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n onRecommendationsShownRef.current?.(messageId, storedResult);\n }, [getRecommendationResult, hasRecommendationResult, hasActiveDelegatedSessionForConversation, messageId]);\n\n // Reuse upstream recommendation payload when available to avoid a second /aip/context call.\n useEffect(() => {\n if (!initialRecommendation || !messageId) {\n return;\n }\n\n if (hasActiveDelegatedSessionForConversation) {\n return;\n }\n\n try {\n const canonicalResponse = initialRecommendation;\n const initialStatus = initialRecommendation.status || 'unknown';\n if (!isFilledAuctionResponse(canonicalResponse)) {\n if (initialStatus === 'no_match') {\n logger.log('[AdMeshRecommendations] ℹ️ Initial recommendation returned no_match - rendering nothing');\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n setRecommendationResult(messageId, null);\n return;\n }\n throw new Error(`Initial recommendation is not a filled auction response (status=${initialStatus})`);\n }\n\n let selectedFormat: string = canonicalResponse.recommendation?.format || 'tail';\n if (selectedFormat === 'weave' || selectedFormat === 'product_card') {\n selectedFormat = 'tail';\n }\n\n setPlatformResult(canonicalResponse);\n setDetectedFormat(selectedFormat);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n setRecommendationResult(messageId, canonicalResponse);\n onRecommendationsShownRef.current?.(messageId, canonicalResponse);\n\n logger.log('[AdMeshRecommendations] ♻️ Using initial recommendation payload, skipping /aip/context fetch');\n logger.log('[AdMeshRecommendations] ✅ Accepted initial generated recommendation payload', {\n messageId,\n recommendationId: canonicalResponse.recommendation_id,\n format: canonicalResponse.recommendation?.format,\n brandName: canonicalResponse.recommendation?.creative?.brand_name,\n headline: canonicalResponse.recommendation?.creative?.headline,\n hasTracking: !!canonicalResponse.tracking,\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reusedInitialRecommendationRef.current = false;\n logger.warn(`[AdMeshRecommendations] ⚠️ Failed to reuse initial recommendation, will fall back to fetch: ${error.message}`);\n }\n }, [hasActiveDelegatedSessionForConversation, initialRecommendation, messageId, setRecommendationResult]);\n\n // Single fetch effect - fetch recommendation once and detect format\n useEffect(() => {\n // Validate required parameters\n if (!messageId || !query || query.trim() === '') {\n logger.log('[AdMeshRecommendations] ❌ Validation failed - missing required parameters');\n setIsLoading(false);\n return;\n }\n\n if (hasActiveDelegatedSessionForConversation) {\n logger.log('[AdMeshRecommendations] ⏸️ Delegated session active, skipping /aip/context fetch', {\n messageId,\n conversationSessionId: sessionId,\n delegationSessionId: activeDelegationSession?.delegation_session_id,\n });\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n isFetchingRef.current = false;\n return;\n }\n\n if (!sdk?.fetchPlatformResponse) {\n logger.log('[AdMeshRecommendations] SDK fetchPlatformResponse not available');\n setIsLoading(false);\n return;\n }\n\n if (reusedInitialRecommendationRef.current) {\n logger.log('[AdMeshRecommendations] ⏭️ Initial recommendation provided, skipping duplicate fetch');\n return;\n }\n\n // Prevent duplicate fetches for the same messageId\n if (fetchedMessageIdRef.current === messageId) {\n logger.log('[AdMeshRecommendations] ⏭️ Already fetched for this messageId, skipping duplicate fetch');\n return;\n }\n\n // Prevent concurrent fetches\n if (isFetchingRef.current) {\n logger.log('[AdMeshRecommendations] ⏭️ Fetch already in progress, skipping duplicate fetch');\n return;\n }\n\n logger.log('[AdMeshRecommendations] 📤 Fetching recommendation from /aip/context (single fetch)');\n\n const fetchRecommendations = async () => {\n try {\n isFetchingRef.current = true;\n setIsLoading(true);\n setError(null);\n\n // Single fetch call\n // Note: messages is optional - only pass if available\n const result = await sdk.fetchPlatformResponse({\n query: query.trim(),\n sessionId: sessionId,\n messageId: messageId, // REQUIRED: messageId is mandatory\n language: language,\n location: location,\n userId: userId,\n model: model,\n ...(messages && messages.length > 0 && { messages }), // Optional: only pass if messages exist\n });\n const resultStatus = (result as any)?.status || 'unknown';\n if (!isFilledAuctionResponse(result)) {\n if (resultStatus === 'no_match') {\n logger.log('[AdMeshRecommendations] ℹ️ No recommendation returned from /aip/context');\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n isFetchingRef.current = false;\n fetchedMessageIdRef.current = messageId;\n setRecommendationResult(messageId, null);\n return;\n }\n throw new Error(`No filled recommendation returned from /aip/context (status=${resultStatus})`);\n }\n\n setPlatformResult(result);\n logger.log('[AdMeshRecommendations] ✅ Accepted fetched generated recommendation payload', {\n messageId,\n recommendationId: result.recommendation_id,\n format: result.recommendation?.format,\n brandName: result.recommendation?.creative?.brand_name,\n headline: result.recommendation?.creative?.headline,\n hasTracking: !!result.tracking,\n });\n\n let selectedFormat: string = result.recommendation?.format || 'tail';\n if (selectedFormat === 'weave' || selectedFormat === 'product_card') {\n selectedFormat = 'tail';\n }\n\n setDetectedFormat(selectedFormat);\n fetchedMessageIdRef.current = messageId; // Mark as fetched\n setRecommendationResult(messageId, result);\n logger.log('[AdMeshRecommendations] 📊 Format detection:', {\n preferred_format: result.recommendation?.format,\n selected_format: selectedFormat\n });\n\n setIsLoading(false);\n isFetchingRef.current = false;\n onRecommendationsShownRef.current?.(messageId, result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n // Log error but don't break the UI - network errors are expected in some scenarios\n if (error.message.includes('Failed to fetch') || error.message.includes('NetworkError')) {\n logger.warn(`[AdMeshRecommendations] ⚠️ Network error fetching recommendations(non - critical): ${error.message} `);\n } else {\n logger.error(`[AdMeshRecommendations] ❌ Error fetching recommendations: ${error.message} `);\n }\n setError(error);\n setIsLoading(false);\n isFetchingRef.current = false;\n onErrorRef.current?.(error);\n }\n };\n\n fetchRecommendations();\n }, [\n activeDelegationSession?.delegation_session_id,\n hasActiveDelegatedSessionForConversation,\n sdk,\n sessionId,\n messageId,\n query,\n language,\n location,\n userId,\n model,\n initialRecommendation,\n setRecommendationResult,\n ]); // Removed messages, onRecommendationsShown, onError from dependencies\n\n useEffect(() => {\n if (!platformResult || !onFollowupDetected) {\n return;\n }\n\n const followupSuggestion =\n platformResult.recommendation?.creative?.follow_up_suggestion &&\n platformResult.tracking?.followup_engagement_url &&\n platformResult.tracking?.followup_exposure_url\n ? {\n label: platformResult.recommendation.creative.follow_up_suggestion,\n query: platformResult.recommendation.creative.follow_up_suggestion,\n engagement_url: platformResult.tracking.followup_engagement_url,\n exposure_url: platformResult.tracking.followup_exposure_url,\n }\n : null;\n if (!followupSuggestion) {\n return;\n }\n\n onFollowupDetected(followupSuggestion, platformResult.recommendation_id);\n }, [platformResult, onFollowupDetected]);\n\n const handleSdkDelegationActivated = useCallback(\n async (payload: DelegationActivationPayload) => {\n if (!sdk || !sessionId) {\n throw new Error('AdMesh SDK activation requires an initialized session');\n }\n\n const response = await fetch(`${sdk.getApiBaseUrl()}/aip/delegation/activate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n session_id: sessionId,\n recommendation_id: payload.recommendation_id,\n metadata: payload.metadata,\n }),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new Error(`Failed to activate delegation session: ${response.status} ${errorBody}`);\n }\n\n const activation = await response.json();\n const resolvedPayload: DelegationActivationPayload = {\n ...payload,\n delegation_session_id: activation.delegation_session_id || payload.delegation_session_id,\n session_id: activation.session_id || sessionId,\n brand_id: activation.brand_id || payload.brand_id,\n brand_name: activation.brand_name || payload.brand_name,\n mcp_endpoint: activation.mcp_endpoint,\n eligibility_reason: activation.eligibility_reason || payload.eligibility_reason,\n delegate_reason: activation.delegate_reason || payload.delegate_reason,\n session_goal: activation.session_goal || payload.session_goal,\n desired_outcome_type: activation.desired_outcome_type || payload.desired_outcome_type,\n required_user_inputs: activation.required_user_inputs || payload.required_user_inputs || [],\n required_consent_types: activation.required_consent_types || payload.required_consent_types || [],\n success_outcome: activation.success_outcome || payload.success_outcome,\n fallback_message: activation.fallback_message || payload.fallback_message,\n session_mode: 'inline',\n status: activation.status || 'active',\n capabilities: activation.capabilities || payload.capabilities || [],\n allowed_data_types: activation.allowed_data_types || payload.allowed_data_types || [],\n auth_model: activation.auth_model || payload.auth_model,\n handoff_protocol: activation.handoff_protocol || payload.handoff_protocol,\n supported_actions: activation.supported_actions || payload.supported_actions || [],\n metadata: activation.metadata || payload.metadata,\n };\n\n const activeSession: ActiveDelegationSession = {\n delegation_session_id: activation.delegation_session_id,\n recommendation_id: payload.recommendation_id,\n session_id: activation.session_id || sessionId,\n brand_agent_id: activation.brand_agent_id,\n brand_id: activation.brand_id || payload.brand_id,\n brand_name: activation.brand_name || payload.brand_name || 'Brand',\n mcp_endpoint: activation.mcp_endpoint,\n status: activation.status || 'active',\n activated_at: activation.created_at,\n last_activity_at: activation.updated_at,\n expires_at: activation.expires_at || activation.updated_at,\n eligibility_reason: activation.eligibility_reason || payload.eligibility_reason,\n delegate_reason: activation.delegate_reason || payload.delegate_reason,\n session_goal: activation.session_goal || payload.session_goal,\n desired_outcome_type: activation.desired_outcome_type || payload.desired_outcome_type,\n required_user_inputs: activation.required_user_inputs || payload.required_user_inputs || [],\n required_consent_types: activation.required_consent_types || payload.required_consent_types || [],\n success_outcome: activation.success_outcome || payload.success_outcome,\n fallback_message: activation.fallback_message || payload.fallback_message,\n capabilities: activation.capabilities || payload.capabilities || [],\n allowed_data_types: activation.allowed_data_types || payload.allowed_data_types || [],\n consent_requirements: activation.consent_requirements || payload.consent_requirements || [],\n auth_model: activation.auth_model || payload.auth_model,\n handoff_protocol: activation.handoff_protocol || payload.handoff_protocol,\n supported_actions: activation.supported_actions || payload.supported_actions || [],\n metadata: activation.metadata || payload.metadata,\n };\n\n setActiveDelegationSession(activeSession);\n await sdk\n .trackPublisherAssistantEvent({\n event_name: 'delegation_started',\n timestamp: new Date().toISOString(),\n session_id: sessionId,\n recommendation_id: payload.recommendation_id,\n delegation_session_id: activation.delegation_session_id,\n brand_name: activeSession.brand_name,\n status: activation.status || 'active',\n metadata: {\n brand_agent_id: activation.brand_agent_id,\n source: 'recommendation_card',\n },\n })\n .catch((analyticsError) => {\n logger.warn('[AdMeshRecommendations] ⚠️ Failed to track delegation_started event:', analyticsError);\n });\n await sdk\n .reportDelegationSessionStarted(activeSession, {\n brand_agent_id: activation.brand_agent_id,\n brand_name: activeSession.brand_name,\n })\n .then((updatedSession) => {\n if (updatedSession) {\n setActiveDelegationSession(updatedSession);\n }\n })\n .catch((eventError) => {\n logger.warn('[AdMeshRecommendations] ⚠️ Failed to report delegation session_started event:', eventError);\n });\n\n if (onDelegationActivated) {\n try {\n await onDelegationActivated(resolvedPayload);\n } catch (callbackError) {\n logger.warn(\n '[AdMeshRecommendations] ⚠️ Host onDelegationActivated callback failed after successful delegation activation:',\n callbackError,\n );\n }\n return;\n }\n\n if (onStartDelegation) {\n try {\n await onStartDelegation({\n ...payload.platform_response,\n delegation: {\n ...payload.platform_response.delegation,\n ...resolvedPayload,\n delegation_session_id: activation.delegation_session_id,\n available: true,\n status: activation.status || 'active',\n },\n });\n } catch (callbackError) {\n logger.warn(\n '[AdMeshRecommendations] ⚠️ Host onStartDelegation callback failed after successful delegation activation:',\n callbackError,\n );\n }\n }\n },\n [\n apiKey,\n onDelegationActivated,\n onStartDelegation,\n sdk,\n sessionId,\n setActiveDelegationSession,\n ],\n );\n\n // Don't render anything if validation fails\n if (!messageId || !query || query.trim() === '') {\n return null;\n }\n\n // Show loading state (optional - can be removed if not needed)\n if (isLoading) {\n return null; // Or return a loading spinner if desired\n }\n\n // Show error state (optional - can be removed if not needed)\n if (error) {\n return null; // Error is already handled by onError callback\n }\n\n // Don't render if no recommendation\n if (!platformResult || !detectedFormat) {\n logger.log('[AdMeshRecommendations] 🚫 Nothing to render', {\n messageId,\n hasPlatformResult: !!platformResult,\n detectedFormat,\n isLoading,\n hasError: !!error,\n });\n return null;\n }\n\n logger.log('[AdMeshRecommendations] 🎨 Rendering recommendation component', {\n messageId,\n recommendationId: platformResult.recommendation_id,\n detectedFormat,\n brandName: platformResult.recommendation?.creative?.brand_name,\n headline: platformResult.recommendation?.creative?.headline,\n });\n\n const followupContainer =\n typeof document !== 'undefined' &&\n followups_container_id &&\n (isContainerReady ?? true)\n ? document.getElementById(followups_container_id)\n : null;\n\n return (\n <>\n <div className=\"admesh-recommendations-container\" style={{ marginTop: '1rem' }}>\n <AdMeshCompactCard\n recommendations={[platformResult]}\n theme={theme}\n sessionId={sessionId}\n triggerExposureUrl={triggerExposureUrl}\n onPasteToInput={onPasteToInput}\n onDelegationConsent={onDelegationConsent}\n onDelegationActivated={handleSdkDelegationActivated}\n onStartDelegation={onStartDelegation}\n />\n </div>\n {followupContainer && sdk && sessionId\n ? createPortal(\n <AdMeshFollowup\n recommendation={platformResult}\n theme={theme}\n sdk={sdk}\n sessionId={sessionId}\n onExecuteQuery={onExecuteQuery}\n />,\n followupContainer,\n )\n : null}\n </>\n );\n};\n\nexport default AdMeshRecommendations;\n","'use client';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useAdMesh } from '../hooks/useAdMesh';\nimport { logger } from '../utils/logger';\n\nexport interface WeaveFallbackRecommendationsProps {\n /** Recommendation format for fallback display\n *\n * - 'product': Display as product cards\n * - 'tail': Display as tail format (default)\n */\n format?: 'product' | 'tail';\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /**\n * Message ID for per-message recommendations.\n *\n * This is the primary identifier for fetching recommendations for a specific message.\n */\n messageId: string;\n\n /**\n * User query text for generating recommendations.\n *\n * This is the query that will be used to fetch recommendations from the backend.\n * Typically the user's question or search query.\n *\n * IMPORTANT: This should be a non-empty string. If not provided or empty,\n * the component will skip rendering to prevent 400 Bad Request errors.\n * The backend requires a valid query parameter.\n */\n query?: string;\n\n /**\n * Fallback state - controls whether to show recommendations\n * When true, recommendations will be fetched and displayed\n * When false or undefined, component will not render\n */\n fallback?: boolean;\n\n /**\n * Previously fetched recommendations from WeaveAdFormatContainer.\n * If provided and not empty, these will be rendered directly without making a new API call.\n * Only makes a new API call if this is empty/null/undefined.\n */\n previousRecommendations?: any[]; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\n/**\n * WeaveFallbackRecommendations - Weave Format Fallback Component\n *\n * Displays recommendations as a fallback UI when no AdMesh links are detected\n * in the LLM response. Works independently without requiring WeaveAdFormatContext.\n *\n * This component will:\n * - Accept messageId, query, and fallback state as props\n * - Only render when fallback prop is true\n * - If previousRecommendations are provided and not empty: renders them directly (no API call)\n * - If previousRecommendations are empty/null: calls SDK's showRecommendations() to fetch recommendations\n * - Display recommendations in the specified format (tail or product)\n *\n * IMPORTANT: Pass previousRecommendations from WeaveAdFormatContainer to avoid duplicate API calls.\n *\n * @example\n * ```tsx\n * const [fallback, setFallback] = useState(false);\n *\n * <AdMeshProvider apiKey={apiKey} sessionId={sessionId}>\n * <WeaveAdFormatContainer\n * messageId={message.id}\n * query={userQuery}\n * onFallbackChange={setFallback}\n * >\n * {llmResponseContent}\n * </WeaveAdFormatContainer>\n * <WeaveFallbackRecommendations\n * messageId={message.id}\n * query={userQuery}\n * format=\"tail\"\n * fallback={fallback}\n * previousRecommendations={recommendations} // Pass from WeaveAdFormatContainer\n * />\n * </AdMeshProvider>\n * ```\n */\nexport const WeaveFallbackRecommendations: React.FC<WeaveFallbackRecommendationsProps> = ({\n format = 'tail',\n onError,\n messageId,\n query,\n fallback,\n previousRecommendations,\n}) => {\n const { sdk, sessionId, theme, apiKey, language, location, userId, model, messages } = useAdMesh();\n const containerRef = useRef<HTMLDivElement>(null);\n const [containerId, setContainerId] = useState<string>('');\n\n // Generate container ID based on message ID\n useEffect(() => {\n if (messageId) {\n setContainerId(`admesh-weave-fallback-${messageId}`);\n }\n }, [messageId]);\n\n // Log component render\n logger.log('[WeaveFallbackRecommendations] 🎨 Component render');\n\n useEffect(() => {\n // Log what we're receiving\n logger.log('[WeaveFallbackRecommendations] 🔄 useEffect triggered', {\n fallback,\n hasPreviousRecommendations: previousRecommendations && previousRecommendations.length > 0,\n previousRecommendationsCount: previousRecommendations?.length || 0\n });\n\n // Skip if fallback is not true\n if (!fallback) {\n logger.log('[WeaveFallbackRecommendations] ⏭️ Skipping - fallback is FALSE, not rendering recommendations');\n return;\n }\n\n logger.log('[WeaveFallbackRecommendations] ✅ fallback is TRUE, proceeding with recommendations');\n\n // Validate required parameters\n if (!messageId || !query || query.trim() === '') {\n logger.log('[WeaveFallbackRecommendations] ❌ Validation failed - returning early');\n return;\n }\n\n logger.log('[WeaveFallbackRecommendations] ✅ Validation passed');\n\n if (!sdk || !containerId) {\n logger.log('[WeaveFallbackRecommendations] SDK or containerId not ready');\n return;\n }\n\n // Check if we have previous recommendations to reuse\n const hasPreviousRecs = previousRecommendations && previousRecommendations.length > 0;\n \n logger.log('[WeaveFallbackRecommendations] 📊 Checking previous recommendations:', {\n hasPreviousRecs,\n count: previousRecommendations?.length || 0,\n fallback,\n messageId\n });\n \n if (hasPreviousRecs) {\n // Use previous recommendations - render directly without API call\n logger.log(`[WeaveFallbackRecommendations] ♻️ Reusing ${previousRecommendations.length} previous recommendation(s), skipping API call`);\n \n const renderRecommendations = async () => {\n try {\n const aipResponse = previousRecommendations[0];\n \n logger.log('[WeaveFallbackRecommendations] 📦 Processing AIP response:', {\n hasAipResponse: !!aipResponse,\n recommendationId: aipResponse?.recommendation_id || '',\n format: aipResponse?.recommendation?.format || 'unknown'\n });\n \n // Development logging: Log full recommendation details\n if (aipResponse && process.env.NODE_ENV === 'development') {\n logger.log('[WeaveFallbackRecommendations] 📋 Recommendation received (DEV):', {\n recommendation_id: aipResponse?.recommendation_id,\n click_url:\n aipResponse?.tracking?.click_url ||\n aipResponse?.recommendation?.creative?.landing_page_url,\n format: aipResponse?.recommendation?.format,\n full_response: aipResponse\n });\n }\n \n if (!aipResponse) {\n logger.warn('[WeaveFallbackRecommendations] ⚠️ Previous recommendation is empty, falling back to API call');\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId,\n });\n return;\n }\n\n const sdkAny = sdk as any;\n const getRendererMethod = sdkAny.getRenderer;\n const getTrackerMethod = sdkAny.getTracker;\n const sdkTheme = sdkAny.config?.theme;\n\n if (getRendererMethod && getTrackerMethod) {\n const response = {\n sessionId,\n messageId,\n recommendations: [aipResponse]\n };\n\n // Get renderer and tracker\n const renderer = getRendererMethod.call(sdk);\n const tracker = getTrackerMethod.call(sdk);\n \n // Get apiBaseUrl from SDK instance\n const apiBaseUrl = (sdk as any)?.apiBaseUrl || \n (typeof window !== 'undefined' && (window as any).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n \n // Render directly - pass all required props for AdMeshProvider\n await renderer.render({\n containerId,\n response,\n theme: theme || sdkTheme,\n tracker: tracker,\n sessionId: sessionId,\n apiKey: apiKey || (sdk as any)?.config?.apiKey,\n apiBaseUrl: apiBaseUrl,\n language: language,\n location: location,\n userId: userId,\n model: model,\n messages: messages,\n });\n \n logger.log('[WeaveFallbackRecommendations] ✅ Recommendations rendered from previous response (no API call)');\n } else {\n // SDK methods not accessible - fall back to showRecommendations\n // This will use the cached result from auction coordination, so it's still fast\n logger.warn('[WeaveFallbackRecommendations] ⚠️ SDK internal methods not accessible, using showRecommendations (will use cached result)');\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId,\n });\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n logger.error(`[WeaveFallbackRecommendations] ❌ Error rendering previous recommendations: ${err.message}`);\n // Fallback to API call on error (will use cached result)\n try {\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId,\n });\n } catch (fallbackError) {\n onError?.(err);\n }\n }\n };\n\n renderRecommendations();\n } else {\n // No previous recommendations - make new API call\n logger.log('[WeaveFallbackRecommendations] 📤 No previous recommendations, calling sdk.showRecommendations');\n \n const fetchRecommendations = async () => {\n try {\n if (!sdk?.showRecommendations) {\n logger.log('[WeaveFallbackRecommendations] SDK showRecommendations not available');\n return;\n }\n\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId, // REQUIRED: messageId must be provided by platform\n });\n\n logger.log('[WeaveFallbackRecommendations] ✅ Recommendations displayed successfully');\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n logger.log(`[WeaveFallbackRecommendations] ❌ Error: ${err.message}`);\n onError?.(err);\n }\n };\n\n fetchRecommendations();\n }\n }, [sdk, sessionId, containerId, format, messageId, query, fallback, onError, previousRecommendations, theme]);\n\n // Don't render anything if fallback is not active or validation fails\n if (!fallback || !messageId || !query || query.trim() === '') {\n return null;\n }\n\n // Render the container where fallback recommendations will be displayed\n // Use display: 'none' initially to prevent taking up space until recommendations are loaded\n // The SDK will set display: 'block' when it renders content\n return (\n <div\n ref={containerRef}\n id={containerId}\n className=\"admesh-weave-fallback-recommendations-container\"\n style={{\n marginTop: '1rem',\n display: 'none', // Hidden by default, SDK will show when recommendations are rendered\n }}\n />\n );\n};\n\nexport default WeaveFallbackRecommendations;\n","'use client';\n\nimport { createContext, useContext, type ReactNode, type FC } from 'react';\n\nexport interface WeaveAdFormatContextType {\n /** Whether the fallback UI should be rendered (no AdMesh links detected) */\n shouldRenderFallback: boolean;\n /** The message ID for this Weave Ad Format container (used for deduplication) */\n messageId: string;\n /** The session ID for this Weave Ad Format container (used for tracking) */\n sessionId?: string;\n /** The query for this message (used for fallback API calls) */\n query?: string;\n}\n\nconst WeaveAdFormatContext = createContext<WeaveAdFormatContextType | undefined>(undefined);\n\nexport const WeaveAdFormatProvider: FC<{\n children: ReactNode;\n shouldRenderFallback: boolean;\n messageId: string;\n sessionId?: string;\n query?: string;\n}> = ({ children, shouldRenderFallback, messageId, sessionId, query }) => {\n return (\n <WeaveAdFormatContext.Provider value={{ shouldRenderFallback, messageId, sessionId, query }}>\n {children}\n </WeaveAdFormatContext.Provider>\n );\n};\n\n/**\n * Hook to access WeaveAdFormatContext\n * \n * Returns the context value if inside a WeaveAdFormatContainer,\n * or undefined if not inside one.\n * \n * @example\n * ```tsx\n * const weaveContext = useWeaveAdFormatContext();\n * if (weaveContext) {\n * // Inside a WeaveAdFormatContainer\n * const { shouldRenderFallback, messageId } = weaveContext;\n * }\n * ```\n */\nexport const useWeaveAdFormatContext = (): WeaveAdFormatContextType | undefined => {\n return useContext(WeaveAdFormatContext);\n};\n\nexport default WeaveAdFormatContext;\n","import { useEffect, useRef, useState, type CSSProperties, type FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { PlatformResponse, AdMeshTheme, DelegationActivationPayload } from '../types/index';\nimport { AdMeshViewabilityTracker } from './AdMeshViewabilityTracker';\n\nexport interface AdMeshTailAdProps {\n recommendations: PlatformResponse[]; // Canonical platform responses\n theme?: AdMeshTheme;\n className?: string;\n style?: CSSProperties;\n sessionId?: string;\n triggerExposureUrl?: boolean;\n onDelegationConsent?: (recommendation: PlatformResponse) => boolean | Promise<boolean>;\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n onStartDelegation?: (recommendation: PlatformResponse) => void | Promise<void>;\n onPasteToInput?: (content: string) => void;\n}\n\n// Utility function to validate and normalize URLs\nconst isValidUrl = (url: string): boolean => {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n};\n\n// Helper function to get CTA label from backend\nconst getCTALabel = (ctaLabel?: string): string => {\n // Use provided CTA label from backend if available\n if (ctaLabel && ctaLabel.trim()) {\n return ctaLabel.trim();\n }\n\n // Return empty string if no CTA label provided (will hide CTA button)\n return '';\n};\n\nconst getDisplayText = (value: unknown): string => {\n if (typeof value === 'string') {\n return value.trim();\n }\n if (typeof value === 'number') {\n return String(value);\n }\n return '';\n};\n\nconst asOptionalString = (value: unknown): string | undefined => {\n const text = getDisplayText(value);\n return text || undefined;\n};\n\nconst truncateWords = (value: string, maxWords: number): string => {\n const words = value.split(/\\s+/).filter(Boolean);\n if (words.length <= maxWords) {\n return value;\n }\n return `${words.slice(0, maxWords).join(' ')}...`;\n};\n\nconst formatProductPrice = (price: unknown, currency?: string): string => {\n if (price === null || price === undefined || price === '') {\n return '';\n }\n\n if (typeof price === 'number') {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: 2,\n }).format(price);\n } catch {\n return String(price);\n }\n }\n\n return getDisplayText(price);\n};\n\nconst formatProductDiscount = (\n discount: unknown,\n discountType?: string,\n currency?: string,\n): string => {\n if (discount === null || discount === undefined || discount === '') {\n return '';\n }\n\n const normalizedType = (discountType || 'percentage').trim().toLowerCase();\n\n if (typeof discount === 'number') {\n if (normalizedType === 'amount' || normalizedType === 'fixed' || normalizedType === 'fixed_amount') {\n try {\n const formattedAmount = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: 2,\n }).format(discount);\n return `${formattedAmount} off`;\n } catch {\n return `${discount} off`;\n }\n }\n\n return `${discount}% off`;\n }\n\n const text = getDisplayText(discount);\n if (!text) {\n return '';\n }\n if (/%|off/i.test(text)) {\n return text;\n }\n if (normalizedType === 'amount' || normalizedType === 'fixed' || normalizedType === 'fixed_amount') {\n return `${text} off`;\n }\n return `${text}% off`;\n};\n\nconst TAIL_AD_COLORS = {\n surface: '#ffffff',\n surfaceMuted: '#f9fafb',\n surfaceSubtle: '#f8fafc',\n border: 'rgba(17, 24, 39, 0.10)',\n text: '#111827',\n textSecondary: '#4b5563',\n textMuted: '#6b7280',\n link: '#2563eb',\n logoFallbackBg: '#f3f4f6',\n logoFallbackText: '#4b5563',\n productImageFallbackBg: '#e5e7eb',\n successText: '#065f46',\n successBg: '#d1fae5',\n};\n\nexport const AdMeshTailAd: FC<AdMeshTailAdProps> = ({\n recommendations,\n theme,\n className = '',\n style = {},\n sessionId,\n triggerExposureUrl = true,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n onPasteToInput,\n}) => {\n // Validate inputs - return null if empty\n if (!recommendations || recommendations.length === 0) {\n logger.log('[AdMesh Tail Ad] No recommendations provided - not rendering');\n return null;\n }\n\n // Get the first recommendation's data for CTA and tracking\n const firstRecommendation = recommendations[0];\n const productId = firstRecommendation?.recommendation?.offerId || '';\n const exposureUrl = firstRecommendation?.tracking?.exposure_url || '';\n const recommendationId = firstRecommendation?.recommendation_id || '';\n const shortDescription = firstRecommendation?.recommendation?.creative?.description || '';\n const disclosure = firstRecommendation?.recommendation?.disclosure || 'Sponsored';\n const brandName = firstRecommendation?.recommendation?.creative?.brand_name || '';\n const productName =\n firstRecommendation?.recommendation?.creative?.headline ||\n firstRecommendation?.recommendation?.creative?.brand_name ||\n '';\n const logoUrl = firstRecommendation?.recommendation?.creative?.logo_url || '';\n const clickUrl =\n firstRecommendation?.tracking?.click_url ||\n firstRecommendation?.recommendation?.creative?.landing_page_url ||\n '';\n const ctaLabel = getCTALabel(firstRecommendation?.recommendation?.creative?.cta_text);\n const relatedProducts = firstRecommendation?.recommendation?.creative?.products || [];\n const hasProductRail = relatedProducts.length > 1;\n const visibleProducts = hasProductRail ? relatedProducts.slice(0, 4) : [];\n const recommendationFormat = firstRecommendation?.recommendation?.format || 'tail';\n const isBridgeRecommendation = recommendationFormat === 'bridge';\n const delegationBrandName = firstRecommendation?.delegation?.brand_name || brandName;\n const hasDelegation = firstRecommendation?.delegation?.available === true;\n const shouldShowDelegationButton = isBridgeRecommendation && hasDelegation;\n const delegationCtaText = 'Talk to Agent';\n const shouldShowPrimaryCta = !hasProductRail && !!ctaLabel && !!clickUrl;\n\n // For tail format, we need at least brand name\n // But we still validate that we have at least one recommendation with data\n if (!brandName && !productName && !shortDescription) {\n logger.log('[AdMesh Tail Ad] No valid recommendation data provided - not rendering', {\n reason: 'brand, headline, and description are missing',\n brandName,\n hasFirstRecommendation: !!firstRecommendation,\n recommendationId,\n recommendationKeys: firstRecommendation ? Object.keys(firstRecommendation) : []\n });\n return null;\n }\n \n // Build headline parts with priority:\n // 1. If offer_summary exists: \"Brand — Offer Summary\"\n // 2. If product_name exists: \"Brand — Product Name\"\n // 3. Otherwise: just \"Brand\"\n let headlineText = brandName;\n let headlineSuffix = '';\n \n if (productName && productName !== brandName) {\n headlineSuffix = productName;\n }\n \n if (headlineSuffix) {\n headlineText = `${brandName} — ${headlineSuffix}`;\n }\n\n logger.debug('[AdMeshTailAd] 📊 Rendering with tracking data:', {\n recommendationId,\n productId,\n exposureUrl: exposureUrl ? 'present' : 'MISSING',\n sessionId: sessionId ? 'present' : 'MISSING',\n recommendationsCount: recommendations.length,\n clickUrl: clickUrl ? clickUrl : 'MISSING',\n clickUrlSource: firstRecommendation?.tracking?.click_url ? 'tracking.click_url' :\n firstRecommendation?.recommendation?.creative?.landing_page_url ? 'recommendation.creative.landing_page_url' :\n 'none',\n shortDescription: shortDescription ? 'present' : 'MISSING',\n brandName,\n productName,\n headlineText,\n triggerExposureUrl\n });\n logger.log('[AdMeshTailAd] ✅ Rendering tail ad', {\n recommendationId,\n brandName,\n productName,\n hasDescription: !!shortDescription,\n hasClickUrl: !!clickUrl,\n hasLogoUrl: !!logoUrl,\n recommendationFormat,\n });\n\n // Handler for tracking clicks on the entire tail ad\n const handleContainerClick = (source: string, e?: React.MouseEvent) => {\n if (e) {\n e.stopPropagation();\n }\n logger.log(`AdMesh tail ad ${source} clicked`);\n if (typeof window !== 'undefined' && (window as any).admeshTracker) {\n (window as any).admeshTracker.trackClick({\n recommendationId,\n productId,\n clickUrl: clickUrl,\n source: source\n }).catch(() => {\n logger.error(`[AdMesh] Failed to track ${source} click`);\n });\n }\n };\n\n // Handler for brand name link click\n const handleBrandNameClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n handleContainerClick('tail_ad_brand_name');\n };\n\n // Handler for CTA link click\n const handleCTAClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n handleContainerClick('tail_ad_cta');\n };\n\n // Handler for logo click\n const handleLogoClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n handleContainerClick('tail_ad_logo');\n };\n\n const handleCardClick = () => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n handleContainerClick('tail_ad_card');\n if (typeof window !== 'undefined') {\n window.open(clickUrl, '_blank', 'noopener,noreferrer');\n }\n };\n\n const handleCardKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleCardClick();\n }\n };\n\n const requestDefaultConsent = (): boolean => {\n return true;\n };\n\n const [showConsentPrompt, setShowConsentPrompt] = useState(false);\n const consentResolverRef = useRef<((value: boolean) => void) | null>(null);\n\n useEffect(() => {\n return () => {\n if (consentResolverRef.current) {\n consentResolverRef.current(false);\n consentResolverRef.current = null;\n }\n };\n }, []);\n\n const resolveConsentPrompt = (value: boolean) => {\n consentResolverRef.current?.(value);\n consentResolverRef.current = null;\n setShowConsentPrompt(false);\n };\n\n const requestConsent = async (): Promise<boolean> => {\n if (onDelegationConsent) {\n return await onDelegationConsent(firstRecommendation);\n }\n if (!requestDefaultConsent()) {\n return false;\n }\n return await new Promise<boolean>((resolve) => {\n consentResolverRef.current = resolve;\n setShowConsentPrompt(true);\n });\n };\n\n const trackDelegationEngagement = async () => {\n if (!(recommendationId && sessionId)) {\n return;\n }\n\n try {\n const apiBaseUrl =\n (typeof window !== 'undefined' && (window as any).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n\n const response = await fetch(`${apiBaseUrl}/click/bridge-engagement`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n recommendation_id: recommendationId,\n session_id: sessionId,\n is_test: false,\n }),\n });\n\n if (!response.ok) {\n logger.warn('[AdMesh Tail Ad] Delegation engagement tracking failed:', response.statusText);\n }\n } catch (error) {\n logger.error('[AdMesh Tail Ad] Error tracking delegation engagement:', error);\n }\n };\n\n const handleDelegationClick = async (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (!firstRecommendation || !shouldShowDelegationButton) {\n return;\n }\n\n handleContainerClick('tail_ad_delegation_cta');\n await trackDelegationEngagement();\n\n const consentGranted = await requestConsent();\n if (!consentGranted) {\n logger.log('[AdMesh Tail Ad] Delegation consent declined');\n return;\n }\n\n const delegation = firstRecommendation.delegation;\n const delegationPayload: DelegationActivationPayload | null =\n delegation?.available\n ? {\n recommendation_id: firstRecommendation.recommendation_id,\n brand_id: asOptionalString(delegation.brand_id),\n brand_name: asOptionalString(\n delegation.brand_name || firstRecommendation.recommendation?.creative?.brand_name,\n ),\n eligibility_reason: asOptionalString(delegation.eligibility_reason),\n delegate_reason: asOptionalString(delegation.delegate_reason),\n session_goal: asOptionalString(delegation.session_goal),\n desired_outcome_type: delegation.desired_outcome_type,\n required_user_inputs: Array.isArray(delegation.required_user_inputs)\n ? delegation.required_user_inputs.filter((value): value is string => typeof value === 'string')\n : [],\n required_consent_types: Array.isArray(delegation.required_consent_types)\n ? delegation.required_consent_types.filter((value): value is string => typeof value === 'string')\n : [],\n success_outcome: asOptionalString(delegation.success_outcome),\n fallback_message: asOptionalString(delegation.fallback_message),\n session_mode: asOptionalString(delegation.session_mode),\n status: asOptionalString(delegation.status),\n capabilities: delegation.capabilities || [],\n allowed_data_types: delegation.allowed_data_types || [],\n consent_requirements: delegation.consent_requirements || [],\n auth_model: asOptionalString(delegation.auth_model),\n handoff_protocol:\n delegation.handoff_protocol && typeof delegation.handoff_protocol === 'object'\n ? delegation.handoff_protocol\n : undefined,\n supported_actions: delegation.supported_actions || [],\n metadata:\n delegation.metadata && typeof delegation.metadata === 'object'\n ? delegation.metadata\n : undefined,\n platform_response: firstRecommendation,\n }\n : null;\n\n if (onDelegationActivated && delegationPayload) {\n await onDelegationActivated(delegationPayload);\n return;\n }\n\n if (onStartDelegation) {\n await onStartDelegation(firstRecommendation);\n return;\n }\n\n const fallbackPrompt = firstRecommendation.recommendation?.creative?.follow_up_suggestion || '';\n if (fallbackPrompt && onPasteToInput) {\n onPasteToInput(fallbackPrompt);\n return;\n }\n\n if (fallbackPrompt && typeof window !== 'undefined' && (window as any).__admesh_setMessage) {\n (window as any).__admesh_setMessage(fallbackPrompt);\n return;\n }\n };\n\n // State for logo load error\n const [logoError, setLogoError] = useState(false);\n\n // Get first letter of brand name for fallback\n const brandInitial = brandName ? brandName.charAt(0).toUpperCase() : 'B';\n\n // Tail ads use their own neutral palette so host light/dark themes cannot\n // make sponsored content unreadable.\n const cardBackground = TAIL_AD_COLORS.surface;\n const cardBorder = TAIL_AD_COLORS.border;\n const cardBorderRadius = theme?.borderRadius || theme?.components?.card?.borderRadius || '8px';\n \n // Shadow styles - definitive shadow for floating feel\n const defaultShadow = '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)';\n const hoverShadow = '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)';\n \n const cardShadow = theme?.shadows?.medium || theme?.components?.card?.boxShadow || defaultShadow;\n const cardHoverShadow = theme?.shadows?.large || hoverShadow;\n\n return (\n <AdMeshViewabilityTracker\n productId={productId}\n recommendationId={recommendationId}\n exposureUrl={exposureUrl}\n sessionId={sessionId}\n triggerExposureUrl={triggerExposureUrl}\n className={`admesh-tail-ad ${className}`}\n style={{\n fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n lineHeight: 1.4,\n ...style\n }}\n >\n <style>{`\n .admesh-tail-product-scroll {\n -ms-overflow-style: none;\n scrollbar-width: none;\n }\n\n .admesh-tail-product-scroll::-webkit-scrollbar {\n display: none;\n width: 0;\n height: 0;\n }\n `}</style>\n <div \n className=\"tail-ad-container flex flex-col gap-3 sm:flex-row\"\n role={!hasProductRail && clickUrl ? 'link' : undefined}\n tabIndex={!hasProductRail && clickUrl ? 0 : undefined}\n style={{\n ...theme?.components?.card,\n backgroundColor: cardBackground,\n borderRadius: cardBorderRadius,\n padding: '16px',\n boxShadow: cardShadow,\n border: `1px solid ${cardBorder}`,\n color: TAIL_AD_COLORS.text,\n transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',\n transform: 'translateY(0)',\n cursor: !hasProductRail && clickUrl ? 'pointer' : undefined,\n }}\n onClick={handleCardClick}\n onKeyDown={handleCardKeyDown}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow = cardHoverShadow;\n e.currentTarget.style.transform = 'translateY(-2px)';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow = cardShadow;\n e.currentTarget.style.transform = 'translateY(0)';\n }}\n >\n {/* Left Section: Logo Area (10% width, stacks on mobile) */}\n {logoUrl && (\n <div \n className=\"flex-shrink-0 flex items-center justify-start pr-0 sm:justify-center sm:pr-2\"\n style={{\n width: 'auto',\n minWidth: '48px'\n }}\n >\n {!logoError && isValidUrl(logoUrl) ? (\n <a\n href={clickUrl || '#'}\n target={clickUrl ? \"_blank\" : undefined}\n rel={clickUrl ? \"noopener noreferrer\" : undefined}\n onClick={clickUrl ? handleLogoClick : undefined}\n className=\"block\"\n style={{ \n cursor: clickUrl ? 'pointer' : 'default',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n maxWidth: '64px'\n }}\n >\n <img\n src={logoUrl}\n alt={`${brandName} logo`}\n className=\"object-cover\"\n style={{\n width: '100%',\n height: 'auto',\n maxWidth: '64px',\n maxHeight: '64px',\n objectFit: 'contain',\n borderRadius: '8px'\n }}\n onError={() => {\n setLogoError(true);\n logger.debug('[AdMesh Tail Ad] Logo failed to load, showing fallback');\n }}\n />\n </a>\n ) : (\n <div\n className=\"flex items-center justify-center text-lg font-semibold\"\n style={{\n width: '100%',\n maxWidth: '64px',\n aspectRatio: '1',\n borderRadius: '8px',\n minHeight: '48px',\n backgroundColor: TAIL_AD_COLORS.logoFallbackBg,\n color: TAIL_AD_COLORS.logoFallbackText,\n fontSize: '18px',\n }}\n >\n {brandInitial}\n </div>\n )}\n </div>\n )}\n\n {/* Right Section: Content Area (90% width) */}\n <div \n className=\"flex-1\"\n style={{\n width: '100%',\n minWidth: 0 // Allow flex item to shrink below content size\n }}\n >\n {/* Headline: Brand Name (clickable link) — Offer Summary / Product Name / Brand only */}\n {headlineText && !hasProductRail && (\n <div className=\"mb-2\">\n <h3 className=\"font-semibold text-base\" style={{ fontSize: '14px', lineHeight: 1.35, color: TAIL_AD_COLORS.text }}>\n {clickUrl && brandName ? (\n <>\n <a\n href={clickUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline transition-colors duration-200 font-semibold\"\n style={{\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textDecorationColor: TAIL_AD_COLORS.link,\n textUnderlineOffset: '2px'\n }}\n onClick={handleBrandNameClick}\n >\n {brandName}\n </a>\n {headlineSuffix && ` — ${headlineSuffix}`}\n </>\n ) : (\n headlineText\n )}\n </h3>\n </div>\n )}\n \n {/* Description: Full short_description */}\n {shortDescription && !hasProductRail && (\n <p className=\"text-sm mb-3 leading-relaxed\" style={{ fontSize: '13px', lineHeight: 1.45, color: TAIL_AD_COLORS.textSecondary }}>\n {shortDescription}\n </p>\n )}\n\n {hasProductRail && visibleProducts.length > 0 && (\n <div className=\"mb-3\">\n <div\n className=\"admesh-tail-product-scroll\"\n style={{\n marginBottom: '8px',\n overflowX: 'auto',\n overflowY: 'hidden',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorX: 'contain',\n overscrollBehaviorY: 'none',\n scrollBehavior: 'smooth',\n paddingBottom: '2px',\n }}\n >\n <div\n style={{\n display: 'flex',\n gap: '10px',\n minWidth: 'max-content',\n scrollSnapType: 'x proximity',\n paddingRight: 0,\n }}\n >\n {visibleProducts.map((product) => {\n const productName = getDisplayText(product.product_name) || 'Product';\n const productLink =\n getDisplayText(product.product_link) ||\n getDisplayText(product.product_url) ||\n clickUrl ||\n '#';\n const productDescription = truncateWords(getDisplayText(product.product_description), 10);\n const productPrice = formatProductPrice(product.product_price, product.product_currency);\n const productDiscount = formatProductDiscount(\n product.product_discount,\n product.product_discount_type,\n product.product_currency,\n );\n const productImageUrl = getDisplayText(product.product_image_url);\n const fallbackLogoUrl = logoUrl && isValidUrl(logoUrl) ? logoUrl : '';\n const displayProductImageUrl =\n productImageUrl && isValidUrl(productImageUrl)\n ? productImageUrl\n : fallbackLogoUrl;\n const productCtaLabel = getCTALabel(product.product_cta_label);\n const hasProductLink = productLink !== '#';\n\n return (\n <a\n key={product.product_id || `${recommendationId}-${productName}`}\n href={productLink}\n target={hasProductLink ? '_blank' : undefined}\n rel={hasProductLink ? 'noopener noreferrer' : undefined}\n onClick={(e) => handleContainerClick(`tail_ad_product_${product.product_id || 'item'}`, e)}\n className=\"block\"\n style={{\n border: `1px solid ${cardBorder}`,\n borderRadius: '8px',\n padding: '10px',\n backgroundColor: TAIL_AD_COLORS.surfaceMuted,\n textDecoration: 'none',\n color: TAIL_AD_COLORS.text,\n minWidth: 'min(264px, 82vw)',\n width: 'clamp(220px, 72vw, 312px)',\n flex: '0 0 clamp(220px, 72vw, 312px)',\n scrollSnapAlign: 'start',\n }}\n >\n <div className=\"flex items-start gap-2\">\n {displayProductImageUrl ? (\n <img\n src={displayProductImageUrl}\n alt={productName}\n style={{\n width: '44px',\n height: '44px',\n objectFit: 'cover',\n borderRadius: '6px',\n flexShrink: 0,\n }}\n />\n ) : (\n <div\n className=\"flex items-center justify-center text-xs font-semibold\"\n style={{\n width: '44px',\n height: '44px',\n borderRadius: '6px',\n flexShrink: 0,\n backgroundColor: TAIL_AD_COLORS.productImageFallbackBg,\n color: TAIL_AD_COLORS.textSecondary,\n fontSize: '12px',\n }}\n >\n {productName.charAt(0).toUpperCase()}\n </div>\n )}\n\n <div style={{ minWidth: 0, flex: 1 }}>\n <p\n className=\"font-medium text-sm\"\n style={{\n fontSize: '13px',\n lineHeight: 1.3,\n color: TAIL_AD_COLORS.text,\n marginBottom: '4px',\n }}\n >\n {productName}\n </p>\n\n {productDescription && (\n <p\n className=\"text-xs\"\n style={{\n fontSize: '12px',\n lineHeight: 1.3,\n color: TAIL_AD_COLORS.textSecondary,\n marginBottom: '6px',\n }}\n >\n {productDescription}\n </p>\n )}\n\n {(productPrice || productDiscount) && (\n <div\n className=\"flex items-center gap-2 flex-wrap\"\n style={{\n marginBottom: productCtaLabel ? '6px' : 0,\n }}\n >\n {productPrice && (\n <div className=\"flex items-center gap-1\">\n <span\n style={{\n fontSize: '10px',\n color: TAIL_AD_COLORS.textMuted,\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n }}\n >\n Price\n </span>\n <span\n className=\"font-semibold\"\n style={{\n fontSize: '13px',\n color: TAIL_AD_COLORS.text,\n }}\n >\n {productPrice}\n </span>\n </div>\n )}\n {productDiscount && (\n <span\n className=\"text-xs\"\n style={{\n fontSize: '11px',\n color: TAIL_AD_COLORS.successText,\n backgroundColor: TAIL_AD_COLORS.successBg,\n borderRadius: '999px',\n padding: '2px 8px',\n fontWeight: 600,\n }}\n >\n {productDiscount}\n </span>\n )}\n </div>\n )}\n\n {productCtaLabel && (\n <span\n className=\"font-medium\"\n style={{\n fontSize: '12px',\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textUnderlineOffset: '2px',\n }}\n >\n {productCtaLabel}\n </span>\n )}\n </div>\n </div>\n </a>\n );\n })}\n </div>\n </div>\n </div>\n )}\n \n {/* CTA Link, Feedback Buttons, and Sponsored Label */}\n <div className=\"mt-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {hasProductRail && brandName && (\n <span\n className=\"text-sm\"\n style={{\n fontSize: '13px',\n color: TAIL_AD_COLORS.textSecondary,\n fontWeight: 400,\n }}\n >\n {brandName}\n </span>\n )}\n\n {shouldShowDelegationButton ? (\n <button\n type=\"button\"\n onClick={handleDelegationClick}\n className=\"underline transition-colors duration-200 font-medium text-sm\"\n style={{\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textDecorationColor: TAIL_AD_COLORS.link,\n textUnderlineOffset: '2px',\n fontSize: '13px',\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n }}\n >\n {delegationCtaText}\n </button>\n ) : null}\n\n {shouldShowPrimaryCta && (\n <a\n href={clickUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline transition-colors duration-200 font-medium text-sm\"\n style={{\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textDecorationColor: TAIL_AD_COLORS.link,\n textUnderlineOffset: '2px',\n fontSize: '13px',\n }}\n onClick={handleCTAClick}\n >\n {ctaLabel}\n </a>\n )}\n\n {hasProductRail && relatedProducts.length > visibleProducts.length && (\n <span\n className=\"text-xs\"\n style={{ fontSize: '11px', color: TAIL_AD_COLORS.textMuted }}\n >\n +{relatedProducts.length - visibleProducts.length} more\n </span>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n <p className=\"text-xs\" style={{ fontSize: '11px', color: TAIL_AD_COLORS.textMuted }}>\n {disclosure || 'Sponsored'}\n </p>\n </div>\n </div>\n\n {showConsentPrompt ? (\n <div\n style={{\n marginTop: '10px',\n border: `1px solid ${cardBorder}`,\n borderRadius: '12px',\n backgroundColor: TAIL_AD_COLORS.surfaceSubtle,\n padding: '12px',\n display: 'flex',\n flexDirection: 'column',\n gap: '10px',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <div\n style={{\n fontSize: '11px',\n fontWeight: 700,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n color: TAIL_AD_COLORS.link,\n }}\n >\n Confirm Agent Access\n </div>\n <div\n style={{\n fontSize: '14px',\n lineHeight: 1.4,\n color: TAIL_AD_COLORS.text,\n fontWeight: 600,\n }}\n >\n Allow {delegationBrandName || 'this brand'} to start a delegated session?\n </div>\n <div\n style={{\n fontSize: '12px',\n lineHeight: 1.45,\n color: TAIL_AD_COLORS.textSecondary,\n }}\n >\n The agent will only use the details you choose to share for this request.\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(false);\n }}\n style={{\n borderRadius: '10px',\n border: `1px solid ${cardBorder}`,\n background: cardBackground,\n color: TAIL_AD_COLORS.text,\n fontSize: '12px',\n fontWeight: 600,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Not now\n </button>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(true);\n }}\n style={{\n borderRadius: '10px',\n border: 'none',\n background: '#2563eb',\n color: '#ffffff',\n fontSize: '12px',\n fontWeight: 700,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Allow agent\n </button>\n </div>\n </div>\n ) : null}\n </div>\n </div>\n </AdMeshViewabilityTracker>\n );\n};\n\nexport default AdMeshTailAd;\n","import React, { useCallback, useEffect, useRef } from 'react';\nimport type { AdMeshLinkTrackerProps } from '../types/index';\nimport { logger } from '../utils/logger';\n\n/**\n * AdMeshLinkTracker Component\n * \n * Wraps content with click tracking via AdMesh click URLs.\n * \n * Note: View/exposure tracking is handled separately by AdMeshViewabilityTracker component.\n * This component only handles click navigation to the admeshLink (which contains click tracking).\n * \n * The admeshLink prop should be the click URL from the recommendation, which already includes\n * all necessary tracking parameters and will redirect to the merchant URL.\n */\nexport const AdMeshLinkTracker: React.FC<AdMeshLinkTrackerProps> = ({\n recommendationId: _recommendationId,\n admeshLink,\n productId: _productId,\n children,\n trackingData: _trackingData,\n className,\n style\n}) => {\n const elementRef = useRef<HTMLDivElement>(null);\n\n // Ensure all child links open in new tab\n useEffect(() => {\n if (!elementRef.current) return;\n\n // Find all <a> tags within this component and ensure they open in new tab\n const links = elementRef.current.querySelectorAll('a');\n links.forEach((link) => {\n // Only set if not already set or if it's not _blank\n if (!link.hasAttribute('target') || link.getAttribute('target') !== '_blank') {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n });\n }, [children]); // Re-run when children change\n\n const handleClick = useCallback((event: React.MouseEvent) => {\n // The admeshLink already contains the click tracking URL from the backend\n // Navigating to it will automatically fire the click tracking pixel and redirect to merchant\n \n // If the children contain a link, ensure it opens in new tab\n // Otherwise, navigate programmatically\n const target = event.target as HTMLElement;\n const link = target.closest('a');\n\n if (!link) {\n // No link found, navigate programmatically to the click URL\n // The click URL will handle tracking and redirect\n if (admeshLink) {\n window.open(admeshLink, '_blank', 'noopener,noreferrer');\n } else {\n logger.warn('[AdMeshLinkTracker] No admeshLink provided for click tracking');\n }\n } else {\n // Link found - ensure it opens in new tab\n // If the link href is not set or is different from admeshLink, update it\n if (!link.href || link.href === '#' || link.href === '') {\n if (admeshLink) {\n link.href = admeshLink;\n }\n }\n if (!link.hasAttribute('target') || link.getAttribute('target') !== '_blank') {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n // Let the browser handle navigation naturally (click URL will track and redirect)\n }\n }, [admeshLink]);\n\n return (\n <div\n ref={elementRef}\n className={className}\n onClick={handleClick}\n style={{\n cursor: 'pointer',\n ...style\n }}\n >\n {children}\n </div>\n );\n};\n\nAdMeshLinkTracker.displayName = 'AdMeshLinkTracker';\n","/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames () {\n\t\tvar classes = '';\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (arg) {\n\t\t\t\tclasses = appendClass(classes, parseValue(arg));\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction parseValue (arg) {\n\t\tif (typeof arg === 'string' || typeof arg === 'number') {\n\t\t\treturn arg;\n\t\t}\n\n\t\tif (typeof arg !== 'object') {\n\t\t\treturn '';\n\t\t}\n\n\t\tif (Array.isArray(arg)) {\n\t\t\treturn classNames.apply(null, arg);\n\t\t}\n\n\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\treturn arg.toString();\n\t\t}\n\n\t\tvar classes = '';\n\n\t\tfor (var key in arg) {\n\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\tclasses = appendClass(classes, key);\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction appendClass (value, newClass) {\n\t\tif (!newClass) {\n\t\t\treturn value;\n\t\t}\n\t\n\t\tif (value) {\n\t\t\treturn value + ' ' + newClass;\n\t\t}\n\t\n\t\treturn value + newClass;\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n","import type { FC } from 'react';\nimport classNames from 'classnames';\nimport type { AdMeshBadgeProps, BadgeType } from '../types/index';\n\n// Badge type to variant mapping\nconst badgeTypeVariants: Record<BadgeType, string> = {\n 'Top Match': 'primary',\n 'Free Tier': 'success',\n 'AI Powered': 'secondary',\n 'Popular': 'warning',\n 'New': 'primary',\n 'Trial Available': 'success'\n};\n\n// Badge type to icon mapping (using clean Unicode symbols)\nconst badgeTypeIcons: Partial<Record<BadgeType, string>> = {\n 'Top Match': '★',\n 'Free Tier': '◆',\n 'AI Powered': '◉',\n 'Popular': '▲',\n 'New': '●',\n 'Trial Available': '◈'\n};\n\nexport const AdMeshBadge: FC<AdMeshBadgeProps> = ({\n type,\n variant,\n size = 'md',\n className,\n style\n}) => {\n const effectiveVariant = variant || badgeTypeVariants[type] || 'secondary';\n const icon = badgeTypeIcons[type];\n\n const badgeClasses = classNames(\n 'admesh-component',\n 'admesh-badge',\n `admesh-badge--${effectiveVariant}`,\n `admesh-badge--${size}`,\n className\n );\n\n return (\n <span\n className={badgeClasses}\n style={style}\n >\n {icon && <span className=\"admesh-badge__icon\">{icon}</span>}\n <span className=\"admesh-badge__text\">{type}</span>\n </span>\n );\n};\n\nAdMeshBadge.displayName = 'AdMeshBadge';\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.js';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.js';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { toKebabCase } from './shared/src/utils/toKebabCase.js';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"m21 3-7 7\", key: \"1l2asr\" }],\n [\"path\", { d: \"m3 21 7-7\", key: \"tjx5ai\" }],\n [\"path\", { d: \"M9 21H3v-6\", key: \"wtvkvv\" }]\n];\nconst Maximize2 = createLucideIcon(\"maximize-2\", __iconNode);\n\nexport { __iconNode, Maximize2 as default };\n//# sourceMappingURL=maximize-2.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m14 10 7-7\", key: \"oa77jy\" }],\n [\"path\", { d: \"M20 10h-6V4\", key: \"mjg0md\" }],\n [\"path\", { d: \"m3 21 7-7\", key: \"tjx5ai\" }],\n [\"path\", { d: \"M4 14h6v6\", key: \"rmj7iw\" }]\n];\nconst Minimize2 = createLucideIcon(\"minimize-2\", __iconNode);\n\nexport { __iconNode, Minimize2 as default };\n//# sourceMappingURL=minimize-2.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\",\n key: \"1ffxy3\"\n }\n ],\n [\"path\", { d: \"m21.854 2.147-10.94 10.939\", key: \"12cjpa\" }]\n];\nconst Send = createLucideIcon(\"send\", __iconNode);\n\nexport { __iconNode, Send as default };\n//# sourceMappingURL=send.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\",\n key: \"m61m77\"\n }\n ],\n [\"path\", { d: \"M17 14V2\", key: \"8ymqnk\" }]\n];\nconst ThumbsDown = createLucideIcon(\"thumbs-down\", __iconNode);\n\nexport { __iconNode, ThumbsDown as default };\n//# sourceMappingURL=thumbs-down.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\",\n key: \"emmmcr\"\n }\n ],\n [\"path\", { d: \"M7 10v12\", key: \"1qc93n\" }]\n];\nconst ThumbsUp = createLucideIcon(\"thumbs-up\", __iconNode);\n\nexport { __iconNode, ThumbsUp as default };\n//# sourceMappingURL=thumbs-up.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n];\nconst X = createLucideIcon(\"x\", __iconNode);\n\nexport { __iconNode, X as default };\n//# sourceMappingURL=x.js.map\n","/**\n * AdMesh Style Injection System\n * \n * Provides platform-agnostic, isolated styling for AdMesh components\n * that prevents interference from host platform CSS frameworks\n */\n\nconst ADMESH_STYLE_ID = 'admesh-ui-sdk-styles';\nconst ADMESH_RESET_ID = 'admesh-ui-sdk-reset';\n\n/**\n * CSS Reset for AdMesh components\n * Normalizes styles to prevent host platform CSS from affecting AdMesh components\n */\nconst ADMESH_CSS_RESET = `\n/* AdMesh UI SDK - CSS Reset & Normalization */\n.admesh-component,\n.admesh-component * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0;\n font-size: 100%;\n font-weight: normal;\n font-style: normal;\n line-height: 1.5;\n text-decoration: none;\n background: transparent;\n color: inherit;\n}\n\n.admesh-component {\n all: revert;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n}\n\n.admesh-component button,\n.admesh-component a {\n cursor: pointer;\n border: none;\n background: none;\n padding: 0;\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n}\n\n.admesh-component a {\n text-decoration: none;\n color: inherit;\n}\n\n.admesh-component button:focus,\n.admesh-component a:focus {\n outline: none;\n}\n\n.admesh-component img {\n max-width: 100%;\n height: auto;\n display: block;\n}\n\n.admesh-component ul,\n.admesh-component ol {\n list-style: none;\n}\n\n.admesh-component table {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\n.admesh-component input,\n.admesh-component textarea,\n.admesh-component select {\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n}\n\n/* Prevent Tailwind and other frameworks from affecting AdMesh */\n.admesh-component .prose,\n.admesh-component .container,\n.admesh-component .grid,\n.admesh-component .flex {\n all: revert;\n}\n\n/* Ensure AdMesh components are not affected by dark mode utilities */\n.admesh-component.dark,\n.admesh-component[data-admesh-theme=\"dark\"] {\n color-scheme: dark;\n}\n\n.admesh-component.light,\n.admesh-component[data-admesh-theme=\"light\"] {\n color-scheme: light;\n}\n`;\n\n/**\n * Core AdMesh Component Styles\n * Self-contained styles that work independently of host platform\n */\nconst ADMESH_CORE_STYLES = `\n/* AdMesh Core Component Styles */\n\n.admesh-component {\n position: relative;\n display: block;\n}\n\n/* Product Card Styles */\n.admesh-product-card {\n position: relative;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n height: 100%;\n border-radius: 0.75rem;\n background: rgb(255, 255, 255);\n border: 1px solid rgb(229, 231, 235);\n box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n overflow: hidden;\n}\n\n.admesh-product-card[data-admesh-theme=\"dark\"] {\n background: rgb(17, 24, 39);\n border-color: rgb(31, 41, 55);\n}\n\n.admesh-product-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n border-color: rgba(99, 102, 241, 0.2);\n}\n\n.admesh-product-card__container {\n position: relative;\n padding: 1rem;\n height: 100%;\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n z-index: 2;\n}\n\n.admesh-product-card__header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 0.5rem;\n margin-bottom: 0.25rem;\n}\n\n.admesh-product-card__title {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1.2;\n color: rgb(17, 24, 39);\n letter-spacing: -0.025em;\n transition: all 0.3s ease;\n}\n\n.admesh-product-card[data-admesh-theme=\"dark\"] .admesh-product-card__title {\n color: rgb(243, 244, 246);\n}\n\n.admesh-product-card:hover .admesh-product-card__title {\n transform: translateX(4px);\n}\n\n.admesh-product-card__cta {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n white-space: nowrap;\n border-radius: 0.5rem;\n font-size: 1rem;\n font-weight: 600;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0.75rem 1.5rem;\n background: rgb(0, 0, 0);\n color: rgb(255, 255, 255);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n}\n\n.admesh-product-card[data-admesh-theme=\"dark\"] .admesh-product-card__cta {\n background: rgb(255, 255, 255);\n color: rgb(0, 0, 0);\n}\n\n.admesh-product-card__cta:hover {\n transform: translateY(-2px);\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n}\n\n.admesh-product-card__cta:active {\n transform: translateY(0);\n}\n\n/* Summary Unit Styles */\n.admesh-summary-unit {\n font-size: 1rem;\n line-height: 1.6;\n color: rgb(17, 24, 39);\n}\n\n.admesh-summary-unit[data-admesh-theme=\"dark\"] {\n color: rgb(243, 244, 246);\n}\n\n.admesh-summary-unit a {\n color: rgb(37, 99, 235);\n text-decoration: underline;\n text-decoration-color: rgb(37, 99, 235);\n text-underline-offset: 2px;\n transition: all 0.2s ease;\n font-weight: 500;\n}\n\n.admesh-summary-unit[data-admesh-theme=\"dark\"] a {\n color: rgb(96, 165, 250);\n text-decoration-color: rgb(96, 165, 250);\n}\n\n.admesh-summary-unit a:hover {\n color: rgb(29, 78, 216);\n text-decoration-color: rgb(29, 78, 216);\n}\n\n.admesh-summary-unit[data-admesh-theme=\"dark\"] a:hover {\n color: rgb(147, 197, 253);\n text-decoration-color: rgb(147, 197, 253);\n}\n\n/* Ecommerce Cards Styles */\n.admesh-ecommerce-container {\n position: relative;\n width: 100%;\n}\n\n.admesh-ecommerce-card {\n flex-shrink: 0;\n background: white;\n border: 1px solid rgb(229, 231, 235);\n border-radius: 0.5rem;\n overflow: hidden;\n transition: all 0.2s ease-in-out;\n cursor: pointer;\n position: relative;\n}\n\n.admesh-ecommerce-card[data-admesh-theme=\"dark\"] {\n background: rgb(31, 41, 55);\n border-color: rgb(55, 65, 81);\n color: white;\n}\n\n.admesh-ecommerce-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);\n}\n\n/* Badge Styles */\n.admesh-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n border-radius: 0.5rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.875rem;\n font-weight: 600;\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n}\n\n.admesh-badge--primary {\n background: linear-gradient(135deg, rgb(99, 102, 241), rgb(79, 70, 229));\n color: white;\n box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.3);\n}\n\n.admesh-badge--secondary {\n background: rgb(243, 244, 246);\n color: rgb(55, 65, 81);\n}\n\n.admesh-badge[data-admesh-theme=\"dark\"].admesh-badge--secondary {\n background: rgb(31, 41, 55);\n color: rgb(209, 213, 219);\n}\n\n/* Responsive */\n@media (max-width: 640px) {\n .admesh-product-card__container {\n padding: 0.75rem;\n gap: 0.5rem;\n }\n\n .admesh-product-card__title {\n font-size: 1.25rem;\n }\n\n .admesh-product-card__cta {\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n }\n}\n`;\n\n/**\n * Inject AdMesh styles into the document\n * Ensures styles are loaded only once and don't conflict with host platform\n */\nexport const injectAdMeshStyles = (): void => {\n if (typeof document === 'undefined') return;\n\n // Check if styles already injected\n if (document.getElementById(ADMESH_RESET_ID) && document.getElementById(ADMESH_STYLE_ID)) {\n return;\n }\n\n // Inject CSS Reset\n if (!document.getElementById(ADMESH_RESET_ID)) {\n const resetStyle = document.createElement('style');\n resetStyle.id = ADMESH_RESET_ID;\n resetStyle.textContent = ADMESH_CSS_RESET;\n document.head.appendChild(resetStyle);\n }\n\n // Inject Core Styles\n if (!document.getElementById(ADMESH_STYLE_ID)) {\n const coreStyle = document.createElement('style');\n coreStyle.id = ADMESH_STYLE_ID;\n coreStyle.textContent = ADMESH_CORE_STYLES;\n document.head.appendChild(coreStyle);\n }\n};\n\n/**\n * Remove AdMesh styles from the document\n * Useful for cleanup or testing\n */\nexport const removeAdMeshStyles = (): void => {\n if (typeof document === 'undefined') return;\n\n const resetStyle = document.getElementById(ADMESH_RESET_ID);\n const coreStyle = document.getElementById(ADMESH_STYLE_ID);\n\n if (resetStyle) resetStyle.remove();\n if (coreStyle) coreStyle.remove();\n};\n\n/**\n * Check if AdMesh styles are already injected\n */\nexport const areAdMeshStylesInjected = (): boolean => {\n if (typeof document === 'undefined') return false;\n return !!(document.getElementById(ADMESH_RESET_ID) && document.getElementById(ADMESH_STYLE_ID));\n};\n\n","import { useEffect } from 'react';\nimport { logger } from '../utils/logger';\nimport { injectAdMeshStyles } from '../utils/styleInjection';\n\n// Complete CSS content as a string - this will be injected automatically\nconst ADMESH_STYLES = `\n/* AdMesh UI SDK - Complete Self-Contained Styles */\n\n/* CSS Reset for AdMesh components */\n.admesh-component, .admesh-component * {\n box-sizing: border-box;\n}\n\n/* CSS Variables - Black/White Color Scheme */\n.admesh-component {\n --admesh-primary: #000000;\n --admesh-primary-hover: #333333;\n --admesh-secondary: #666666;\n --admesh-accent: #000000;\n --admesh-background: #ffffff;\n --admesh-surface: #ffffff;\n --admesh-border: #e5e7eb;\n --admesh-text: #000000;\n --admesh-text-muted: #666666;\n --admesh-text-light: #999999;\n --admesh-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --admesh-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --admesh-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --admesh-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --admesh-radius: 0.5rem;\n --admesh-radius-sm: 0.25rem;\n --admesh-radius-lg: 0.75rem;\n --admesh-radius-xl: 1rem;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] {\n --admesh-primary: #ffffff;\n --admesh-primary-hover: #e5e7eb;\n --admesh-secondary: #9ca3af;\n --admesh-accent: #ffffff;\n --admesh-background: #000000;\n --admesh-surface: #111111;\n --admesh-border: #333333;\n --admesh-text: #ffffff;\n --admesh-text-muted: #9ca3af;\n --admesh-text-light: #666666;\n --admesh-shadow: 0 1px 3px 0 rgb(255 255 255 / 0.1), 0 1px 2px -1px rgb(255 255 255 / 0.1);\n --admesh-shadow-md: 0 4px 6px -1px rgb(255 255 255 / 0.1), 0 2px 4px -2px rgb(255 255 255 / 0.1);\n --admesh-shadow-lg: 0 10px 15px -3px rgb(255 255 255 / 0.1), 0 4px 6px -4px rgb(255 255 255 / 0.1);\n --admesh-shadow-xl: 0 20px 25px -5px rgb(255 255 255 / 0.1), 0 8px 10px -6px rgb(255 255 255 / 0.1);\n}\n\n/* Layout Styles */\n.admesh-layout {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n color: var(--admesh-text);\n background-color: var(--admesh-background);\n border-radius: var(--admesh-radius);\n padding: 1.5rem;\n box-shadow: var(--admesh-shadow);\n border: 1px solid var(--admesh-border);\n /* Consistent width: 100% for all layouts except ecommerce */\n width: 100%;\n}\n\n/* Ecommerce layout exception */\n.admesh-layout--ecommerce {\n width: auto;\n}\n\n/* Citation Unit Styles */\n.admesh-citation-unit {\n width: 100%;\n}\n\n/* Inline Recommendation Styles */\n.admesh-inline-recommendation {\n width: 100%;\n}\n\n/* Simple Ad Styles */\n.admesh-simple-ad {\n width: 100%;\n}\n\n.admesh-layout__header {\n margin-bottom: 1.5rem;\n text-align: center;\n}\n\n.admesh-layout__title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--admesh-text);\n margin-bottom: 0.5rem;\n}\n\n.admesh-layout__subtitle {\n font-size: 0.875rem;\n color: var(--admesh-text-muted);\n}\n\n.admesh-layout__cards-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 1rem;\n margin-bottom: 1.5rem;\n}\n\n.admesh-layout__more-indicator {\n text-align: center;\n padding: 1rem;\n color: var(--admesh-text-muted);\n font-size: 0.875rem;\n}\n\n.admesh-layout__empty {\n text-align: center;\n padding: 3rem 1rem;\n}\n\n.admesh-layout__empty-content h3 {\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--admesh-text-muted);\n margin-bottom: 0.5rem;\n}\n\n.admesh-layout__empty-content p {\n font-size: 0.875rem;\n color: var(--admesh-text-muted);\n}\n\n/* Product Card Styles */\n.admesh-product-card {\n background-color: var(--admesh-surface);\n border: 1px solid var(--admesh-border);\n border-radius: var(--admesh-radius);\n padding: 1.5rem;\n transition: all 0.2s ease-in-out;\n position: relative;\n overflow: hidden;\n /* Consistent width: 100% for product cards */\n width: 100%;\n}\n\n.admesh-product-card:hover {\n box-shadow: var(--admesh-shadow-lg);\n transform: translateY(-2px);\n border-color: var(--admesh-primary);\n}\n\n.admesh-product-card__header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__title {\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--admesh-text);\n margin-bottom: 0.5rem;\n line-height: 1.4;\n}\n\n.admesh-product-card__reason {\n font-size: 0.875rem;\n color: var(--admesh-text-muted);\n line-height: 1.5;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__match-score {\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__match-score-label {\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.75rem;\n color: var(--admesh-text-muted);\n margin-bottom: 0.25rem;\n}\n\n.admesh-product-card__match-score-bar {\n width: 100%;\n height: 0.375rem;\n background-color: var(--admesh-border);\n border-radius: var(--admesh-radius-sm);\n overflow: hidden;\n}\n\n.admesh-product-card__match-score-fill {\n height: 100%;\n background: var(--admesh-primary);\n border-radius: var(--admesh-radius-sm);\n transition: width 0.3s ease-in-out;\n}\n\n.admesh-product-card__badges {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__badge {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n background-color: var(--admesh-primary);\n color: white;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: var(--admesh-radius-sm);\n}\n\n.admesh-product-card__badge--secondary {\n background-color: var(--admesh-secondary);\n}\n\n.admesh-product-card__keywords {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__keyword {\n padding: 0.125rem 0.375rem;\n background-color: var(--admesh-border);\n color: var(--admesh-text-muted);\n font-size: 0.75rem;\n border-radius: var(--admesh-radius-sm);\n}\n\n/* Dark mode specific enhancements */\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-product-card__keyword {\n background-color: #4b5563;\n color: #d1d5db;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-product-card:hover {\n border-color: var(--admesh-primary);\n background-color: #374151;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-product-card__button:hover {\n background: var(--admesh-primary-hover);\n}\n\n.admesh-product-card__footer {\n display: flex;\n justify-content: flex-end;\n margin-top: 1.5rem;\n}\n\n/* Mobile-specific sidebar improvements */\n@media (max-width: 640px) {\n .admesh-sidebar {\n /* Ensure proper mobile viewport handling */\n height: 100vh !important;\n height: 100dvh !important; /* Dynamic viewport height for mobile browsers */\n max-height: 100vh !important;\n max-height: 100dvh !important;\n width: 100vw !important;\n max-width: 90vw !important;\n overflow: hidden !important;\n }\n\n .admesh-sidebar.relative {\n height: 100% !important;\n width: 100% !important;\n max-width: 100% !important;\n }\n\n /* Improve touch scrolling */\n .admesh-sidebar .overflow-y-auto {\n -webkit-overflow-scrolling: touch !important;\n overscroll-behavior: contain !important;\n scroll-behavior: smooth !important;\n }\n\n /* Prevent body scroll when sidebar is open */\n body:has(.admesh-sidebar[data-mobile-open=\"true\"]) {\n overflow: hidden !important;\n position: fixed !important;\n width: 100% !important;\n }\n}\n\n/* Tablet improvements */\n@media (min-width: 641px) and (max-width: 1024px) {\n .admesh-sidebar {\n max-width: 400px !important;\n }\n}\n\n/* Mobile responsiveness improvements for all components */\n@media (max-width: 640px) {\n /* Product cards mobile optimization */\n .admesh-card {\n padding: 0.75rem !important;\n margin-bottom: 0.75rem !important;\n }\n\n /* Inline recommendations mobile optimization */\n .admesh-inline-recommendation {\n padding: 0.5rem !important;\n margin-bottom: 0.5rem !important;\n }\n\n /* Conversation summary mobile optimization */\n .admesh-conversation-summary {\n padding: 1rem !important;\n }\n\n /* Percentage text mobile improvements */\n .admesh-component .text-xs {\n font-size: 0.75rem !important;\n line-height: 1rem !important;\n }\n\n .admesh-component .text-sm {\n font-size: 0.875rem !important;\n line-height: 1.25rem !important;\n }\n\n /* Button mobile improvements */\n .admesh-component button {\n padding: 0.375rem 0.75rem !important;\n font-size: 0.75rem !important;\n min-height: 2rem !important;\n touch-action: manipulation !important;\n }\n\n /* Badge mobile improvements */\n .admesh-component .rounded-full {\n padding: 0.25rem 0.5rem !important;\n font-size: 0.625rem !important;\n line-height: 1rem !important;\n }\n\n /* Progress bar mobile improvements */\n .admesh-component .bg-gray-200,\n .admesh-component .bg-slate-600 {\n height: 0.25rem !important;\n }\n\n /* Flex layout mobile improvements */\n .admesh-component .flex {\n flex-wrap: wrap !important;\n }\n\n .admesh-component .gap-2 {\n gap: 0.375rem !important;\n }\n\n .admesh-component .gap-3 {\n gap: 0.5rem !important;\n }\n}\n\n.admesh-product-card__button {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: var(--admesh-primary);\n color: var(--admesh-background);\n font-size: 0.875rem;\n font-weight: 500;\n border: none;\n border-radius: var(--admesh-radius);\n cursor: pointer;\n transition: all 0.2s ease-in-out;\n text-decoration: none;\n}\n\n.admesh-product-card__button:hover {\n transform: translateY(-1px);\n box-shadow: var(--admesh-shadow-lg);\n}\n\n/* Utility Classes */\n.admesh-text-xs { font-size: 0.75rem; }\n.admesh-text-sm { font-size: 0.875rem; }\n.admesh-text-base { font-size: 1rem; }\n.admesh-text-lg { font-size: 1.125rem; }\n.admesh-text-xl { font-size: 1.25rem; }\n\n.admesh-font-medium { font-weight: 500; }\n.admesh-font-semibold { font-weight: 600; }\n.admesh-font-bold { font-weight: 700; }\n\n.admesh-text-muted { color: var(--admesh-text-muted); }\n\n/* Comparison Table Styles */\n.admesh-compare-table {\n width: 100%;\n border-collapse: collapse;\n background-color: var(--admesh-surface);\n border: 1px solid var(--admesh-border);\n border-radius: var(--admesh-radius);\n overflow: hidden;\n}\n\n.admesh-compare-table th,\n.admesh-compare-table td {\n padding: 0.75rem;\n text-align: left;\n border-bottom: 1px solid var(--admesh-border);\n}\n\n.admesh-compare-table th {\n background-color: var(--admesh-background);\n font-weight: 600;\n color: var(--admesh-text);\n font-size: 0.875rem;\n}\n\n.admesh-compare-table td {\n color: var(--admesh-text);\n font-size: 0.875rem;\n}\n\n.admesh-compare-table tr:hover {\n background-color: var(--admesh-border);\n}\n\n/* Dark mode table enhancements */\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-compare-table th {\n background-color: #374151;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-compare-table tr:hover {\n background-color: #4b5563;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .admesh-layout {\n padding: 1rem;\n }\n\n .admesh-layout__cards-grid {\n grid-template-columns: 1fr;\n gap: 0.75rem;\n }\n\n .admesh-product-card {\n padding: 1rem;\n }\n\n .admesh-compare-table {\n font-size: 0.75rem;\n }\n\n .admesh-compare-table th,\n .admesh-compare-table td {\n padding: 0.5rem;\n }\n}\n\n/* Essential Utility Classes for Self-Contained SDK - High Specificity */\n.admesh-component .relative { position: relative !important; }\n.admesh-component .absolute { position: absolute !important; }\n.admesh-component .flex { display: flex !important; }\n.admesh-component .inline-flex { display: inline-flex !important; }\n.admesh-component .grid { display: grid !important; }\n.admesh-component .hidden { display: none !important; }\n.admesh-component .block { display: block !important; }\n.admesh-component .inline-block { display: inline-block !important; }\n\n/* Flexbox utilities */\n.admesh-component .flex-col { flex-direction: column !important; }\n.admesh-component .flex-row { flex-direction: row !important; }\n.admesh-component .flex-wrap { flex-wrap: wrap !important; }\n.admesh-component .items-center { align-items: center !important; }\n.admesh-component .items-start { align-items: flex-start !important; }\n.admesh-component .items-end { align-items: flex-end !important; }\n.admesh-component .justify-center { justify-content: center !important; }\n.admesh-component .justify-between { justify-content: space-between !important; }\n.admesh-component .justify-end { justify-content: flex-end !important; }\n.admesh-component .flex-1 { flex: 1 1 0% !important; }\n.admesh-component .flex-shrink-0 { flex-shrink: 0 !important; }\n\n/* Grid utilities */\n.admesh-component .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }\n.admesh-component .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n.admesh-component .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n\n/* Spacing utilities */\n.admesh-component .gap-1 { gap: 0.25rem; }\n.admesh-component .gap-2 { gap: 0.5rem; }\n.admesh-component .gap-3 { gap: 0.75rem; }\n.admesh-component .gap-4 { gap: 1rem; }\n.admesh-component .gap-6 { gap: 1.5rem; }\n.admesh-component .gap-8 { gap: 2rem; }\n\n/* Padding utilities */\n.admesh-component .p-1 { padding: 0.25rem; }\n.admesh-component .p-2 { padding: 0.5rem; }\n.admesh-component .p-3 { padding: 0.75rem; }\n.admesh-component .p-4 { padding: 1rem; }\n.admesh-component .p-5 { padding: 1.25rem; }\n.admesh-component .p-6 { padding: 1.5rem; }\n.admesh-component .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }\n.admesh-component .px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }\n.admesh-component .px-4 { padding-left: 1rem; padding-right: 1rem; }\n.admesh-component .py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }\n.admesh-component .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }\n.admesh-component .py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }\n.admesh-component .pt-2 { padding-top: 0.5rem; }\n.admesh-component .pt-3 { padding-top: 0.75rem; }\n.admesh-component .pb-2 { padding-bottom: 0.5rem; }\n.admesh-component .pb-3 { padding-bottom: 0.75rem; }\n\n/* Margin utilities */\n.admesh-component .m-0 { margin: 0; }\n.admesh-component .mb-1 { margin-bottom: 0.25rem; }\n.admesh-component .mb-2 { margin-bottom: 0.5rem; }\n.admesh-component .mb-3 { margin-bottom: 0.75rem; }\n.admesh-component .mb-4 { margin-bottom: 1rem; }\n.admesh-component .mb-6 { margin-bottom: 1.5rem; }\n.admesh-component .mt-1 { margin-top: 0.25rem; }\n.admesh-component .mt-2 { margin-top: 0.5rem; }\n.admesh-component .mt-4 { margin-top: 1rem; }\n.admesh-component .mt-6 { margin-top: 1.5rem; }\n.admesh-component .mt-auto { margin-top: auto; }\n.admesh-component .ml-1 { margin-left: 0.25rem; }\n.admesh-component .mr-1 { margin-right: 0.25rem; }\n.admesh-component .mr-2 { margin-right: 0.5rem; }\n\n/* Width and height utilities */\n.admesh-component .w-2 { width: 0.5rem; }\n.admesh-component .w-3 { width: 0.75rem; }\n.admesh-component .w-4 { width: 1rem; }\n.admesh-component .w-5 { width: 1.25rem; }\n.admesh-component .w-6 { width: 1.5rem; }\n.admesh-component .w-full { width: 100%; }\n.admesh-component .w-fit { width: fit-content; }\n.admesh-component .h-2 { height: 0.5rem; }\n.admesh-component .h-3 { height: 0.75rem; }\n.admesh-component .h-4 { height: 1rem; }\n.admesh-component .h-5 { height: 1.25rem; }\n.admesh-component .h-6 { height: 1.5rem; }\n.admesh-component .h-full { height: 100%; }\n.admesh-component .min-w-0 { min-width: 0px; }\n\n/* Border utilities */\n.admesh-component .border { border-width: 1px; }\n.admesh-component .border-t { border-top-width: 1px; }\n.admesh-component .border-gray-100 { border-color: #f3f4f6; }\n.admesh-component .border-gray-200 { border-color: #e5e7eb; }\n.admesh-component .border-gray-300 { border-color: #d1d5db; }\n.admesh-component .border-blue-200 { border-color: #bfdbfe; }\n.admesh-component .border-green-200 { border-color: #bbf7d0; }\n\n/* Border radius utilities */\n.admesh-component .rounded { border-radius: 0.25rem !important; }\n.admesh-component .rounded-md { border-radius: 0.375rem !important; }\n.admesh-component .rounded-lg { border-radius: 0.5rem !important; }\n.admesh-component .rounded-xl { border-radius: 0.75rem !important; }\n.admesh-component .rounded-full { border-radius: 9999px !important; }\n\n/* Background utilities */\n.admesh-component .bg-white { background-color: #ffffff; }\n.admesh-component .bg-gray-50 { background-color: #f9fafb; }\n.admesh-component .bg-gray-100 { background-color: #f3f4f6; }\n.admesh-component .bg-blue-50 { background-color: #eff6ff; }\n.admesh-component .bg-blue-100 { background-color: #dbeafe; }\n.admesh-component .bg-green-100 { background-color: #dcfce7; }\n.admesh-component .bg-green-500 { background-color: #22c55e; }\n.admesh-component .bg-blue-500 { background-color: #3b82f6; }\n\n/* Solid backgrounds - no gradients for minimal design */\n.admesh-component .bg-primary { background-color: var(--admesh-primary); }\n.admesh-component .bg-secondary { background-color: var(--admesh-secondary); }\n.admesh-component .bg-surface { background-color: var(--admesh-surface); }\n.admesh-component .bg-background { background-color: var(--admesh-background); }\n\n/* Text utilities */\n.admesh-component .text-xs { font-size: 0.75rem; line-height: 1rem; }\n.admesh-component .text-sm { font-size: 0.875rem; line-height: 1.25rem; }\n.admesh-component .text-base { font-size: 1rem; line-height: 1.5rem; }\n.admesh-component .text-lg { font-size: 1.125rem; line-height: 1.75rem; }\n.admesh-component .text-xl { font-size: 1.25rem; line-height: 1.75rem; }\n.admesh-component .font-medium { font-weight: 500; }\n.admesh-component .font-semibold { font-weight: 600; }\n.admesh-component .font-bold { font-weight: 700; }\n.admesh-component .leading-relaxed { line-height: 1.625; }\n\n/* Text colors */\n.admesh-component .text-white { color: #ffffff; }\n.admesh-component .text-gray-400 { color: #9ca3af; }\n.admesh-component .text-gray-500 { color: #6b7280; }\n.admesh-component .text-gray-600 { color: #4b5563; }\n.admesh-component .text-gray-700 { color: #374151; }\n.admesh-component .text-gray-800 { color: #1f2937; }\n.admesh-component .text-blue-600 { color: #2563eb; }\n.admesh-component .text-blue-700 { color: #1d4ed8; }\n.admesh-component .text-green-700 { color: #15803d; }\n\n/* Shadow utilities */\n.admesh-component .shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }\n.admesh-component .shadow { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }\n.admesh-component .shadow-md { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); }\n.admesh-component .shadow-lg { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); }\n.admesh-component .shadow-xl { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); }\n\n/* Transition utilities */\n.admesh-component .transition-all { transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }\n.admesh-component .transition-colors { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }\n.admesh-component .duration-200 { transition-duration: 200ms; }\n.admesh-component .duration-300 { transition-duration: 300ms; }\n\n/* Transform utilities */\n.admesh-component .hover\\\\:-translate-y-1:hover { transform: translateY(-0.25rem); }\n.admesh-component .hover\\\\:scale-105:hover { transform: scale(1.05); }\n\n/* Hover utilities */\n.admesh-component .hover\\\\:shadow-xl:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); }\n.admesh-component .hover\\\\:bg-gray-100:hover { background-color: #f3f4f6; }\n.admesh-component .hover\\\\:text-blue-800:hover { color: #1e40af; }\n\n/* Cursor utilities */\n.admesh-component .cursor-pointer { cursor: pointer; }\n\n/* Overflow utilities */\n.admesh-component .overflow-hidden { overflow: hidden; }\n.admesh-component .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n/* Text decoration */\n.admesh-component .underline { text-decoration-line: underline; }\n\n/* Whitespace */\n.admesh-component .whitespace-nowrap { white-space: nowrap; }\n\n/* Dark mode utilities */\n@media (prefers-color-scheme: dark) {\n .admesh-component .dark\\\\:bg-slate-800 { background-color: #1e293b; }\n .admesh-component .dark\\\\:bg-slate-900 { background-color: #0f172a; }\n .admesh-component .dark\\\\:border-slate-700 { border-color: #334155; }\n .admesh-component .dark\\\\:text-white { color: #ffffff; }\n .admesh-component .dark\\\\:text-gray-200 { color: #e5e7eb; }\n .admesh-component .dark\\\\:text-gray-300 { color: #d1d5db; }\n .admesh-component .dark\\\\:text-gray-400 { color: #9ca3af; }\n .admesh-component .dark\\\\:text-blue-400 { color: #60a5fa; }\n}\n\n/* Responsive utilities */\n@media (min-width: 640px) {\n .admesh-component .sm\\\\:p-5 { padding: 1.25rem; }\n .admesh-component .sm\\\\:text-base { font-size: 1rem; line-height: 1.5rem; }\n .admesh-component .sm\\\\:text-lg { font-size: 1.125rem; line-height: 1.75rem; }\n .admesh-component .sm\\\\:flex-row { flex-direction: row; }\n .admesh-component .sm\\\\:items-center { align-items: center; }\n .admesh-component .sm\\\\:justify-between { justify-content: space-between; }\n}\n\n@media (min-width: 768px) {\n .admesh-component .md\\\\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n\n@media (min-width: 1024px) {\n .admesh-component .lg\\\\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n .admesh-component .lg\\\\:col-span-1 { grid-column: span 1 / span 1; }\n}\n`;\n\nlet stylesInjected = false;\n\n/**\n * Hook to inject AdMesh styles into the document\n * Ensures platform-agnostic, isolated styling that prevents\n * interference from host platform CSS frameworks\n *\n * Usage:\n * const MyComponent = () => {\n * useAdMeshStyles();\n * return <div className=\"admesh-component\">...</div>;\n * };\n */\nexport const useAdMeshStyles = () => {\n useEffect(() => {\n if (stylesInjected) return;\n\n try {\n // Use the new style injection system for better isolation\n injectAdMeshStyles();\n\n // Also inject the legacy styles for backward compatibility\n const styleElement = document.createElement('style');\n styleElement.id = 'admesh-ui-sdk-styles-legacy';\n styleElement.textContent = ADMESH_STYLES;\n\n if (!document.getElementById('admesh-ui-sdk-styles-legacy')) {\n document.head.appendChild(styleElement);\n }\n\n stylesInjected = true;\n } catch (error) {\n logger.error('[AdMesh] Failed to inject styles');\n }\n\n // Cleanup function\n return () => {\n // Note: We don't remove styles on unmount to prevent flickering\n // Styles are designed to be persistent for the lifetime of the app\n };\n }, []);\n};\n","\"use client\";\n\nimport { Fragment, useState, useEffect, useLayoutEffect, useRef, useCallback, useMemo, type CSSProperties, type FC, type ReactNode } from \"react\";\nimport { XIcon, SendIcon, Maximize2, Minimize2, ThumbsUp, ThumbsDown } from \"lucide-react\";\nimport type { PlatformResponse, AdMeshTheme, ChatMessage } from \"../types/index\";\nimport { AdMeshRecommendations } from \"./AdMeshRecommendations\";\nimport { useAdMesh } from \"../hooks/useAdMesh\";\nimport { useAdMeshStyles } from \"../hooks/useAdMeshStyles\";\nimport { useAdMeshContext } from \"../context/AdMeshContext\";\nimport type { PublisherAssistantAnalyticsEvent } from \"../sdk/AdMeshSDK\";\n\nfunction formatGenerationDuration(totalSeconds: number): string {\n const seconds = Math.max(1, Math.round(totalSeconds));\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n const remainder = seconds % 60;\n return remainder > 0 ? `${minutes}m ${remainder}s` : `${minutes}m`;\n}\n\nfunction formatGenerationDurationFromMs(durationMs: number): string {\n return formatGenerationDuration(durationMs / 1000);\n}\n\ntype AnswerFeedbackValue = 'helpful' | 'not_helpful';\n\n// Custom markdown renderer with proper styling\nconst CustomMarkdownRenderer = ({ content, theme, fontSize }: { content: string; theme: AdMeshTheme; fontSize: string }) => {\n const renderInlineFormatting = (text: string) => {\n const parts = text.split(/(\\*\\*[^*]+\\*\\*)/g);\n return parts.map((part, index) => {\n if (part.startsWith('**') && part.endsWith('**') && part.length > 4) {\n return (\n <strong key={index} style={{ fontWeight: '600', color: theme.textColor }}>\n {part.slice(2, -2)}\n </strong>\n );\n }\n return <Fragment key={index}>{part}</Fragment>;\n });\n };\n\n const parseTableRow = (line: string) => {\n const trimmed = line.trim().replace(/^\\|/, '').replace(/\\|$/, '');\n return trimmed.split('|').map((cell) => cell.trim()).filter((cell, index, cells) => (\n cell.length > 0 || index < cells.length - 1\n ));\n };\n\n const isTableSeparator = (line: string) => {\n const cells = parseTableRow(line);\n return cells.length > 1 && cells.every((cell) => /^:?-{3,}:?$/.test(cell));\n };\n\n const splitTablePrefixHeading = (line: string) => {\n const pipeIndex = line.indexOf('|');\n if (pipeIndex <= 0) {\n return { heading: null as string | null, headerLine: line };\n }\n const prefix = line.slice(0, pipeIndex).trim();\n if (!prefix || /^[-|:\\s]+$/.test(prefix)) {\n return { heading: null, headerLine: line };\n }\n return { heading: prefix, headerLine: line.slice(pipeIndex).trim() };\n };\n\n const normalizeTableSeparator = (headerLine: string, separatorLine: string) => {\n const headerCount = parseTableRow(headerLine).length;\n const separatorCount = parseTableRow(separatorLine).length;\n if (headerCount <= 1 || headerCount === separatorCount) {\n return separatorLine;\n }\n return `| ${Array.from({ length: headerCount }, () => '---').join(' | ')} |`;\n };\n\n const normalizeTableLines = (lines: string[]) => {\n if (lines.length < 2 || !lines[0].includes('|')) {\n return { heading: null as string | null, lines };\n }\n const { heading, headerLine } = splitTablePrefixHeading(lines[0]);\n const normalizedHeader = headerLine.startsWith('|') ? headerLine : `| ${headerLine}`;\n const normalizedSeparator = normalizeTableSeparator(normalizedHeader, lines[1]);\n return {\n heading,\n lines: [normalizedHeader, normalizedSeparator, ...lines.slice(2)],\n };\n };\n\n const isMarkdownTable = (lines: string[]) => {\n if (lines.length < 2 || !lines[0].includes('|')) {\n return false;\n }\n const { lines: normalizedLines } = normalizeTableLines(lines);\n return (\n isTableSeparator(normalizedLines[1]) &&\n parseTableRow(normalizedLines[0]).length >= 2\n );\n };\n\n const expandInlineTableLine = (line: string) => {\n if (!line.includes('|')) {\n return [line];\n }\n\n let working = line.trim();\n const result: string[] = [];\n\n const pipeIndex = working.indexOf('|');\n if (pipeIndex > 0) {\n const prefix = working.slice(0, pipeIndex).trim();\n if (prefix && !/^[-|:\\s]+$/.test(prefix)) {\n result.push(prefix);\n working = working.slice(pipeIndex).trim();\n }\n }\n\n // Some models (e.g. Gemma) emit header + separator + rows on one line.\n working = working.replace(/\\|\\s*(\\|(?:\\s*:?-{3,}:?\\s*\\|)+)/g, (_match, separatorRow: string) => `\\n${separatorRow}`);\n working = working.replace(/\\|\\s*\\|\\s*(?=[A-Za-z0-9*])/g, '|\\n| ');\n working = working.replace(/\\|\\s+(?=\\|(?!\\s*:?-{3,}:?\\s*\\|)[^|\\n])/g, '|\\n');\n\n result.push(...working.split('\\n').map((part) => part.trim()).filter(Boolean));\n return result;\n };\n\n const normalizeCompactMarkdownTables = (markdown: string) => {\n const lines = markdown.split('\\n');\n const normalized: string[] = [];\n\n for (const line of lines) {\n if (!line.includes('|')) {\n normalized.push(line);\n continue;\n }\n normalized.push(...expandInlineTableLine(line));\n }\n\n return normalized.join('\\n');\n };\n\n const isolateMarkdownTables = (markdown: string) => {\n const lines = normalizeCompactMarkdownTables(markdown).split('\\n');\n const output: string[] = [];\n let index = 0;\n\n while (index < lines.length) {\n const line = lines[index];\n const nextLine = lines[index + 1] || '';\n\n if (line.includes('|') && isTableSeparator(nextLine)) {\n if (output.length > 0 && output[output.length - 1].trim()) {\n output.push('');\n }\n\n const { heading, headerLine } = splitTablePrefixHeading(line);\n if (heading) {\n output.push(heading);\n }\n output.push(headerLine, normalizeTableSeparator(headerLine, nextLine));\n index += 2;\n\n while (index < lines.length && lines[index].includes('|') && lines[index].trim()) {\n output.push(lines[index]);\n index += 1;\n }\n\n if (index < lines.length && lines[index].trim()) {\n output.push('');\n }\n continue;\n }\n\n output.push(line);\n index += 1;\n }\n\n return output.join('\\n');\n };\n\n const blocks = isolateMarkdownTables(content)\n .split(/\\n\\s*\\n/)\n .map((block) => block.trim())\n .filter(Boolean);\n\n return (\n <div style={{ margin: 0, color: theme.textColor, fontSize }}>\n {blocks.map((block, blockIndex) => {\n const lines = block.split('\\n').map((line) => line.trim()).filter(Boolean);\n const isBulletList = lines.every((line) => /^[-*]\\s+/.test(line));\n const isNumberedList = lines.every((line) => /^\\d+\\.\\s+/.test(line));\n const isHeading = lines.length === 1 && /^#{1,3}\\s+/.test(lines[0]);\n const isTable = isMarkdownTable(lines);\n\n if (isHeading) {\n const text = lines[0].replace(/^#{1,3}\\s+/, '');\n return (\n <h3\n key={blockIndex}\n style={{\n marginTop: blockIndex === 0 ? 0 : '1rem',\n marginBottom: '0.75rem',\n fontWeight: '600',\n fontSize: '1.05em',\n color: theme.textColor,\n }}\n >\n {renderInlineFormatting(text)}\n </h3>\n );\n }\n\n if (isTable) {\n const { heading, lines: tableLines } = normalizeTableLines(lines);\n const headers = parseTableRow(tableLines[0]);\n const rows = tableLines.slice(2).map(parseTableRow).filter((row) => row.length === headers.length);\n\n return (\n <div\n key={blockIndex}\n style={{\n width: '100%',\n overflowX: 'auto',\n marginBottom: '1rem',\n }}\n >\n {heading ? (\n <p\n style={{\n marginTop: blockIndex === 0 ? 0 : '1rem',\n marginBottom: '0.75rem',\n fontWeight: 600,\n color: theme.textColor,\n fontSize,\n }}\n >\n {renderInlineFormatting(heading)}\n </p>\n ) : null}\n <div\n style={{\n border: `1px solid ${theme.borderColor || 'rgba(148, 163, 184, 0.28)'}`,\n borderRadius: 8,\n overflowX: 'auto',\n }}\n >\n <table\n style={{\n width: '100%',\n minWidth: headers.length > 3 ? 520 : undefined,\n borderCollapse: 'collapse',\n color: theme.textColor,\n fontSize,\n lineHeight: 1.45,\n }}\n >\n <thead>\n <tr>\n {headers.map((header, index) => (\n <th\n key={index}\n style={{\n textAlign: 'left',\n padding: '9px 10px',\n fontWeight: 600,\n background: theme.surfaceColor || 'rgba(148, 163, 184, 0.12)',\n borderBottom: `1px solid ${theme.borderColor || 'rgba(148, 163, 184, 0.28)'}`,\n whiteSpace: 'normal',\n }}\n >\n {renderInlineFormatting(header)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((cell, cellIndex) => (\n <td\n key={cellIndex}\n style={{\n padding: '9px 10px',\n verticalAlign: 'top',\n borderBottom:\n rowIndex === rows.length - 1\n ? 'none'\n : `1px solid ${theme.borderColor || 'rgba(148, 163, 184, 0.18)'}`,\n whiteSpace: 'normal',\n }}\n >\n {renderInlineFormatting(cell)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n }\n\n if (isBulletList || isNumberedList) {\n const ListTag = isNumberedList ? 'ol' : 'ul';\n return (\n <ListTag\n key={blockIndex}\n style={{\n marginBottom: '1rem',\n paddingLeft: '1.25rem',\n color: theme.textColor,\n fontSize,\n }}\n >\n {lines.map((line, lineIndex) => (\n <li key={lineIndex} style={{ marginBottom: '0.45rem' }}>\n {renderInlineFormatting(line.replace(/^([-*]|\\d+\\.)\\s+/, ''))}\n </li>\n ))}\n </ListTag>\n );\n }\n\n return (\n <p\n key={blockIndex}\n style={{\n marginBottom: '1rem',\n lineHeight: '1.6',\n color: theme.textColor,\n fontSize,\n whiteSpace: 'pre-wrap',\n }}\n >\n {lines.map((line, lineIndex) => (\n <Fragment key={lineIndex}>\n {lineIndex > 0 && <br />}\n {renderInlineFormatting(line)}\n </Fragment>\n ))}\n </p>\n );\n })}\n </div>\n );\n};\n\n// Types for the Intent Assistant\nexport interface Suggestion {\n id: string;\n text: string;\n type: 'product' | 'comparison' | 'information' | 'action';\n is_sponsored?: boolean;\n recommendation?: PlatformResponse;\n metadata?: Record<string, unknown>;\n}\n\nexport interface AssistantSourceLink {\n title?: string;\n url: string;\n}\n\nexport interface AssistantRelatedItem {\n title?: string;\n url: string;\n snippet?: string;\n image_url?: string | null;\n publisher?: string | null;\n}\n\nexport interface AssistantQueryResult {\n answer: string;\n source_links?: AssistantSourceLink[];\n related_items?: AssistantRelatedItem[];\n recommendation?: PlatformResponse | null;\n followup_suggestions?: Array<{ text: string; type?: Suggestion['type'] }>;\n}\n\nexport interface AssistantQueryContext {\n sponsoredSuggestion?: Suggestion | null;\n}\n\ntype SuggestionStyle = 'carousel' | 'stacked';\n\nfunction toCssSize(value?: number | string) {\n return value === undefined ? undefined : typeof value === 'number' ? `${value}px` : value;\n}\n\nexport interface AdMeshIntentAssistantProps {\n // AssistantModal Root props\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n unstable_openOnRunStart?: boolean;\n \n // UI Configuration\n layout?: 'floating' | 'inline';\n surface?: 'page' | 'ad-slot';\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n size?: 'sm' | 'md' | 'lg' | 'xl';\n theme?: AdMeshTheme;\n className?: string;\n style?: CSSProperties;\n triggerLabel?: string;\n triggerIcon?: ReactNode;\n headerTitle?: string;\n headerIcon?: ReactNode;\n headerLogoUrl?: string | null;\n showHeaderTitle?: boolean;\n showSubtitle?: boolean;\n panelWidth?: number | string;\n panelHeight?: number | string;\n fontScale?: number;\n analyticsPageUrl?: string;\n \n // Behavior\n autoOpen?: boolean;\n showWelcomeMessage?: boolean;\n welcomeMessage?: string;\n placeholder?: string;\n adsEnabled?: boolean;\n suggestions?: Suggestion[]; // Optional - will use context suggestions if not provided\n maxSuggestions?: number;\n suggestionStyle?: SuggestionStyle;\n onlyShowWhenSponsored?: boolean; // Only show modal when sponsored suggestions are available\n variant?: 'default' | 'legacy';\n queryHandler?: (query: string, context: AssistantQueryContext) => Promise<AssistantQueryResult>;\n suggestionsLoader?: () => Promise<Suggestion[]>;\n disclaimerText?: string;\n poweredByLabel?: string;\n subtitle?: string;\n \n // Events\n onOpen?: () => void;\n onClose?: () => void;\n}\n\nfunction normalizeSuggestionText(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\nfunction mergeSuggestionsPreservingOrganic(\n currentSuggestions: Suggestion[],\n nextSuggestions: Suggestion[],\n): Suggestion[] {\n const currentOrganicSuggestions = currentSuggestions\n .filter((suggestion) => !suggestion?.is_sponsored)\n .slice(0, 3);\n const nextOrganicSuggestions = nextSuggestions\n .filter((suggestion) => !suggestion?.is_sponsored)\n .slice(0, 3);\n\n const sponsoredSuggestion = nextSuggestions.find((suggestion) => suggestion?.is_sponsored);\n\n if (!sponsoredSuggestion) {\n return nextOrganicSuggestions.length ? nextOrganicSuggestions : currentOrganicSuggestions;\n }\n\n const organicSuggestions = nextOrganicSuggestions.length ? nextOrganicSuggestions : currentOrganicSuggestions;\n return [sponsoredSuggestion, ...organicSuggestions].slice(0, 4);\n}\n\nfunction buildFollowupSuggestionsFromAnswer(\n query: string,\n answer: string,\n sourceLinks?: AssistantSourceLink[],\n relatedItems?: AssistantRelatedItem[],\n): Suggestion[] {\n const seen = new Set<string>();\n const suggestions: Suggestion[] = [];\n\n const pushSuggestion = (text: string, type: Suggestion['type'] = 'information') => {\n const normalized = normalizeSuggestionText(text);\n if (!normalized) return;\n const key = normalized.toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n suggestions.push({\n id: `followup_${suggestions.length}_${key.replace(/[^a-z0-9]+/g, '_')}`,\n text: normalized,\n type,\n is_sponsored: false,\n });\n };\n\n const topics = new Set<string>();\n\n const collectTopic = (value?: string | null) => {\n const normalized = normalizeSuggestionText(value || '');\n if (!normalized) return;\n const cleaned = normalized\n .replace(/^(how|why|what|when|where|which|who)\\s+/i, '')\n .replace(/\\?+$/g, '')\n .trim();\n if (!cleaned) return;\n topics.add(cleaned);\n };\n\n (relatedItems || []).forEach((item) => collectTopic(item?.title));\n (sourceLinks || []).forEach((item) => collectTopic(item?.title));\n\n const sentenceMatches = answer\n .split(/\\n+/)\n .map((line) => normalizeSuggestionText(line.replace(/^[-*]\\s+/, '')))\n .filter(Boolean)\n .filter((line) => line.length >= 24 && line.length <= 90);\n\n sentenceMatches.forEach((line) => {\n if (topics.size >= 6) return;\n collectTopic(line);\n });\n\n const cleanQuery = normalizeSuggestionText(query.replace(/[?.!]+$/g, ''));\n const topicList = Array.from(topics).slice(0, 3);\n const continuations = [\n topicList[0] ? `Tell me more about ${topicList[0]}` : '',\n topicList[1] ? `Show me examples related to ${topicList[1]}` : '',\n topicList[2] ? `Compare the main options for ${topicList[2]}` : '',\n `Break this down more simply`,\n `What should I look at next about ${cleanQuery}`,\n `Give me the practical takeaway here`,\n ];\n\n continuations.forEach((text, index) => {\n if (suggestions.length >= 3) return;\n pushSuggestion(text, index === 0 ? 'comparison' : 'information');\n });\n\n return suggestions.slice(0, 3);\n}\n\nfunction detectAssistantDeviceType(): PublisherAssistantAnalyticsEvent['device_type'] {\n if (typeof window === 'undefined') return 'unknown';\n const width = window.innerWidth;\n if (width < 768) return 'mobile';\n if (width < 1024) return 'tablet';\n return 'desktop';\n}\n\nfunction isResolvedPageUrl(value?: string) {\n const trimmed = value?.trim();\n if (!trimmed || /%%[^%]+%%/.test(trimmed)) {\n return false;\n }\n try {\n const parsed = new URL(trimmed);\n return Boolean(parsed.protocol && parsed.hostname);\n } catch {\n return false;\n }\n}\n\nfunction getUsableWindowHref() {\n try {\n const href = window.location.href?.trim();\n if (isResolvedPageUrl(href)) {\n return href;\n }\n } catch {\n return undefined;\n }\n return undefined;\n}\n\nfunction getAssistantPageContext(pageUrlOverride?: string) {\n if (typeof window === 'undefined') {\n return {\n page_url: undefined,\n page_path: undefined,\n article_slug: undefined,\n page_title: undefined,\n referrer: undefined,\n device_type: 'unknown' as const,\n };\n }\n\n const resolvedPageUrl = getUsableWindowHref()\n || (isResolvedPageUrl(pageUrlOverride) ? pageUrlOverride!.trim() : undefined);\n let page_path: string | undefined = resolvedPageUrl ? window.location.pathname || '/' : undefined;\n try {\n page_path = resolvedPageUrl ? new URL(resolvedPageUrl).pathname || '/' : undefined;\n } catch {\n page_path = getUsableWindowHref() ? window.location.pathname || '/' : undefined;\n }\n const segments = (page_path || '').split('/').filter(Boolean);\n\n return {\n page_url: resolvedPageUrl,\n page_path,\n article_slug: segments[segments.length - 1],\n page_title: document.title || undefined,\n referrer: document.referrer || undefined,\n device_type: detectAssistantDeviceType(),\n };\n}\n\nfunction buildSponsoredSuggestionFromRecommendation(recommendation?: PlatformResponse | null): Suggestion | null {\n const suggestionText = recommendation?.recommendation?.creative?.follow_up_suggestion;\n const recommendationId = recommendation?.recommendation_id;\n if (!suggestionText || !recommendationId) {\n return null;\n }\n\n return {\n id: recommendationId,\n text: normalizeSuggestionText(suggestionText),\n type: 'action',\n is_sponsored: true,\n recommendation,\n metadata: {\n source: 'assistant_query_recommendation',\n recommendation_id: recommendationId,\n },\n };\n}\n\nfunction prioritizeSponsoredSuggestions(items: Suggestion[]): Suggestion[] {\n return [...items].sort((left, right) => {\n const leftSponsored = Boolean(left.is_sponsored);\n const rightSponsored = Boolean(right.is_sponsored);\n if (leftSponsored === rightSponsored) {\n return 0;\n }\n return leftSponsored ? -1 : 1;\n });\n}\n\n// Default theme\nconst defaultTheme: AdMeshTheme = {\n mode: 'light',\n primaryColor: '#3b82f6',\n secondaryColor: '#64748b',\n backgroundColor: '#ffffff',\n surfaceColor: '#f8fafc',\n borderColor: '#e2e8f0',\n textColor: '#1e293b',\n textSecondaryColor: '#64748b',\n borderRadius: '0.5rem',\n spacing: {\n small: '0.5rem',\n medium: '1rem',\n large: '1.5rem',\n },\n shadows: {\n small: '0 1px 2px 0 rgb(0 0 0 / 0.05)',\n medium: '0 4px 6px -1px rgb(0 0 0 / 0.1)',\n large: '0 10px 15px -3px rgb(0 0 0 / 0.1)',\n },\n};\n\n// Size configurations\nconst sizeConfig = {\n sm: { width: '320px', height: '400px' },\n md: { width: '400px', height: '500px' },\n lg: { width: '480px', height: '600px' },\n xl: { width: '560px', height: '700px' },\n};\n\n// Position configurations\nconst positionConfig = {\n 'bottom-right': { bottom: '20px', right: '20px' },\n 'bottom-left': { bottom: '20px', left: '20px' },\n 'top-right': { top: '20px', right: '20px' },\n 'top-left': { top: '20px', left: '20px' },\n};\n\n// Main Assistant Component\nexport const AdMeshIntentAssistant: FC<AdMeshIntentAssistantProps> = ({\n theme: propTheme,\n className,\n style,\n triggerLabel = 'Ask Ava',\n headerTitle = 'Ask Ava',\n headerLogoUrl,\n showHeaderTitle = true,\n showSubtitle = true,\n layout = 'floating',\n surface = 'page',\n panelWidth,\n panelHeight,\n analyticsPageUrl,\n fontScale = 1,\n position = 'bottom-right',\n size = 'md',\n // AssistantModal Root props\n defaultOpen,\n open,\n onOpenChange,\n // Behavior props\n autoOpen = false,\n showWelcomeMessage = false,\n welcomeMessage = \"Hi, I’m Ava. I’ll help you find the best options.\",\n placeholder = \"Ask me anything about products...\",\n adsEnabled = true,\n suggestions: propSuggestions, // Renamed to avoid conflict\n maxSuggestions = 6,\n suggestionStyle = 'carousel',\n onlyShowWhenSponsored = false, // New prop to only show modal when sponsored suggestions are available\n variant = 'default',\n queryHandler,\n suggestionsLoader,\n disclaimerText,\n poweredByLabel = 'Powered by AdMesh',\n subtitle = 'Publisher Assistant',\n onOpen,\n onClose,\n}) => {\n // Get AdMesh context\n const { sdk, sessionId, theme: contextTheme, apiKey, userId } = useAdMesh();\n const { \n suggestions: contextSuggestions, \n isAnalyzingIntent, \n intentError,\n retryIntentAnalysis,\n activeDelegationSession,\n hasActiveDelegationSession,\n stopDelegationSession,\n refreshDelegationActivity,\n } = useAdMeshContext();\n useAdMeshStyles();\n \n // Debug: Log context availability\n console.log('[AdMeshIntentAssistant] Context:', { \n sdk:sdk, \n sessionId, \n hasContextTheme: !!contextTheme \n });\n \n // Use prop theme or fallback to context theme or default theme\n const theme = propTheme || contextTheme || defaultTheme;\n const themeMode = theme?.mode || 'light';\n const isAdSlotSurface = surface === 'ad-slot';\n // Use controlled or uncontrolled state based on props\n const [internalOpen, setInternalOpen] = useState(defaultOpen || autoOpen);\n const isControlled = open !== undefined;\n const isOpen = isControlled ? open : internalOpen;\n \n const [inputValue, setInputValue] = useState('');\n type RenderMessage = ChatMessage & {\n sourceLinks?: AssistantSourceLink[];\n relatedItems?: AssistantRelatedItem[];\n initialRecommendation?: PlatformResponse | null;\n responseTimeMs?: number;\n };\n const [messages, setMessages] = useState<RenderMessage[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [isExpanded, setIsExpanded] = useState(false);\n const [sponsoredClickedMessages, setSponsoredClickedMessages] = useState<Set<string>>(new Set());\n const [resolvedSuggestions, setResolvedSuggestions] = useState<Suggestion[]>(propSuggestions || contextSuggestions || []);\n const [loadingLabelIndex, setLoadingLabelIndex] = useState(0);\n const [generationElapsedSec, setGenerationElapsedSec] = useState(0);\n const [messageFeedback, setMessageFeedback] = useState<Record<string, AnswerFeedbackValue>>({});\n const generationStartedAtRef = useRef<number | null>(null);\n const currentMessageIsSponsored = useRef(false);\n const currentSponsoredSuggestionRef = useRef<Suggestion | null>(null);\n const suggestionButtonRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n const suggestionExposureCleanupRef = useRef<Array<() => void>>([]);\n const messagesScrollRef = useRef<HTMLDivElement>(null);\n const activeSubmittedMessageRef = useRef<HTMLDivElement>(null);\n const activeSubmittedMessageIdRef = useRef<string | null>(null);\n const shouldAnchorSubmittedMessageRef = useRef(false);\n const suppressAutoScrollToBottomRef = useRef(false);\n const adSlotRootRef = useRef<HTMLDivElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const suggestionsScrollRef = useRef<HTMLDivElement>(null);\n const generationAbortRef = useRef<AbortController | null>(null);\n const activeAssistantMessageIdRef = useRef<string | null>(null);\n const [canScrollSuggestionsLeft, setCanScrollSuggestionsLeft] = useState(false);\n const [canScrollSuggestionsRight, setCanScrollSuggestionsRight] = useState(false);\n const canUseDirectAdMeshFetch = Boolean(apiKey?.toLowerCase().startsWith('pub_'));\n const connectedDelegationSession =\n hasActiveDelegationSession() && activeDelegationSession?.session_id === sessionId\n ? activeDelegationSession\n : null;\n const trackedSuggestionExposureKeysRef = useRef<Set<string>>(new Set());\n const trackedRecommendationKeysRef = useRef<Set<string>>(new Set());\n const loadedTrackedRef = useRef(false);\n const shouldExpandAdSlot = isAdSlotSurface && (isExpanded || messages.length > 0 || isLoading);\n const adSlotWidthCss = toCssSize(panelWidth) ?? '100%';\n const adSlotHeightCss = toCssSize(panelHeight) ?? '100%';\n\n const setSuggestionButtonRef = useCallback((suggestionId: string) => {\n return (node: HTMLButtonElement | null) => {\n if (node) {\n suggestionButtonRefs.current.set(suggestionId, node);\n } else {\n suggestionButtonRefs.current.delete(suggestionId);\n }\n };\n }, []);\n\n const trackAssistantEvent = useCallback(\n async (\n event_name: PublisherAssistantAnalyticsEvent['event_name'],\n event: Omit<Partial<PublisherAssistantAnalyticsEvent>, 'event_name' | 'timestamp' | 'session_id'> = {},\n ) => {\n if (!sdk || !sessionId) {\n return;\n }\n\n try {\n await sdk.trackPublisherAssistantEvent({\n event_name,\n timestamp: new Date().toISOString(),\n session_id: sessionId,\n ...getAssistantPageContext(analyticsPageUrl),\n ...event,\n });\n } catch (analyticsError) {\n console.warn(`[AdMeshIntentAssistant] Failed to track ${event_name}`, analyticsError);\n }\n },\n [analyticsPageUrl, sdk, sessionId],\n );\n\n const handleRecommendationShown = useCallback(\n (messageId: string, recommendation: PlatformResponse | null, query?: string) => {\n const recommendationId = recommendation?.recommendation_id;\n if (!recommendationId) {\n return;\n }\n const trackKey = `${messageId}:${recommendationId}`;\n if (trackedRecommendationKeysRef.current.has(trackKey)) {\n return;\n }\n trackedRecommendationKeysRef.current.add(trackKey);\n void trackAssistantEvent('recommendation_shown', {\n message_id: messageId,\n query,\n recommendation_id: recommendationId,\n brand_name: recommendation.recommendation?.creative?.brand_name,\n is_sponsored: true,\n });\n },\n [trackAssistantEvent],\n );\n\n const refreshSuggestionsForResponse = useCallback(\n (\n query: string,\n answer: string,\n sourceLinks?: AssistantSourceLink[],\n relatedItems?: AssistantRelatedItem[],\n recommendation?: PlatformResponse | null,\n followupSuggestions?: Array<{ text: string; type?: Suggestion['type'] }>,\n ) => {\n const generated =\n Array.isArray(followupSuggestions) && followupSuggestions.length\n ? followupSuggestions\n .map((item, index) => {\n const normalizedText = normalizeSuggestionText(item.text || '');\n if (!normalizedText) return null;\n return {\n id: `followup_llm_${index}_${normalizedText.toLowerCase().replace(/[^a-z0-9]+/g, '_')}`,\n text: normalizedText,\n type: item.type || 'information',\n is_sponsored: false,\n } satisfies Suggestion;\n })\n .filter((item): item is Suggestion => Boolean(item))\n .slice(0, 3)\n : buildFollowupSuggestionsFromAnswer(query, answer, sourceLinks, relatedItems);\n const sponsoredSuggestion = buildSponsoredSuggestionFromRecommendation(recommendation);\n const nextSuggestions = sponsoredSuggestion\n ? [sponsoredSuggestion, ...generated.slice(0, 2)]\n : generated.slice(0, 3);\n if (nextSuggestions.length) {\n setResolvedSuggestions(prioritizeSponsoredSuggestions(nextSuggestions));\n }\n },\n [],\n );\n\n const upsertSponsoredFollowupSuggestion = useCallback(\n (\n followupSuggestion: {\n query?: string;\n label?: string;\n engagement_url?: string;\n exposure_url?: string;\n },\n recommendationId: string,\n ) => {\n const suggestionText = normalizeSuggestionText(\n followupSuggestion.query || followupSuggestion.label || '',\n );\n if (!suggestionText || !recommendationId) {\n return;\n }\n\n const sponsoredSuggestion: Suggestion = {\n id: recommendationId,\n text: suggestionText,\n type: 'action',\n is_sponsored: true,\n recommendation: {\n recommendation_id: recommendationId,\n recommendation: {\n creative: {\n follow_up_suggestion: suggestionText,\n },\n },\n tracking: {\n followup_engagement_url: followupSuggestion.engagement_url,\n followup_exposure_url: followupSuggestion.exposure_url,\n },\n } as PlatformResponse,\n };\n\n setResolvedSuggestions((current) => {\n const organic = current.filter((item) => !item.is_sponsored).slice(0, 3);\n return prioritizeSponsoredSuggestions([sponsoredSuggestion, ...organic].slice(0, 4));\n });\n },\n [],\n );\n\n const scrollSubmittedMessageToTop = useCallback(() => {\n const scroller = messagesScrollRef.current;\n const activeMessage = activeSubmittedMessageRef.current;\n if (!scroller || !activeMessage) return false;\n\n const scrollerRect = scroller.getBoundingClientRect();\n const activeMessageRect = activeMessage.getBoundingClientRect();\n const targetTop = Math.max(\n 0,\n scroller.scrollTop + activeMessageRect.top - scrollerRect.top,\n );\n\n scroller.scrollTop = targetTop;\n return true;\n }, []);\n\n // New submissions pin the submitted query to the top of the active\n // message panel while the answer streams below it.\n useLayoutEffect(() => {\n if (shouldAnchorSubmittedMessageRef.current) {\n if (scrollSubmittedMessageToTop()) {\n shouldAnchorSubmittedMessageRef.current = false;\n }\n return;\n }\n\n if (suppressAutoScrollToBottomRef.current) return;\n\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, scrollSubmittedMessageToTop]);\n\n useLayoutEffect(() => {\n if (!isAdSlotSurface) return;\n const root = adSlotRootRef.current;\n if (!root) return;\n\n const mountNode = root.closest('.admesh-publisher-assistant-reactMount') as HTMLElement | null;\n const nextHeight = adSlotHeightCss;\n\n [root, mountNode].forEach((node) => {\n if (!node) return;\n node.style.width = adSlotWidthCss;\n node.style.maxWidth = adSlotWidthCss;\n node.style.height = nextHeight;\n node.style.maxHeight = nextHeight;\n node.style.overflow = 'hidden';\n node.style.boxSizing = 'border-box';\n node.dataset.admeshAdSlotExpanded = shouldExpandAdSlot ? 'true' : 'false';\n });\n\n const host = mountNode?.parentElement;\n if (host && host !== document.body && host !== document.documentElement) {\n host.style.width = adSlotWidthCss;\n host.style.maxWidth = adSlotWidthCss;\n host.style.height = nextHeight;\n host.style.maxHeight = nextHeight;\n host.style.overflow = 'hidden';\n host.style.boxSizing = 'border-box';\n }\n }, [adSlotHeightCss, adSlotWidthCss, isAdSlotSurface, shouldExpandAdSlot]);\n\n useEffect(() => {\n if (propSuggestions && propSuggestions.length) {\n setResolvedSuggestions(propSuggestions);\n return;\n }\n if (contextSuggestions && contextSuggestions.length) {\n setResolvedSuggestions((currentSuggestions) =>\n mergeSuggestionsPreservingOrganic(currentSuggestions, contextSuggestions)\n );\n }\n }, [propSuggestions, contextSuggestions]);\n\n useEffect(() => {\n if (variant !== 'default') return;\n\n if (!suggestionsLoader) return;\n let cancelled = false;\n suggestionsLoader()\n .then((items) => {\n if (!cancelled && Array.isArray(items) && items.length) {\n setResolvedSuggestions(items);\n }\n })\n .catch((loadError) => {\n console.warn('[AdMeshIntentAssistant] Failed to load suggestions', loadError);\n });\n return () => {\n cancelled = true;\n };\n }, [suggestionsLoader, variant]);\n\n useEffect(() => {\n if (!isLoading) {\n setGenerationElapsedSec(0);\n generationStartedAtRef.current = null;\n return;\n }\n\n if (generationStartedAtRef.current == null) {\n generationStartedAtRef.current = typeof performance !== 'undefined' ? performance.now() : Date.now();\n }\n\n const tick = () => {\n const startedAt = generationStartedAtRef.current;\n if (startedAt == null) {\n return;\n }\n const now = typeof performance !== 'undefined' ? performance.now() : Date.now();\n setGenerationElapsedSec(Math.floor((now - startedAt) / 1000));\n };\n\n tick();\n const interval = window.setInterval(tick, 1000);\n return () => window.clearInterval(interval);\n }, [isLoading]);\n\n useEffect(() => {\n if (!isLoading || variant !== 'default') {\n setLoadingLabelIndex(0);\n return;\n }\n const interval = window.setInterval(() => {\n setLoadingLabelIndex((prev) => Math.min(prev + 1, 7));\n }, 3000);\n return () => window.clearInterval(interval);\n }, [isLoading, variant]);\n\n useEffect(() => {\n if (loadedTrackedRef.current || !sdk || !sessionId) {\n return;\n }\n loadedTrackedRef.current = true;\n void trackAssistantEvent('assistant_loaded', {\n metadata: {\n layout,\n surface,\n variant,\n default_open: defaultOpen || autoOpen,\n },\n });\n }, [autoOpen, defaultOpen, layout, sdk, sessionId, surface, trackAssistantEvent, variant]);\n\n // Handle open state changes\n const handleOpenChange = useCallback((newOpen: boolean) => {\n if (isControlled) {\n onOpenChange?.(newOpen);\n } else {\n setInternalOpen(newOpen);\n }\n \n if (newOpen) {\n void trackAssistantEvent('assistant_opened', {\n metadata: {\n layout,\n surface,\n variant,\n expanded: isExpanded,\n },\n });\n onOpen?.();\n } else {\n onClose?.();\n }\n }, [isControlled, isExpanded, layout, onOpenChange, onOpen, onClose, surface, trackAssistantEvent, variant]);\n\n // Handle opening/closing\n const handleOpenClick = useCallback(() => {\n handleOpenChange(true);\n }, [handleOpenChange]);\n\n const handleCloseClick = useCallback(() => {\n handleOpenChange(false);\n }, [handleOpenChange]);\n\n const handleToggleExpand = useCallback(() => {\n setIsExpanded(prev => !prev);\n }, []);\n\n // Call backend API for assistant response with streaming using SDK\n const callAssistantAPI = useCallback(async (\n message: string,\n messageId?: string,\n onContentChunk?: (content: string) => void,\n onStreamStart?: () => void,\n sponsoredRecommendation?: PlatformResponse | null,\n signal?: AbortSignal,\n ) => {\n if (!sdk) {\n console.warn('[AdMeshIntentAssistant] SDK not available - using fallback response');\n // Return a fallback response when SDK is not available\n return {\n text: \"I'm a demo assistant. The SDK is not properly configured, but I can still help with suggestions! Try clicking on one of the suggested questions above.\",\n };\n }\n \n try {\n if (connectedDelegationSession) {\n await refreshDelegationActivity('turn_started', {\n source: 'publisher_assistant',\n recommendation_id: connectedDelegationSession.recommendation_id,\n }).catch((activityError) => {\n console.warn('[AdMeshIntentAssistant] Failed to report delegation turn_started', activityError);\n });\n }\n\n // Use SDK to make the chat assistant API call\n const response = await fetch(`${sdk.getApiBaseUrl()}/api/chat/assistant`, {\n method: 'POST',\n signal,\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'text/plain',\n 'Cache-Control': 'no-cache',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n message,\n session_id: sessionId || 'default-session',\n message_id: messageId,\n user_id: userId,\n context: {\n timestamp: new Date().toISOString(),\n source: 'admesh-ui-sdk',\n page_context: getAssistantPageContext(analyticsPageUrl),\n sponsored_recommendation: sponsoredRecommendation?.recommendation_id\n ? {\n recommendation_id: sponsoredRecommendation.recommendation_id,\n brand_name: sponsoredRecommendation.recommendation?.creative?.brand_name,\n }\n : undefined,\n active_delegation_session: connectedDelegationSession\n ? {\n delegation_session_id: connectedDelegationSession.delegation_session_id,\n recommendation_id: connectedDelegationSession.recommendation_id,\n session_id: connectedDelegationSession.session_id,\n brand_name: connectedDelegationSession.brand_name,\n mcp_endpoint: connectedDelegationSession.mcp_endpoint,\n status: connectedDelegationSession.status,\n }\n : undefined,\n }\n }),\n });\n\n if (!response.ok) {\n throw new Error(`API request failed: ${response.status} ${response.statusText}`);\n }\n\n // Handle streaming response\n const reader = response.body?.getReader();\n const decoder = new TextDecoder();\n \n if (!reader) {\n throw new Error('Response body is not readable');\n }\n\n let fullResponse = '';\n let finalSourceLinks: AssistantSourceLink[] | undefined;\n let finalRelatedItems: AssistantRelatedItem[] | undefined;\n let finalFollowupSuggestions: Array<{ text: string; type?: Suggestion['type'] }> | undefined;\n let finalUsedCapability: string | undefined;\n let finalResponseTimeMs: number | undefined;\n \n const processStream = async () => {\n try {\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) break;\n \n const chunk = decoder.decode(value, { stream: true });\n const lines = chunk.split('\\n');\n \n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6); // Remove 'data: ' prefix\n \n if (data.trim() === '[DONE]') {\n if (connectedDelegationSession) {\n void refreshDelegationActivity('turn_completed', {\n source: 'publisher_assistant',\n recommendation_id: connectedDelegationSession.recommendation_id,\n }).catch((activityError) => {\n console.warn('[AdMeshIntentAssistant] Failed to report delegation turn_completed', activityError);\n });\n }\n return {\n text: fullResponse,\n source_links: finalSourceLinks,\n related_items: finalRelatedItems,\n followup_suggestions: finalFollowupSuggestions,\n used_capability: finalUsedCapability,\n response_time_ms: finalResponseTimeMs,\n };\n }\n \n try {\n const parsedData = JSON.parse(data);\n \n switch (parsedData.type) {\n case 'content': {\n const content = parsedData.content || '';\n fullResponse += content;\n onContentChunk?.(content);\n break;\n }\n \n case 'final': {\n fullResponse = parsedData.reply || fullResponse;\n finalSourceLinks = Array.isArray(parsedData.source_links) ? parsedData.source_links : undefined;\n finalRelatedItems = Array.isArray(parsedData.related_items) ? parsedData.related_items : undefined;\n finalFollowupSuggestions = Array.isArray(parsedData.followup_suggestions) ? parsedData.followup_suggestions : undefined;\n finalUsedCapability = typeof parsedData.used_capability === 'string' ? parsedData.used_capability : finalUsedCapability;\n finalResponseTimeMs =\n typeof parsedData.response_time_ms === 'number' ? parsedData.response_time_ms : finalResponseTimeMs;\n break;\n }\n\n case 'followup_suggestions': {\n finalFollowupSuggestions = Array.isArray(parsedData.followup_suggestions)\n ? parsedData.followup_suggestions\n : finalFollowupSuggestions;\n break;\n }\n \n case 'error':\n throw new Error(parsedData.message || 'Unknown streaming error');\n \n case 'session_start':\n onStreamStart?.();\n console.log('Session started:', parsedData.session_id);\n break;\n }\n } catch (parseError) {\n console.warn('Failed to parse streaming chunk:', data);\n continue;\n }\n }\n }\n }\n } catch (error) {\n if (signal?.aborted) {\n return {\n text: fullResponse,\n source_links: finalSourceLinks,\n related_items: finalRelatedItems,\n followup_suggestions: finalFollowupSuggestions,\n used_capability: finalUsedCapability,\n response_time_ms: finalResponseTimeMs,\n error: 'aborted',\n };\n }\n console.error('Stream processing error:', error);\n throw error;\n } finally {\n reader.releaseLock();\n }\n \n return {\n text: fullResponse,\n source_links: finalSourceLinks,\n related_items: finalRelatedItems,\n followup_suggestions: finalFollowupSuggestions,\n used_capability: finalUsedCapability,\n response_time_ms: finalResponseTimeMs,\n };\n };\n \n return await processStream();\n \n } catch (error) {\n if (signal?.aborted) {\n return {\n text: '',\n error: 'aborted',\n };\n }\n console.error('Error calling assistant API:', error);\n // Fallback to basic response if API fails\n return {\n text: \"I'm having trouble connecting to my services right now. Please try again in a moment.\",\n error: error instanceof Error ? error.message : 'request_failed',\n };\n }\n }, [sdk, sessionId, apiKey, userId, connectedDelegationSession, refreshDelegationActivity]);\n\n const handleStopGeneration = useCallback(() => {\n const controller = generationAbortRef.current;\n if (!controller || controller.signal.aborted) return;\n controller.abort();\n setIsLoading(false);\n currentSponsoredSuggestionRef.current = null;\n currentMessageIsSponsored.current = false;\n const activeAssistantMessageId = activeAssistantMessageIdRef.current;\n if (activeAssistantMessageId) {\n setMessages(prev => prev.map(msg =>\n msg.id === activeAssistantMessageId && !msg.content.trim()\n ? { ...msg, content: 'Generation stopped.' }\n : msg\n ));\n }\n }, []);\n\n // Handle message sending with streaming\n const handleSendMessage = useCallback(async (message: string) => {\n if (!message.trim() || isLoading) return;\n const startedAt = typeof performance !== 'undefined' ? performance.now() : Date.now();\n const normalizedMessage = message.trim();\n const userMessageId = Date.now().toString();\n const generationController = new AbortController();\n const activeSponsoredSuggestion = currentSponsoredSuggestionRef.current;\n const activeSponsoredRecommendation = activeSponsoredSuggestion?.recommendation || null;\n\n generationAbortRef.current = generationController;\n activeAssistantMessageIdRef.current = null;\n activeSubmittedMessageIdRef.current = userMessageId;\n shouldAnchorSubmittedMessageRef.current = true;\n suppressAutoScrollToBottomRef.current = true;\n currentSponsoredSuggestionRef.current = null;\n setResolvedSuggestions((current) => current.some((suggestion) => suggestion.is_sponsored)\n ? current.filter((suggestion) => !suggestion.is_sponsored)\n : current\n );\n\n // Clear any previous errors\n setError(null);\n\n const userMessage: ChatMessage = {\n id: userMessageId,\n role: 'user',\n content: normalizedMessage,\n timestamp: new Date(),\n };\n\n void trackAssistantEvent('query_submitted', {\n message_id: userMessageId,\n query: normalizedMessage,\n });\n\n setMessages(prev => [...prev, userMessage]);\n setInputValue('');\n setIsLoading(true);\n\n if (variant === 'default' && queryHandler) {\n try {\n const assistantMessageId = (Date.now() + 1).toString();\n const initialAssistantMessage: RenderMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n recommendations: [],\n userQuery: message,\n initialRecommendation: null,\n };\n\n if (currentMessageIsSponsored.current) {\n setSponsoredClickedMessages(prev => new Set([...prev, assistantMessageId]));\n currentMessageIsSponsored.current = false;\n }\n\n setMessages(prev => [...prev, initialAssistantMessage]);\n activeAssistantMessageIdRef.current = assistantMessageId;\n\n const response = await queryHandler(normalizedMessage, {\n sponsoredSuggestion: activeSponsoredSuggestion,\n });\n if (generationController.signal.aborted) {\n currentSponsoredSuggestionRef.current = null;\n return;\n }\n const recommendation =\n response.recommendation ||\n activeSponsoredRecommendation ||\n null;\n\n console.log('[AdMeshIntentAssistant] Query handler completed:', {\n query: message,\n hasResponseRecommendation: !!response.recommendation,\n hasSponsoredSuggestionRecommendation: !!activeSponsoredRecommendation,\n finalRecommendationId: recommendation?.recommendation_id,\n });\n\n setMessages(prev => prev.map(msg =>\n msg.id === assistantMessageId\n ? {\n ...msg,\n content: response.answer,\n sourceLinks: response.source_links,\n relatedItems: response.related_items,\n initialRecommendation: recommendation,\n responseTimeMs:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n }\n : msg\n ));\n refreshSuggestionsForResponse(\n normalizedMessage,\n response.answer,\n response.source_links,\n response.related_items,\n response.recommendation || null,\n response.followup_suggestions,\n );\n void trackAssistantEvent('answer_completed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: recommendation?.recommendation_id,\n brand_name: recommendation?.recommendation?.creative?.brand_name,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: 'completed',\n metadata: {\n variant,\n source: 'query_handler',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n } catch (queryError) {\n console.error('Error sending message:', queryError);\n const errorMessage = queryError instanceof Error ? queryError.message : 'Unknown error occurred';\n setError(errorMessage);\n const errorResponse: RenderMessage = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: 'Sorry, I encountered an error. Please try again.',\n timestamp: new Date(),\n };\n setMessages(prev => [...prev, errorResponse]);\n void trackAssistantEvent('answer_failed', {\n query: normalizedMessage,\n status: errorMessage,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n metadata: {\n variant,\n source: 'query_handler',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n } finally {\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n setIsLoading(false);\n }\n }\n return;\n }\n\n // If SDK is not available, still show a response for demo purposes\n if (!sdk) {\n // Simulate a brief loading delay for better UX\n setTimeout(() => {\n if (generationController.signal.aborted) {\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n }\n return;\n }\n const assistantMessage: ChatMessage = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: \"I'm a demo assistant. The SDK is not properly configured, but I can still help! Try clicking on the suggested questions above, or check your AdMesh API key configuration.\",\n timestamp: new Date(),\n recommendations: [],\n userQuery: message,\n };\n\n setMessages(prev => [...prev, assistantMessage]);\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n setIsLoading(false);\n }\n }, 1000);\n return;\n }\n\n try {\n // Create an initial assistant message for streaming\n const assistantMessageId = (Date.now() + 1).toString();\n const sponsoredRecommendationForMessage = activeSponsoredRecommendation;\n const initialAssistantMessage: RenderMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n recommendations: [],\n userQuery: message,\n initialRecommendation: sponsoredRecommendationForMessage,\n };\n\n // If this message was triggered by a sponsored suggestion, track it to prevent duplicate recommendations\n if (currentMessageIsSponsored.current) {\n setSponsoredClickedMessages(prev => new Set([...prev, assistantMessageId]));\n currentMessageIsSponsored.current = false; // Reset the flag\n }\n\n setMessages(prev => [...prev, initialAssistantMessage]);\n activeAssistantMessageIdRef.current = assistantMessageId;\n\n // Call the streaming backend API\n const response = await callAssistantAPI(\n normalizedMessage,\n userMessageId,\n // Callback for real-time content updates\n (contentChunk: string) => {\n setMessages(prev => prev.map(msg => \n msg.id === assistantMessageId \n ? { ...msg, content: msg.content + contentChunk }\n : msg\n ));\n },\n () => {\n setIsLoading(true);\n setLoadingLabelIndex(0);\n },\n sponsoredRecommendationForMessage,\n generationController.signal,\n );\n if (generationController.signal.aborted) {\n if (!response.text.trim()) {\n setMessages(prev => prev.map(msg =>\n msg.id === assistantMessageId && !msg.content.trim()\n ? { ...msg, content: 'Generation stopped.' }\n : msg\n ));\n }\n void trackAssistantEvent('answer_failed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: sponsoredRecommendationForMessage?.recommendation_id,\n brand_name: sponsoredRecommendationForMessage?.recommendation?.creative?.brand_name,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: 'aborted',\n metadata: {\n variant,\n source: 'api_chat_assistant',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n return;\n }\n \n // Final update with complete response\n const resolvedResponseTimeMs =\n typeof response.response_time_ms === 'number'\n ? response.response_time_ms\n : (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt;\n\n setMessages(prev => prev.map(msg => \n msg.id === assistantMessageId \n ? {\n ...msg,\n content: response.text,\n sourceLinks: response.source_links,\n relatedItems: response.related_items,\n initialRecommendation: msg.initialRecommendation || sponsoredRecommendationForMessage,\n responseTimeMs: resolvedResponseTimeMs,\n }\n : msg\n ));\n refreshSuggestionsForResponse(\n normalizedMessage,\n response.text,\n response.source_links,\n response.related_items,\n null,\n response.followup_suggestions,\n );\n if (response.error) {\n void trackAssistantEvent('answer_failed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: sponsoredRecommendationForMessage?.recommendation_id,\n brand_name: sponsoredRecommendationForMessage?.recommendation?.creative?.brand_name,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: response.error,\n metadata: {\n variant,\n source: 'api_chat_assistant',\n },\n });\n } else {\n void trackAssistantEvent('answer_completed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: sponsoredRecommendationForMessage?.recommendation_id,\n brand_name: sponsoredRecommendationForMessage?.recommendation?.creative?.brand_name,\n used_capability: response.used_capability,\n latency_ms: resolvedResponseTimeMs,\n status: 'completed',\n metadata: {\n variant,\n source: 'api_chat_assistant',\n response_time_ms: resolvedResponseTimeMs,\n },\n });\n }\n currentSponsoredSuggestionRef.current = null;\n \n } catch (error) {\n console.error('Error sending message:', error);\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n setError(errorMessage);\n \n const errorResponse: ChatMessage = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: 'Sorry, I encountered an error. Please try again.',\n timestamp: new Date(),\n };\n setMessages(prev => [...prev, errorResponse]);\n void trackAssistantEvent('answer_failed', {\n query: normalizedMessage,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: errorMessage,\n metadata: {\n variant,\n source: 'api_chat_assistant',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n } finally {\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n setIsLoading(false);\n }\n }\n }, [isLoading, callAssistantAPI, queryHandler, refreshSuggestionsForResponse, sdk, trackAssistantEvent, variant]);\n\n // Use prop suggestions or fallback to context suggestions\n const suggestions = resolvedSuggestions;\n\n // Check if we have any sponsored suggestions (for onlyShowWhenSponsored logic)\n const hasSponsoredSuggestions = useMemo(\n () => suggestions.some(s => s?.is_sponsored),\n [suggestions]\n );\n\n // Filter suggestions based on the onlyShowWhenSponsored option\n const safeSuggestions = useMemo(\n () => suggestions.filter(\n (suggestion): suggestion is Suggestion => {\n const isValid = Boolean(suggestion && typeof suggestion.id === 'string');\n if (!isValid) return false;\n\n // If onlyShowWhenSponsored is true, only show suggestions if we have at least one sponsored\n if (onlyShowWhenSponsored) {\n // Return all valid suggestions, but only if we have at least one sponsored\n return hasSponsoredSuggestions;\n }\n\n // Otherwise, include all valid suggestions\n return true;\n }\n ),\n [hasSponsoredSuggestions, onlyShowWhenSponsored, suggestions]\n );\n const orderedSuggestions = useMemo(\n () => prioritizeSponsoredSuggestions(safeSuggestions),\n [safeSuggestions]\n );\n\n // Handle suggestion click\n const handleSuggestionClick = useCallback(async (suggestion: Suggestion) => {\n console.log('[AdMeshIntentAssistant] 🖱️ Suggestion clicked:', {\n text: suggestion.text,\n is_sponsored: suggestion.is_sponsored,\n hasRecommendation: !!suggestion.recommendation,\n recommendationId: suggestion.recommendation?.recommendation_id || undefined,\n hasFollowupEngagementUrl: !!suggestion.recommendation?.tracking?.followup_engagement_url,\n sessionId: sessionId\n });\n\n // Set sponsored flag for the next message immediately\n currentMessageIsSponsored.current = suggestion.is_sponsored || false;\n currentSponsoredSuggestionRef.current = suggestion.is_sponsored ? suggestion : null;\n const suggestionPosition = orderedSuggestions.findIndex((item) => item.id === suggestion.id);\n void trackAssistantEvent('suggestion_clicked', {\n suggestion_id: suggestion.id,\n suggestion_text: suggestion.text,\n suggestion_type: suggestion.type,\n suggestion_position: suggestionPosition >= 0 ? suggestionPosition : undefined,\n is_sponsored: suggestion.is_sponsored,\n recommendation_id: suggestion.recommendation?.recommendation_id,\n brand_name: suggestion.recommendation?.recommendation?.creative?.brand_name,\n query: suggestion.text,\n });\n \n // Send the message immediately for instant response\n handleSendMessage(suggestion.text);\n \n // Fire engagement URL for sponsored suggestions asynchronously (non-blocking)\n if (suggestion.is_sponsored && suggestion.recommendation && sdk) {\n // Use setTimeout to make this non-blocking\n setTimeout(async () => {\n try {\n const followupEngagementUrl = suggestion.recommendation!.tracking?.followup_engagement_url;\n const recommendationId = suggestion.recommendation!.recommendation_id;\n \n console.log('[AdMeshIntentAssistant] 🎯 Preparing to fire sponsored suggestion engagement:', {\n followupEngagementUrl,\n recommendationId,\n sessionId\n });\n \n if (followupEngagementUrl && recommendationId && sessionId) {\n console.log('[AdMeshIntentAssistant] 🎯 Firing sponsored suggestion engagement tracking');\n await sdk.fireFollowupEngagement(followupEngagementUrl, recommendationId, sessionId);\n console.log('[AdMeshIntentAssistant] ✅ Engagement tracking fired successfully');\n \n } else {\n console.warn('[AdMeshIntentAssistant] ⚠️ Missing required data for engagement tracking:', {\n hasFollowupEngagementUrl: !!followupEngagementUrl,\n hasRecommendationId: !!recommendationId,\n hasSessionId: !!sessionId\n });\n }\n } catch (error) {\n console.error('[AdMeshIntentAssistant] ❌ Error firing sponsored suggestion engagement:', error);\n // Don't block the user action if engagement tracking fails\n }\n }, 0); // Use setTimeout(0) to make it async but execute immediately\n } else {\n console.log('[AdMeshIntentAssistant] ℹ️ Not a sponsored suggestion or missing data, skipping engagement tracking');\n }\n }, [handleSendMessage, orderedSuggestions, sdk, sessionId, trackAssistantEvent]);\n\n // Position and size styles\n const positionStyle = positionConfig[position];\n const sizeStyle = sizeConfig[size];\n\n // Track suggestion exposure only after the suggestion is actually viewable.\n useEffect(() => {\n suggestionExposureCleanupRef.current.forEach((cleanup) => cleanup());\n suggestionExposureCleanupRef.current = [];\n\n if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') {\n return;\n }\n\n orderedSuggestions.forEach((suggestion, index) => {\n const element = suggestionButtonRefs.current.get(suggestion.id);\n if (!element) {\n return;\n }\n\n const exposureKey = `${sessionId || 'anonymous'}:${suggestion.id}:${suggestion.is_sponsored ? 's' : 'o'}`;\n if (trackedSuggestionExposureKeysRef.current.has(exposureKey)) {\n return;\n }\n\n let viewableTimer: ReturnType<typeof setTimeout> | null = null;\n let observer: IntersectionObserver | null = null;\n\n const cleanup = () => {\n if (viewableTimer) {\n clearTimeout(viewableTimer);\n viewableTimer = null;\n }\n observer?.disconnect();\n observer = null;\n };\n\n const fireSuggestionExposure = () => {\n if (trackedSuggestionExposureKeysRef.current.has(exposureKey)) {\n cleanup();\n return;\n }\n\n trackedSuggestionExposureKeysRef.current.add(exposureKey);\n cleanup();\n\n void trackAssistantEvent('suggestion_exposure', {\n suggestion_id: suggestion.id,\n suggestion_text: suggestion.text,\n suggestion_type: suggestion.type,\n suggestion_position: index,\n is_sponsored: suggestion.is_sponsored,\n recommendation_id: suggestion.recommendation?.recommendation_id,\n brand_name: suggestion.recommendation?.recommendation?.creative?.brand_name,\n });\n\n if (sdk && sessionId && suggestion.is_sponsored && suggestion.recommendation) {\n const exposureUrl = suggestion.recommendation.tracking?.followup_exposure_url;\n const recommendationId = suggestion.recommendation.recommendation_id;\n\n if (exposureUrl && recommendationId) {\n console.log('[AdMeshIntentAssistant] 🎯 Firing viewable sponsored suggestion exposure:', {\n exposureUrl,\n recommendationId,\n suggestionText: suggestion.text,\n sessionId\n });\n\n sdk.fireFollowupExposure(exposureUrl, recommendationId, sessionId);\n } else {\n console.warn('[AdMeshIntentAssistant] ⚠️ Missing exposure URL or recommendation ID for sponsored suggestion:', {\n hasExposureUrl: !!exposureUrl,\n hasRecommendationId: !!recommendationId,\n suggestionText: suggestion.text\n });\n }\n }\n };\n\n observer = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (!entry) {\n return;\n }\n\n if (entry.intersectionRatio >= 0.5) {\n if (!viewableTimer) {\n viewableTimer = setTimeout(fireSuggestionExposure, 1000);\n }\n return;\n }\n\n if (viewableTimer) {\n clearTimeout(viewableTimer);\n viewableTimer = null;\n }\n },\n { threshold: [0, 0.25, 0.5, 0.75, 1], rootMargin: '0px' }\n );\n\n observer.observe(element);\n suggestionExposureCleanupRef.current.push(cleanup);\n });\n\n return () => {\n suggestionExposureCleanupRef.current.forEach((cleanup) => cleanup());\n suggestionExposureCleanupRef.current = [];\n };\n }, [orderedSuggestions, sdk, sessionId, trackAssistantEvent]);\n\n // Debug log received suggestions and analysis state\n console.log('[AdMeshIntentAssistant] 📥 Received suggestions:', {\n totalSuggestions: suggestions.length,\n safeSuggestions: safeSuggestions.length,\n isAnalyzingIntent,\n hasIntentError: !!intentError,\n onlyShowWhenSponsored,\n hasSponsoredSuggestions,\n sponsoredCount: suggestions.filter(s => s?.is_sponsored).length,\n nonSponsoredCount: suggestions.filter(s => s && !s?.is_sponsored).length,\n modalShouldAppear: onlyShowWhenSponsored ? hasSponsoredSuggestions : true,\n suggestions: suggestions.map(s => ({\n id: s?.id,\n text: s?.text,\n type: s?.type,\n is_sponsored: s?.is_sponsored,\n hasRecommendation: !!s?.recommendation,\n recommendationId: s?.recommendation?.recommendation_id || undefined,\n hasFollowupEngagementUrl: !!s?.recommendation?.tracking?.followup_engagement_url\n })),\n renderedSuggestions: orderedSuggestions.map(s => ({\n id: s?.id,\n text: s?.text,\n type: s?.type,\n is_sponsored: s?.is_sponsored,\n hasRecommendation: !!s?.recommendation,\n recommendationId: s?.recommendation?.recommendation_id || undefined,\n hasFollowupEngagementUrl: !!s?.recommendation?.tracking?.followup_engagement_url\n }))\n });\n const fontSizes = {\n base: `${16 * fontScale}px`,\n sm: `${14 * fontScale}px`,\n xs: `${12 * fontScale}px`,\n };\n const genericDisclaimer = disclaimerText || 'AI-generated responses may contain errors. Please verify important information independently.';\n const loadingSteps = [\n 'Searching trusted sources...',\n 'Reviewing publisher coverage...',\n 'Checking relevant context...',\n 'Comparing supporting signals...',\n 'Identifying the strongest examples...',\n 'Organizing the most useful details...',\n 'Shaping the response for clarity...',\n 'Preparing the clearest answer...',\n 'Finishing the response...',\n ];\n\n const renderGeneratingIndicator = (options?: {\n compact?: boolean;\n accentColor?: string;\n metaColor?: string;\n includeSteps?: boolean;\n }) => {\n const accent = options?.accentColor || publisherAccent;\n const meta = options?.metaColor || publisherMeta;\n const includeSteps = options?.includeSteps ?? variant === 'default';\n const timerLabel = `${generationElapsedSec}s`;\n const statusLabel = includeSteps\n ? `${loadingSteps[loadingLabelIndex]} (${timerLabel})`\n : `Generating answer... ${timerLabel}`;\n\n return (\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: options?.compact ? '8px' : '10px',\n color: meta,\n fontSize: options?.compact ? fontSizes.xs : fontSizes.sm,\n }}\n >\n <span\n style={{\n width: options?.compact ? 8 : 9,\n height: options?.compact ? 8 : 9,\n borderRadius: 999,\n background: accent,\n animation: 'admeshPulse 1.4s ease-in-out infinite',\n boxShadow: `0 0 0 0 ${withAlpha(brandPrimary, 0.28)}`,\n flexShrink: 0,\n }}\n />\n <span>{statusLabel}</span>\n </div>\n );\n };\n\n const handleAnswerFeedback = useCallback(\n (message: RenderMessage, helpful: boolean) => {\n if (messageFeedback[message.id]) {\n return;\n }\n\n const feedbackValue: AnswerFeedbackValue = helpful ? 'helpful' : 'not_helpful';\n setMessageFeedback((prev) => ({ ...prev, [message.id]: feedbackValue }));\n void trackAssistantEvent('answer_feedback', {\n message_id: message.id,\n query: message.userQuery,\n status: feedbackValue,\n latency_ms: message.responseTimeMs,\n metadata: {\n helpful,\n },\n });\n },\n [messageFeedback, trackAssistantEvent],\n );\n\n function renderAnswerFooter(message: RenderMessage, options?: { accentColor?: string; metaColor?: string }) {\n if (message.role !== 'assistant' || !message.content.trim()) {\n return null;\n }\n\n if (isLoading && message.id === activeAssistantMessageIdRef.current) {\n return null;\n }\n\n const accent = options?.accentColor || publisherAccent;\n const meta = options?.metaColor || publisherMeta;\n const selectedFeedback = messageFeedback[message.id];\n const hasTiming = typeof message.responseTimeMs === 'number';\n\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n marginTop: '10px',\n paddingTop: '10px',\n borderTop: `1px solid ${withAlpha(brandPrimary, 0.08)}`,\n flexWrap: 'nowrap',\n }}\n >\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n minWidth: 0,\n flex: '1 1 auto',\n }}\n >\n <span style={{ fontSize: fontSizes.xs, color: meta, whiteSpace: 'nowrap' }}>\n {selectedFeedback ? 'Thanks for your feedback' : 'Is this helpful?'}\n </span>\n {!selectedFeedback ? (\n <div style={{ display: 'inline-flex', alignItems: 'center', gap: '6px', flexShrink: 0 }}>\n <button\n type=\"button\"\n aria-label=\"Mark answer as helpful\"\n onClick={() => handleAnswerFeedback(message, true)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandPrimary, 0.12)}`,\n background: '#ffffff',\n color: meta,\n cursor: 'pointer',\n }}\n >\n <ThumbsUp size={14} />\n </button>\n <button\n type=\"button\"\n aria-label=\"Mark answer as not helpful\"\n onClick={() => handleAnswerFeedback(message, false)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandPrimary, 0.12)}`,\n background: '#ffffff',\n color: meta,\n cursor: 'pointer',\n }}\n >\n <ThumbsDown size={14} />\n </button>\n </div>\n ) : (\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n borderRadius: 999,\n background: withAlpha(accent, 0.12),\n color: accent,\n flexShrink: 0,\n }}\n >\n {selectedFeedback === 'helpful' ? <ThumbsUp size={14} /> : <ThumbsDown size={14} />}\n </span>\n )}\n </div>\n {hasTiming ? (\n <span\n style={{\n fontSize: fontSizes.xs,\n color: meta,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n marginLeft: 'auto',\n }}\n >\n Answer Completed in {formatGenerationDurationFromMs(message.responseTimeMs!)}\n </span>\n ) : null}\n </div>\n );\n }\n\n const updateSuggestionScrollState = useCallback(() => {\n const node = suggestionsScrollRef.current;\n if (!node) return;\n const maxScrollLeft = Math.max(0, node.scrollWidth - node.clientWidth);\n setCanScrollSuggestionsLeft(node.scrollLeft > 4);\n setCanScrollSuggestionsRight(node.scrollLeft < maxScrollLeft - 4);\n }, []);\n\n useEffect(() => {\n updateSuggestionScrollState();\n window.addEventListener('resize', updateSuggestionScrollState);\n return () => window.removeEventListener('resize', updateSuggestionScrollState);\n }, [updateSuggestionScrollState, orderedSuggestions.length]);\n\n const scrollSuggestions = useCallback((direction: 'left' | 'right') => {\n const node = suggestionsScrollRef.current;\n if (!node) return;\n node.scrollBy({\n left: direction === 'left' ? -Math.max(160, Math.floor(node.clientWidth * 0.75)) : Math.max(160, Math.floor(node.clientWidth * 0.75)),\n behavior: 'smooth',\n });\n }, []);\n\n const withAlpha = (hex: string | undefined, alpha: number) => {\n if (!hex || !hex.startsWith('#')) return `rgba(15, 23, 42, ${alpha})`;\n const raw = hex.slice(1);\n const full = raw.length === 3 ? raw.split('').map((char) => `${char}${char}`).join('') : raw;\n if (full.length !== 6) return hex;\n const red = parseInt(full.slice(0, 2), 16);\n const green = parseInt(full.slice(2, 4), 16);\n const blue = parseInt(full.slice(4, 6), 16);\n return `rgba(${red}, ${green}, ${blue}, ${alpha})`;\n };\n\n const brandPrimary = theme.primaryColor || '#3F037F';\n const brandSurface = theme.surfaceColor || '#ffffff';\n const brandBackground = theme.backgroundColor || '#eef2ff';\n const brandBorder = theme.borderColor || '#e5e7eb';\n const brandText = theme.textColor || '#111827';\n const brandMuted = theme.textSecondaryColor || '#6b7280';\n const brandAccentSoft = withAlpha(brandPrimary, 0.12);\n const purpleBorderSoft = withAlpha(brandPrimary, 0.24);\n const purpleBorderStrong = withAlpha(brandPrimary, 0.38);\n const purpleShadowSoft = withAlpha(brandPrimary, 0.12);\n const publisherPanelWidth = isAdSlotSurface ? adSlotWidthCss : isExpanded ? 'min(960px, calc(100vw - 24px))' : layout === 'inline' ? '100%' : 'min(420px, calc(100vw - 32px))';\n const publisherPanelHeight = isAdSlotSurface ? adSlotHeightCss : isExpanded ? 'min(78vh, 760px)' : 'auto';\n const publisherPanelMaxWidth = isAdSlotSurface ? adSlotWidthCss : '100%';\n const publisherPanelMaxHeight = isAdSlotSurface ? adSlotHeightCss : undefined;\n const publisherMessageFontSize = isAdSlotSurface ? '13px' : '16.25px';\n const publisherSurfaceBg = `linear-gradient(180deg, ${withAlpha(brandPrimary, 0.04)} 0%, ${withAlpha(brandPrimary, 0.08)} 100%)`;\n const publisherAccent = brandPrimary;\n const publisherMuted = brandMuted;\n const publisherMeta = brandMuted;\n const assistantSubtitle = subtitle || 'Publisher Assistant';\n const shouldShowSuggestionSkeletons = isAnalyzingIntent && orderedSuggestions.length === 0 && messages.length === 0;\n const expandedShellBackground = '#f7f8fc';\n const expandedPanelBackground = '#ffffff';\n const expandedHeaderBackground = 'linear-gradient(180deg, rgba(255,255,255,0.96) 0%, rgba(248,250,252,0.98) 100%)';\n const expandedBorder = 'rgba(15, 23, 42, 0.08)';\n const expandedBorderStrong = 'rgba(15, 23, 42, 0.12)';\n const expandedShadow = '0 24px 60px rgba(15, 23, 42, 0.16)';\n const expandedMutedText = '#667085';\n const expandedSubtleText = '#98a2b3';\n const expandedUserBubble = publisherAccent;\n const expandedAssistantBubble = '#f8fafc';\n const expandedChipBackground = '#f8fafc';\n const expandedChipBorder = 'rgba(15, 23, 42, 0.08)';\n const expandedComposerBackground = '#ffffff';\n const expandedComposerShadow = '0 8px 24px rgba(15, 23, 42, 0.08)';\n const expandedOverlay = 'rgba(15, 23, 42, 0.18)';\n\n function renderDelegationBanner(mode: 'default' | 'legacy') {\n if (!connectedDelegationSession) {\n return null;\n }\n\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n padding: mode === 'default' ? '10px 12px' : '8px 10px',\n borderRadius: mode === 'default' ? '14px' : '12px',\n border: `1px solid ${purpleBorderSoft}`,\n background: withAlpha('#ffffff', 0.9),\n marginBottom: '4px',\n }}\n >\n <div style={{ minWidth: 0 }}>\n <div\n style={{\n color: publisherAccent,\n fontSize: fontSizes.xs,\n fontWeight: 700,\n textTransform: 'uppercase',\n letterSpacing: '0.06em',\n }}\n >\n Agent Connected\n </div>\n <div style={{ color: brandText, fontSize: fontSizes.sm, fontWeight: 600, lineHeight: 1.3 }}>\n {connectedDelegationSession.brand_name} agent is active\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => {\n void stopDelegationSession('user_stopped', { source: 'publisher_assistant' });\n }}\n style={{\n border: `1px solid ${purpleBorderSoft}`,\n borderRadius: 999,\n background: withAlpha('#ffffff', 0.92),\n color: publisherAccent,\n padding: '7px 12px',\n fontSize: fontSizes.xs,\n fontWeight: 700,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n }}\n >\n Stop\n </button>\n </div>\n );\n }\n\n function renderExpandedBranding(mode: 'default' | 'legacy') {\n const compact = isAdSlotSurface;\n\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: compact ? 'column' : 'row',\n alignItems: compact ? 'center' : mode === 'default' ? 'center' : 'flex-start',\n justifyContent: compact ? 'center' : 'space-between',\n gap: compact ? '2px' : '12px',\n flexWrap: 'wrap',\n paddingTop: compact ? '2px' : mode === 'default' ? '2px' : '8px',\n borderTop: mode === 'default' ? `1px solid ${expandedBorder}` : 'none',\n marginTop: compact ? '0' : mode === 'default' ? '4px' : 0,\n flexShrink: 0,\n }}\n >\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: compact ? '4px' : '8px',\n color: expandedSubtleText,\n fontSize: compact ? '9.5px' : '11px',\n fontWeight: 700,\n letterSpacing: '0.01em',\n }}\n >\n <span>\n Powered by{' '}\n <a\n href=\"https://useadmesh.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit', textDecoration: 'none', fontWeight: 700 }}\n >\n AdMesh\n </a>\n </span>\n </div>\n <div\n style={{\n color: expandedSubtleText,\n fontSize: compact ? '9px' : '11px',\n lineHeight: compact ? 1.25 : 1.45,\n maxWidth: compact ? '100%' : mode === 'default' ? '68%' : '100%',\n textAlign: compact ? 'center' : mode === 'default' ? 'right' : 'left',\n }}\n >\n {genericDisclaimer}\n </div>\n </div>\n );\n }\n\n function renderSuggestionSkeletons(mode: 'publisher' | 'legacy') {\n const skeletonWidths = mode === 'publisher' ? [180, 220, 196] : ['100%', '82%', '68%'];\n if (mode === 'publisher') {\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div\n style={{\n width: 28,\n height: 28,\n borderRadius: 999,\n background: withAlpha(brandPrimary, 0.10),\n flexShrink: 0,\n }}\n />\n <div\n style={{\n display: 'flex',\n gap: '10px',\n overflow: 'hidden',\n flex: 1,\n }}\n >\n {skeletonWidths.map((width, index) => (\n <div\n key={`suggestion-skeleton-${index}`}\n style={{\n width,\n maxWidth: '100%',\n height: 40,\n borderRadius: 999,\n background: `linear-gradient(90deg, ${withAlpha(brandPrimary, 0.08)} 0%, ${withAlpha(brandPrimary, 0.18)} 50%, ${withAlpha(brandPrimary, 0.08)} 100%)`,\n backgroundSize: '200% 100%',\n animation: 'admeshShimmer 1.4s ease-in-out infinite',\n boxShadow: `0 8px 22px ${withAlpha(brandPrimary, 0.08)}`,\n flexShrink: 0,\n }}\n />\n ))}\n </div>\n <div\n style={{\n width: 28,\n height: 28,\n borderRadius: 999,\n background: withAlpha(brandPrimary, 0.10),\n flexShrink: 0,\n }}\n />\n </div>\n );\n }\n\n return (\n <div\n aria-hidden=\"true\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: mode === 'publisher' ? '10px' : '12px',\n }}\n >\n {skeletonWidths.map((width, index) => (\n <div\n key={`suggestion-skeleton-${index}`}\n style={{\n width,\n maxWidth: '100%',\n height: mode === 'publisher' ? 40 : 52,\n borderRadius: 999,\n background: `linear-gradient(90deg, ${withAlpha(brandPrimary, 0.08)} 0%, ${withAlpha(brandPrimary, 0.18)} 50%, ${withAlpha(brandPrimary, 0.08)} 100%)`,\n backgroundSize: '200% 100%',\n animation: 'admeshShimmer 1.4s ease-in-out infinite',\n boxShadow: mode === 'publisher' ? `0 8px 22px ${withAlpha(brandPrimary, 0.08)}` : 'none',\n }}\n />\n ))}\n </div>\n );\n }\n\n function renderPublisherSuggestions() {\n if (isLoading) return null;\n if (shouldShowSuggestionSkeletons) {\n return renderSuggestionSkeletons('publisher');\n }\n if (!orderedSuggestions.length) return null;\n const visibleSuggestions = orderedSuggestions.slice(0, maxSuggestions);\n if (suggestionStyle === 'stacked') {\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: isAdSlotSurface ? '6px' : '8px',\n flexShrink: 0,\n overflowY: 'auto',\n maxHeight: isAdSlotSurface ? '240px' : undefined,\n paddingRight: isAdSlotSurface ? '2px' : 0,\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n }}\n >\n {visibleSuggestions.map((suggestion) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => {\n if (variant === 'default') {\n setIsExpanded(true);\n if (layout === 'floating') {\n handleOpenChange(true);\n }\n }\n handleSuggestionClick(suggestion);\n }}\n type=\"button\"\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n width: '100%',\n minWidth: 0,\n borderRadius: isAdSlotSurface ? '12px' : '14px',\n border: suggestion.is_sponsored\n ? `1px solid ${withAlpha(brandPrimary, 0.32)}`\n : `1px solid ${withAlpha(brandPrimary, 0.42)}`,\n background: suggestion.is_sponsored ? brandPrimary : withAlpha('#ffffff', 0.94),\n color: suggestion.is_sponsored ? '#ffffff' : brandText,\n padding: isAdSlotSurface ? '8px 10px' : '10px 14px',\n fontSize: isAdSlotSurface ? '12px' : '13px',\n fontWeight: 500,\n lineHeight: 1.25,\n textAlign: 'left',\n boxShadow: suggestion.is_sponsored\n ? `0 8px 18px ${withAlpha(brandPrimary, 0.14)}`\n : '0 4px 12px rgba(15, 23, 42, 0.05)',\n cursor: 'pointer',\n }}\n >\n <span style={{ minWidth: 0 }}>{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <span\n style={{\n flexShrink: 0,\n borderRadius: 999,\n background: withAlpha('#ffffff', 0.18),\n padding: '2px 6px',\n fontSize: '10px',\n fontWeight: 700,\n }}\n >\n Ad\n </span>\n )}\n </button>\n ))}\n </div>\n );\n }\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: isAdSlotSurface ? '6px' : '10px', flexShrink: 0 }}>\n <button\n type=\"button\"\n onClick={() => scrollSuggestions('left')}\n disabled={!canScrollSuggestionsLeft}\n aria-label=\"Scroll suggestions left\"\n style={{\n width: isAdSlotSurface ? 24 : 28,\n height: isAdSlotSurface ? 24 : 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandBorder, 0.8)}`,\n background: withAlpha('#ffffff', 0.9),\n color: '#6b7280',\n cursor: canScrollSuggestionsLeft ? 'pointer' : 'default',\n opacity: canScrollSuggestionsLeft ? 1 : 0.55,\n }}\n >\n ‹\n </button>\n <div\n ref={suggestionsScrollRef}\n onScroll={updateSuggestionScrollState}\n style={{\n display: 'flex',\n gap: isAdSlotSurface ? '6px' : '10px',\n overflowX: 'auto',\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n flex: 1,\n }}\n >\n {visibleSuggestions.map((suggestion) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => {\n if (variant === 'default') {\n setIsExpanded(true);\n if (layout === 'floating') {\n handleOpenChange(true);\n }\n }\n handleSuggestionClick(suggestion);\n }}\n type=\"button\"\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n whiteSpace: 'nowrap',\n borderRadius: 999,\n border: suggestion.is_sponsored\n ? `1px solid ${withAlpha(brandPrimary, 0.32)}`\n : `1px solid ${withAlpha(brandPrimary, 0.42)}`,\n background: suggestion.is_sponsored ? brandPrimary : withAlpha('#ffffff', 0.94),\n color: suggestion.is_sponsored ? '#ffffff' : brandText,\n padding: isAdSlotSurface ? '7px 10px' : '8px 14px',\n fontSize: isAdSlotSurface ? '12px' : '13px',\n fontWeight: 500,\n boxShadow: suggestion.is_sponsored\n ? `0 8px 18px ${withAlpha(brandPrimary, 0.14)}`\n : '0 4px 12px rgba(15, 23, 42, 0.05)',\n cursor: 'pointer',\n }}\n >\n <span>{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <sup style={{ fontSize: '10px', opacity: 0.9 }}>Ad</sup>\n )}\n </button>\n ))}\n </div>\n <button\n type=\"button\"\n onClick={() => scrollSuggestions('right')}\n disabled={!canScrollSuggestionsRight}\n aria-label=\"Scroll suggestions right\"\n style={{\n width: isAdSlotSurface ? 24 : 28,\n height: isAdSlotSurface ? 24 : 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandBorder, 0.8)}`,\n background: withAlpha('#ffffff', 0.9),\n color: '#6b7280',\n cursor: canScrollSuggestionsRight ? 'pointer' : 'default',\n opacity: canScrollSuggestionsRight ? 1 : 0.55,\n }}\n >\n ›\n </button>\n </div>\n );\n }\n\n function renderSourceLinks(message: RenderMessage) {\n if (message.relatedItems?.length) return null;\n if (!message.sourceLinks?.length) return null;\n return (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '12px' }}>\n {message.sourceLinks.map((link) => (\n <a\n key={`${message.id}-${link.url}`}\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={() => {\n void trackAssistantEvent('source_link_clicked', {\n message_id: message.id,\n query: message.userQuery,\n metadata: {\n source_title: link.title,\n source_url: link.url,\n },\n });\n }}\n style={{\n color: publisherAccent,\n fontSize: fontSizes.xs,\n textDecoration: 'none',\n borderBottom: `1px solid ${withAlpha(brandPrimary, 0.18)}`,\n }}\n >\n {link.title || link.url}\n </a>\n ))}\n </div>\n );\n }\n\n function renderRelatedItems(message: RenderMessage) {\n if (!message.relatedItems?.length) return null;\n return (\n <div style={{ marginTop: '14px' }}>\n <div style={{ fontSize: fontSizes.xs, fontWeight: 700, color: '#4b5563', marginBottom: '8px' }}>Related</div>\n <div\n style={{\n display: 'flex',\n gap: isAdSlotSurface ? '8px' : '10px',\n overflowX: 'auto',\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n padding: '2px 2px 6px',\n maxWidth: '100%',\n scrollSnapType: 'x proximity',\n }}\n >\n {message.relatedItems.slice(0, 4).map((item) => (\n <a\n key={`${message.id}-${item.url}`}\n href={item.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={() => {\n void trackAssistantEvent('source_link_clicked', {\n message_id: message.id,\n query: message.userQuery,\n metadata: {\n source_title: item.title,\n source_url: item.url,\n source_publisher: item.publisher,\n source_type: 'related_item',\n },\n });\n }}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: isAdSlotSurface ? '6px' : '10px',\n padding: isAdSlotSurface ? '10px' : '14px',\n borderRadius: isAdSlotSurface ? '12px' : '14px',\n textDecoration: 'none',\n color: brandText,\n border: `1px solid ${withAlpha(brandPrimary, 0.18)}`,\n background: '#ffffff',\n boxShadow: '0 10px 24px rgba(15, 23, 42, 0.08)',\n flex: isAdSlotSurface\n ? '0 0 min(220px, calc(100% - 8px))'\n : '0 0 min(250px, calc(100% - 16px))',\n minWidth: 0,\n maxWidth: isAdSlotSurface ? '220px' : '250px',\n flexShrink: 0,\n scrollSnapAlign: 'start',\n boxSizing: 'border-box',\n }}\n >\n <div\n style={{\n fontSize: isAdSlotSurface ? '13px' : '18px',\n fontWeight: 650,\n lineHeight: 1.35,\n color: brandPrimary,\n overflowWrap: 'anywhere',\n }}\n >\n {item.title || item.url}\n </div>\n {item.publisher && (\n <div\n style={{\n fontSize: isAdSlotSurface ? '11px' : '15px',\n color: '#6b7280',\n lineHeight: 1.4,\n overflowWrap: 'anywhere',\n }}\n >\n {item.publisher}\n </div>\n )}\n </a>\n ))}\n </div>\n </div>\n );\n }\n\n function renderPublisherMessages() {\n return (\n <div\n ref={messagesScrollRef}\n style={{\n flex: isAdSlotSurface ? '1 1 0' : 1,\n minHeight: 0,\n maxHeight: '100%',\n overflowY: 'auto',\n overscrollBehavior: isAdSlotSurface ? 'contain' : undefined,\n WebkitOverflowScrolling: 'touch',\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n padding: isAdSlotSurface ? '0 2px 4px' : isExpanded ? '16px 16px 8px' : 0,\n }}\n >\n {messages.map((message) => {\n const isActiveSubmittedMessage =\n message.role === 'user' &&\n message.id === activeSubmittedMessageIdRef.current;\n\n return (\n <div\n key={message.id}\n ref={isActiveSubmittedMessage ? activeSubmittedMessageRef : undefined}\n style={{ marginBottom: '12px', textAlign: message.role === 'user' ? 'right' : 'left' }}\n >\n {(() => {\n const answerHasStarted = Boolean(message.content.trim());\n const shouldShowRecommendations = answerHasStarted || !isLoading;\n\n return (\n <>\n <div\n style={{\n display: message.role === 'assistant' ? 'block' : 'inline-block',\n width: message.role === 'assistant' ? '100%' : undefined,\n maxWidth: message.role === 'assistant' ? '100%' : '76%',\n padding: message.role === 'assistant' ? '4px 6px 4px 2px' : '10px 14px',\n borderRadius: message.role === 'assistant' ? 0 : '18px',\n background: message.role === 'user' ? publisherAccent : 'transparent',\n color: message.role === 'user' ? '#ffffff' : brandText,\n boxShadow: 'none',\n border: 'none',\n fontSize: message.role === 'assistant' ? publisherMessageFontSize : isAdSlotSurface ? '12px' : '13px',\n lineHeight: message.role === 'assistant' ? 1.62 : 1.4,\n }}\n >\n {message.role === 'assistant' ? (\n message.content.trim() ? (\n <CustomMarkdownRenderer content={message.content} theme={{ ...theme, textColor: brandText }} fontSize={publisherMessageFontSize} />\n ) : isLoading && message.id === activeAssistantMessageIdRef.current ? (\n renderGeneratingIndicator({ includeSteps: true })\n ) : null\n ) : (\n <p style={{ margin: 0 }}>{message.content}</p>\n )}\n {message.role === 'assistant' && renderSourceLinks(message)}\n {message.role === 'assistant' && renderRelatedItems(message)}\n {message.role === 'assistant' && renderAnswerFooter(message)}\n {message.role === 'assistant' && shouldShowRecommendations && sponsoredClickedMessages.has(message.id) && message.initialRecommendation && (\n <div style={{ marginTop: '14px' }}>\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n initialRecommendation={message.initialRecommendation}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(recommendationError) => {\n console.error('[AdMeshIntentAssistant] Recommendation error:', recommendationError);\n }}\n />\n </div>\n )}\n {message.role === 'assistant' && shouldShowRecommendations && !sponsoredClickedMessages.has(message.id) && (message.initialRecommendation || canUseDirectAdMeshFetch) && (\n <div style={{ marginTop: '14px' }}>\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n initialRecommendation={message.initialRecommendation || undefined}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(recommendationError) => {\n console.error('[AdMeshIntentAssistant] Recommendation error:', recommendationError);\n }}\n />\n </div>\n )}\n </div>\n </>\n );\n })()}\n </div>\n );\n })}\n\n {error && (\n <div style={{ color: publisherMeta, fontSize: fontSizes.sm }}>Connection issue. Please try again.</div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n );\n }\n\n if (variant === 'default') {\n const teaser = (\n <div\n style={{\n width: publisherPanelWidth,\n maxWidth: publisherPanelMaxWidth,\n height: publisherPanelHeight,\n maxHeight: publisherPanelMaxHeight,\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n background: isExpanded ? expandedShellBackground : publisherSurfaceBg,\n borderRadius: isAdSlotSurface ? '12px' : isExpanded ? '18px' : '20px',\n padding: isExpanded ? 0 : isAdSlotSurface ? '8px' : '12px',\n boxShadow: isExpanded ? expandedShadow : 'none',\n border: isExpanded ? `1px solid ${expandedBorderStrong}` : 'none',\n overflow: 'hidden',\n minHeight: isAdSlotSurface ? 0 : undefined,\n }}\n >\n {(isExpanded || isAdSlotSurface) && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: isAdSlotSurface ? '10px 12px' : '16px 18px',\n background: isExpanded ? expandedHeaderBackground : '#ffffff29',\n color: brandText,\n borderBottom: `1px solid ${expandedBorder}`,\n flexShrink: 0,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>\n <div\n style={{\n width: isAdSlotSurface ? 30 : 40,\n height: isAdSlotSurface ? 30 : 40,\n borderRadius: isAdSlotSurface ? '10px' : '14px',\n background: withAlpha(brandPrimary, 0.08),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 16,\n fontWeight: 700,\n color: publisherAccent,\n overflow: 'hidden',\n }}\n >\n {headerLogoUrl ? (\n <img src={headerLogoUrl} alt={`${headerTitle || 'Assistant'} logo`} style={{ width: '100%', height: '100%', objectFit: 'contain', background: '#ffffff', padding: 4 }} />\n ) : (\n (headerTitle || 'AA').slice(0, 2).toUpperCase()\n )}\n </div>\n {(showHeaderTitle || showSubtitle) && (\n <div>\n {showHeaderTitle && <div style={{ fontSize: isAdSlotSurface ? '14px' : '20px', fontWeight: 700, lineHeight: 1.1, letterSpacing: 0 }}>{headerTitle}</div>}\n {showSubtitle && <div style={{ fontSize: isAdSlotSurface ? '10px' : '12px', color: expandedMutedText, marginTop: '2px' }}>{assistantSubtitle}</div>}\n </div>\n )}\n </div>\n {!isAdSlotSurface && (\n <button\n type=\"button\"\n onClick={() => setIsExpanded(false)}\n aria-label=\"Minimize assistant\"\n style={{\n width: 36,\n height: 36,\n borderRadius: '12px',\n border: `1px solid ${expandedBorder}`,\n background: '#ffffff',\n color: expandedMutedText,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <span style={{ fontSize: '18px', lineHeight: 1, fontWeight: 700, transform: 'translateY(-1px)' }}>-</span>\n </button>\n )}\n </div>\n )}\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: isAdSlotSurface ? '6px' : '16px',\n minHeight: 0,\n flex: isAdSlotSurface ? '1 1 0' : undefined,\n overflow: isAdSlotSurface ? 'hidden' : undefined,\n padding: isAdSlotSurface ? '8px 10px 6px' : isExpanded ? '18px' : '14px',\n background: isExpanded ? expandedShellBackground : withAlpha('#ffffff', 0.16),\n height: isAdSlotSurface ? undefined : isExpanded ? publisherPanelHeight : 'auto',\n }}\n >\n {renderDelegationBanner('default')}\n {isExpanded && renderPublisherMessages()}\n {isAdSlotSurface && !isExpanded && <div aria-hidden=\"true\" style={{ flex: '1 1 auto', minHeight: 0 }} />}\n {isAdSlotSurface && !isExpanded && showWelcomeMessage && messages.length === 0 && (\n <div\n style={{\n color: brandText,\n fontSize: '15px',\n lineHeight: 1.3,\n fontWeight: 700,\n letterSpacing: 0,\n padding: '2px 2px 0',\n textAlign: 'center',\n }}\n >\n {welcomeMessage}\n </div>\n )}\n {renderPublisherSuggestions()}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n borderRadius: isAdSlotSurface ? '12px' : '16px',\n background: expandedComposerBackground,\n padding: isAdSlotSurface ? '6px 6px 6px 10px' : '8px 8px 8px 14px',\n boxShadow: isExpanded ? expandedComposerShadow : `0 8px 22px ${purpleShadowSoft}`,\n border: `1px solid ${isExpanded ? expandedBorder : purpleBorderSoft}`,\n flexShrink: 0,\n }}\n >\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyPress={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n if (isLoading) return;\n currentSponsoredSuggestionRef.current = null;\n currentMessageIsSponsored.current = false;\n setIsExpanded(true);\n if (layout === 'floating') handleOpenChange(true);\n handleSendMessage(inputValue);\n }\n }}\n placeholder={placeholder}\n style={{\n flex: 1,\n border: 'none',\n outline: 'none',\n borderRadius: '12px',\n padding: isAdSlotSurface ? '8px 2px' : '10px 4px',\n color: brandText,\n fontSize: isAdSlotSurface ? '13px' : '15px',\n background: 'transparent',\n }}\n />\n <button\n type=\"button\"\n onClick={() => {\n if (isLoading) {\n handleStopGeneration();\n return;\n }\n currentSponsoredSuggestionRef.current = null;\n currentMessageIsSponsored.current = false;\n setIsExpanded(true);\n if (layout === 'floating') handleOpenChange(true);\n handleSendMessage(inputValue);\n }}\n disabled={!isLoading && !inputValue.trim()}\n style={{\n border: 'none',\n borderRadius: '12px',\n background: isLoading ? '#dc2626' : publisherAccent,\n color: '#ffffff',\n minWidth: isAdSlotSurface ? '40px' : '48px',\n height: isAdSlotSurface ? '36px' : '44px',\n padding: isAdSlotSurface ? '0 10px' : '0 16px',\n fontSize: isAdSlotSurface ? '12px' : '14px',\n fontWeight: 700,\n cursor: !isLoading && !inputValue.trim() ? 'default' : 'pointer',\n opacity: !isLoading && !inputValue.trim() ? 0.6 : 1,\n boxShadow: `0 10px 20px ${isLoading ? 'rgba(220, 38, 38, 0.18)' : withAlpha(brandPrimary, 0.18)}`,\n }}\n >\n {isLoading ? 'Stop' : 'Send'}\n </button>\n </div>\n {isExpanded && renderExpandedBranding('default')}\n {!isExpanded && (\n <div style={{ textAlign: 'center', paddingTop: '2px' }}>\n <div style={{ color: publisherMeta, fontSize: isAdSlotSurface ? '9.5px' : fontSizes.xs, fontWeight: 600 }}>\n Powered by{' '}\n <a\n href=\"https://useadmesh.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit', textDecoration: 'none', fontWeight: 700 }}\n >\n AdMesh\n </a>\n </div>\n <div style={{ color: publisherMeta, fontSize: isAdSlotSurface ? '9px' : fontSizes.xs, lineHeight: isAdSlotSurface ? 1.25 : 1.5 }}>{genericDisclaimer}</div>\n </div>\n )}\n </div>\n </div>\n );\n\n if (layout === 'inline') {\n if (isAdSlotSurface) {\n return (\n <div\n ref={adSlotRootRef}\n className=\"admesh-component\"\n data-admesh-theme={themeMode}\n data-admesh-surface=\"ad-slot\"\n data-admesh-ad-slot-expanded={shouldExpandAdSlot ? 'true' : 'false'}\n style={{\n width: adSlotWidthCss,\n height: adSlotHeightCss,\n maxWidth: adSlotWidthCss,\n maxHeight: adSlotHeightCss,\n position: 'relative',\n overflow: 'hidden',\n }}\n >\n {teaser}\n </div>\n );\n }\n\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode} style={{ width: '100%', position: 'relative' }}>\n {teaser}\n {isExpanded && (\n <div\n onClick={() => setIsExpanded(false)}\n style={{\n position: 'fixed',\n inset: 0,\n background: expandedOverlay,\n backdropFilter: 'blur(6px)',\n zIndex: 2147483000,\n }}\n />\n )}\n {isExpanded && (\n <div\n style={{\n position: 'fixed',\n left: '50%',\n bottom: '12px',\n transform: 'translateX(-50%)',\n width: 'min(960px, calc(100vw - 24px))',\n zIndex: 2147483001,\n }}\n >\n {teaser}\n </div>\n )}\n </div>\n );\n }\n\n if (!isOpen) {\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <button\n type=\"button\"\n onClick={handleOpenClick}\n style={{\n position: 'fixed',\n ...positionStyle,\n zIndex: 2147483000,\n border: 'none',\n borderRadius: 999,\n background: theme.primaryColor,\n color: '#ffffff',\n padding: '14px 18px',\n boxShadow: '0 18px 40px rgba(15, 23, 42, 0.18)',\n cursor: 'pointer',\n }}\n >\n {triggerLabel}\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n {isExpanded && (\n <div\n onClick={() => setIsExpanded(false)}\n style={{\n position: 'fixed',\n inset: 0,\n background: expandedOverlay,\n backdropFilter: 'blur(6px)',\n zIndex: 2147483000,\n }}\n />\n )}\n <div\n style={{\n position: 'fixed',\n ...(isExpanded ? { left: '50%', bottom: '12px', transform: 'translateX(-50%)' } : positionStyle),\n zIndex: 2147483001,\n }}\n >\n {teaser}\n </div>\n </div>\n );\n }\n\n // Conditional rendering: only show if we have suggestions\n if (orderedSuggestions.length === 0 && !shouldShowSuggestionSkeletons) {\n console.log('[AdMeshIntentAssistant] No suggestions available - not rendering');\n return null;\n }\n\n if (layout === 'inline') {\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <div\n className={`overflow-hidden rounded-[2rem] ${className || ''}`}\n style={{\n width: toCssSize(panelWidth) ?? '100%',\n backgroundColor: '#eef2ff',\n fontSize: fontSizes.base,\n ...style,\n }}\n >\n <div\n className=\"space-y-4 rounded-[1.75rem] p-4\"\n style={{ backgroundColor: 'rgba(255, 255, 255, 0.35)' }}\n >\n {shouldShowSuggestionSkeletons ? (\n renderSuggestionSkeletons('legacy')\n ) : orderedSuggestions.length > 0 && (\n <div className=\"flex flex-col gap-3\">\n {orderedSuggestions.slice(0, maxSuggestions).map((suggestion, index) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => handleSuggestionClick(suggestion)}\n className=\"rounded-full px-5 py-4 text-left shadow-sm transition-transform duration-200 hover:scale-[1.01] active:scale-[0.99]\"\n style={{\n width: index === 0 ? '100%' : index === 1 ? '82%' : '68%',\n backgroundColor: theme.surfaceColor || '#ffffff',\n color: theme.textColor || '#1e293b',\n border: `1px solid ${theme.borderColor || '#e2e8f0'}`,\n fontSize: fontSizes.sm,\n }}\n >\n <span className=\"leading-tight\">{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <sup\n className=\"ml-1 rounded-full px-1.5 py-0.5\"\n style={{\n backgroundColor: theme.backgroundColor || '#ffffff',\n color: theme.textSecondaryColor || '#64748b',\n fontSize: '9px',\n lineHeight: 1,\n }}\n >\n Ad\n </sup>\n )}\n </button>\n ))}\n </div>\n )}\n\n {messages.length > 0 && (\n <div\n ref={messagesScrollRef}\n className=\"max-h-[280px] space-y-3 overflow-y-auto rounded-[1.5rem] bg-white/80 p-4\"\n style={{ color: theme.textColor }}\n >\n {messages.map((message) => {\n const isActiveSubmittedMessage =\n message.role === 'user' &&\n message.id === activeSubmittedMessageIdRef.current;\n\n return (\n <div\n key={message.id}\n ref={isActiveSubmittedMessage ? activeSubmittedMessageRef : undefined}\n className={message.role === 'user' ? 'text-right' : 'text-left'}\n >\n <div\n className=\"inline-block max-w-[85%] rounded-2xl px-4 py-3\"\n style={{\n backgroundColor: message.role === 'user' ? theme.primaryColor : '#ffffff',\n color: message.role === 'user' ? '#ffffff' : theme.textColor,\n fontSize: fontSizes.sm,\n }}\n >\n {message.role === 'assistant' ? (\n message.content.trim() ? (\n <>\n <CustomMarkdownRenderer content={message.content} theme={theme} fontSize={fontSizes.sm} />\n {renderAnswerFooter(message, {\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n })}\n </>\n ) : isLoading && message.id === activeAssistantMessageIdRef.current ? (\n renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })\n ) : null\n ) : (\n <p style={{ margin: 0, lineHeight: '1.4' }}>{message.content}</p>\n )}\n </div>\n </div>\n );\n })}\n\n {isLoading && !messages.some(\n (message) =>\n message.role === 'assistant' &&\n message.id === activeAssistantMessageIdRef.current &&\n !message.content.trim(),\n ) && (\n <div className=\"text-sm\" style={{ color: theme.textSecondaryColor }}>\n {renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })}\n </div>\n )}\n\n {error && (\n <div className=\"text-sm\" style={{ color: theme.textSecondaryColor }}>\n Connection issue. Please try again.\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n )}\n\n <div className=\"rounded-[1.5rem] bg-white p-3 shadow-sm\">\n <div className=\"flex items-center gap-3\">\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyPress={(e) => {\n if (e.key !== 'Enter') return;\n if (isLoading) {\n e.preventDefault();\n return;\n }\n handleSendMessage(inputValue);\n }}\n placeholder={placeholder}\n className=\"min-w-0 flex-1 rounded-full px-4 py-3 focus:outline-none\"\n style={{\n backgroundColor: theme.backgroundColor || '#ffffff',\n color: theme.textColor,\n fontSize: fontSizes.sm,\n }}\n />\n <button\n onClick={() => {\n if (isLoading) {\n handleStopGeneration();\n return;\n }\n handleSendMessage(inputValue);\n }}\n disabled={!isLoading && !inputValue.trim()}\n className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-50\"\n style={{\n backgroundColor: isLoading ? '#dc2626' : theme.primaryColor,\n color: '#ffffff',\n }}\n >\n {isLoading ? <XIcon size={18} /> : <SendIcon size={18} />}\n </button>\n </div>\n </div>\n\n <div className=\"space-y-2 text-center\">\n <p style={{ color: theme.textSecondaryColor, fontSize: fontSizes.xs, fontWeight: 600 }}>\n Powered by{' '}\n <a\n href=\"https://useadmesh.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit', textDecoration: 'none', fontWeight: 700 }}\n >\n AdMesh\n </a>\n </p>\n <p style={{ color: theme.textSecondaryColor, fontSize: fontSizes.xs, lineHeight: 1.5 }}>\n {genericDisclaimer}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n if (!isOpen) {\n // Floating button when closed\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <button\n onClick={handleOpenClick}\n className=\"flex items-center gap-2 px-4 py-3 rounded-full shadow-lg transition-all duration-200 hover:scale-105 active:scale-95\"\n style={{\n position: 'fixed',\n ...positionStyle,\n backgroundColor: theme.primaryColor,\n color: '#ffffff',\n zIndex: 9999,\n fontSize: fontSizes.base,\n ...style,\n }}\n >\n {/* {triggerIcon ?? <BotIcon size={20} />} */}\n <span className=\"font-medium\">{triggerLabel}</span>\n </button>\n </div>\n );\n }\n\n // Main assistant interface when open\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <div\n className={`flex flex-col overflow-hidden ${className || ''}`}\n style={{\n position: 'fixed',\n display: 'flex',\n flexDirection: 'column',\n ...(isExpanded ? {\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: 'min(1040px, calc(100vw - 40px))',\n height: 'min(84vh, 820px)',\n maxWidth: '1040px',\n maxHeight: '820px',\n } : {\n ...positionStyle,\n width: toCssSize(panelWidth) ?? sizeStyle.width,\n height: toCssSize(panelHeight) ?? sizeStyle.height,\n }),\n backgroundColor: isExpanded ? expandedShellBackground : theme.backgroundColor,\n zIndex: 9999,\n fontSize: fontSizes.base,\n borderRadius: isExpanded ? '20px' : '16px',\n border: isExpanded ? `1px solid ${expandedBorderStrong}` : '1px solid transparent',\n boxShadow: isExpanded ? expandedShadow : '0 20px 40px rgba(15, 23, 42, 0.12)',\n ...style,\n }}\n >\n {/* Header */}\n <div\n className=\"sticky top-0 z-10 flex items-center justify-between p-4 border-b\"\n style={{ \n position: 'sticky',\n top: 0,\n zIndex: 10,\n borderColor: isExpanded ? expandedBorder : 'transparent',\n background: isExpanded ? expandedHeaderBackground : theme.backgroundColor,\n padding: isExpanded ? '18px 20px' : '16px',\n }}\n >\n <div className=\"flex items-center gap-3\">\n <div\n style={{\n width: isExpanded ? 40 : 32,\n height: isExpanded ? 40 : 32,\n borderRadius: isExpanded ? '14px' : '10px',\n background: withAlpha(brandPrimary, 0.08),\n color: publisherAccent,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: isExpanded ? '15px' : '13px',\n fontWeight: 700,\n flexShrink: 0,\n overflow: 'hidden',\n }}\n >\n {headerLogoUrl ? (\n <img src={headerLogoUrl} alt={`${headerTitle || 'Assistant'} logo`} style={{ width: '100%', height: '100%', objectFit: 'contain', background: '#ffffff', padding: 4 }} />\n ) : (\n (headerTitle || 'AA').slice(0, 2).toUpperCase()\n )}\n </div>\n {(showHeaderTitle || (showSubtitle && isExpanded)) && (\n <div>\n {showHeaderTitle && (\n <div\n className=\"font-medium\"\n style={{ color: theme.textColor, fontSize: isExpanded ? '20px' : fontSizes.base, fontWeight: 700, letterSpacing: isExpanded ? '-0.02em' : 0 }}\n >\n {headerTitle}\n </div>\n )}\n {showSubtitle && isExpanded && (\n <div style={{ color: expandedMutedText, fontSize: '12px', marginTop: '2px' }}>\n {assistantSubtitle}\n </div>\n )}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n {!isAdSlotSurface && (\n <button\n onClick={handleToggleExpand}\n className=\"transition-colors\"\n title={isExpanded ? \"Minimize\" : \"Expand\"}\n style={{\n width: isExpanded ? 36 : 28,\n height: isExpanded ? 36 : 28,\n borderRadius: isExpanded ? '12px' : '10px',\n border: `1px solid ${isExpanded ? expandedBorder : 'transparent'}`,\n background: isExpanded ? '#ffffff' : 'transparent',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {isExpanded ? (\n <Minimize2 size={16} style={{ color: theme.textSecondaryColor }} />\n ) : (\n <Maximize2 size={16} style={{ color: theme.textSecondaryColor }} />\n )}\n </button>\n )}\n <button\n onClick={handleCloseClick}\n className=\"transition-colors\"\n style={{\n width: isExpanded ? 36 : 28,\n height: isExpanded ? 36 : 28,\n borderRadius: isExpanded ? '12px' : '10px',\n border: `1px solid ${isExpanded ? expandedBorder : 'transparent'}`,\n background: isExpanded ? '#ffffff' : 'transparent',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <XIcon size={16} style={{ color: theme.textSecondaryColor }} />\n </button>\n </div>\n </div>\n\n {/* Messages */}\n <div\n ref={messagesScrollRef}\n className=\"flex-1 min-h-0 overflow-y-auto p-4\"\n style={{\n flex: '1 1 0%',\n minHeight: 0,\n overflowY: 'auto',\n padding: isExpanded ? '20px' : '16px',\n }}\n >\n {renderDelegationBanner('legacy')}\n {showWelcomeMessage && messages.length === 0 && (\n <div className=\"mb-3\">\n <div\n className=\"inline-block p-2 rounded-lg\"\n \n >\n <p style={{ color: theme.textColor, margin: 0, fontSize: fontSizes.sm }}>{welcomeMessage}</p>\n </div>\n </div>\n )}\n\n {messages.map((message) => {\n const isActiveSubmittedMessage =\n message.role === 'user' &&\n message.id === activeSubmittedMessageIdRef.current;\n\n return (\n <div\n key={message.id}\n ref={isActiveSubmittedMessage ? activeSubmittedMessageRef : undefined}\n className=\"mb-3\"\n >\n <div\n className={message.role === 'user' ? 'inline-block max-w-[85%] ml-auto' : 'max-w-[92%]'}\n style={{\n backgroundColor: message.role === 'user' ? expandedUserBubble : 'transparent',\n color: message.role === 'user' \n ? '#ffffff' \n : theme.textColor,\n border: 'none',\n borderRadius: message.role === 'user' ? (isExpanded ? '14px' : '12px') : 0,\n padding: message.role === 'user' ? (isExpanded ? '12px 14px' : undefined) : '2px 6px 2px 2px',\n boxShadow: 'none',\n }}\n >\n {message.role === 'assistant' ? (\n message.content.trim() ? (\n <>\n <div style={{ fontSize: `calc(${fontSizes.sm} * 1.3)`, lineHeight: 1.65 }}>\n <CustomMarkdownRenderer \n content={message.content}\n theme={theme}\n fontSize={`calc(${fontSizes.sm} * 1.3)`}\n />\n </div>\n {renderAnswerFooter(message, {\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n })}\n </>\n ) : isLoading && message.id === activeAssistantMessageIdRef.current ? (\n renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })\n ) : null\n ) : (\n <p style={{ margin: 0, fontSize: fontSizes.sm, lineHeight: '1.4' }}>{message.content}</p>\n )}\n </div>\n \n {/* Add recommendations after assistant messages */}\n {message.role === 'assistant' && !sponsoredClickedMessages.has(message.id) && (\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(error) => {\n console.error(`[AdMeshIntentAssistant] Recommendations error:`, error);\n }}\n />\n )}\n \n {/* Display sponsored recommendation after assistant content if available */}\n {message.role === 'assistant' && sponsoredClickedMessages.has(message.id) && message.initialRecommendation && !isLoading && (\n <div className=\"mb-4\">\n <div className=\"text-xs text-gray-500 mb-2 font-semibold\">Sponsored Recommendation</div>\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n initialRecommendation={message.initialRecommendation}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(error) => {\n console.error(`[AdMeshIntentAssistant] Recommendations error:`, error);\n }}\n />\n </div>\n )}\n </div>\n );\n })}\n\n {isLoading && !messages.some(\n (message) =>\n message.role === 'assistant' &&\n message.id === activeAssistantMessageIdRef.current &&\n !message.content.trim(),\n ) && (\n <div className=\"mb-3\">\n <div\n className=\"inline-block p-2 rounded-lg\"\n style={{ backgroundColor: 'transparent' }}\n >\n {renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })}\n </div>\n </div>\n )}\n\n {error && (\n <div className=\"mb-3\">\n <div\n className=\"inline-block p-2 rounded-lg border\"\n style={{ \n backgroundColor: 'transparent',\n borderColor: 'transparent',\n color: theme.textSecondaryColor\n }}\n >\n <div className=\"flex items-center gap-2\">\n <span style={{ fontSize: fontSizes.xs }}>⚠️</span>\n <span style={{ fontSize: fontSizes.sm }}>Connection issue. Please try again.</span>\n </div>\n </div>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n \n\n {/* Suggestions */}\n {messages.length === 0 && shouldShowSuggestionSkeletons && (\n <div className=\"px-4 pb-2\">\n {renderSuggestionSkeletons('legacy')}\n </div>\n )}\n\n {orderedSuggestions.length > 0 && messages.length === 0 && !shouldShowSuggestionSkeletons && (\n <div className=\"px-4 pb-2\">\n <div className=\"flex flex-col gap-2\">\n {orderedSuggestions.slice(0, maxSuggestions).map((suggestion) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => handleSuggestionClick(suggestion)}\n className=\"relative flex w-full items-center text-left transition-all duration-200\"\n style={{\n backgroundColor: theme.surfaceColor || '#f8fafc',\n color: theme.textColor || '#1e293b',\n border: `1px solid ${theme.borderColor || '#e2e8f0'}`,\n fontSize: fontSizes.sm,\n padding: '10px 12px',\n borderRadius: '999px',\n fontWeight: 500,\n }}\n >\n <span className=\"leading-tight\">{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <sup\n className=\"absolute right-1 top-1 rounded-full px-1.5 py-0.5 tracking-wide\"\n style={{\n fontSize: '9px',\n lineHeight: 1,\n backgroundColor: theme.backgroundColor || '#ffffff',\n color: theme.textSecondaryColor || '#64748b'\n }}\n >\n Ad\n </sup>\n )}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Intent Analysis Error */}\n {intentError && !isAnalyzingIntent && safeSuggestions.length === 0 && (\n <div className=\"px-4 pb-2\">\n <div className=\"flex flex-col gap-2\">\n <div className=\"p-3 rounded-lg border\" style={{ \n backgroundColor: theme.surfaceColor,\n borderColor: theme.borderColor,\n color: theme.textSecondaryColor\n }}>\n <div className=\"flex items-center justify-between mb-2\">\n <span style={{ fontSize: fontSizes.sm }}>Intent analysis failed</span>\n <button\n onClick={retryIntentAnalysis}\n className=\"text-xs px-2 py-1 rounded\"\n style={{ \n backgroundColor: theme.primaryColor,\n color: '#ffffff'\n }}\n >\n Retry\n </button>\n </div>\n <span style={{ fontSize: fontSizes.xs }}>{intentError}</span>\n </div>\n </div>\n </div>\n )}\n\n {/* Input */}\n <div className=\"p-3 border-t\" style={{ borderColor: isExpanded ? expandedBorder : 'transparent', padding: isExpanded ? '18px 20px' : undefined, background: isExpanded ? expandedHeaderBackground : undefined }}>\n <div className=\"flex gap-2\" style={{ alignItems: 'center', border: `1px solid ${expandedBorder}`, borderRadius: isExpanded ? '16px' : '12px', background: expandedComposerBackground, boxShadow: isExpanded ? expandedComposerShadow : 'none', padding: isExpanded ? '8px 8px 8px 14px' : undefined }}>\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyPress={(e) => {\n if (e.key !== 'Enter') return;\n if (isLoading) {\n e.preventDefault();\n return;\n }\n handleSendMessage(inputValue);\n }}\n placeholder={placeholder}\n className=\"flex-1 px-3 py-2 rounded-lg border focus:outline-none focus:ring-2\"\n style={{\n backgroundColor: 'transparent',\n borderColor: 'transparent',\n color: theme.textColor,\n fontSize: isExpanded ? '15px' : fontSizes.sm,\n '--tw-ring-color': theme.primaryColor,\n } as CSSProperties}\n />\n <button\n onClick={() => {\n if (isLoading) {\n handleStopGeneration();\n return;\n }\n handleSendMessage(inputValue);\n }}\n disabled={!isLoading && !inputValue.trim()}\n className=\"transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n style={{\n backgroundColor: isLoading ? '#dc2626' : theme.primaryColor,\n color: '#ffffff',\n borderRadius: isExpanded ? '12px' : '10px',\n width: isExpanded ? '46px' : undefined,\n height: isExpanded ? '46px' : undefined,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: isExpanded ? `0 10px 20px ${withAlpha(brandPrimary, 0.18)}` : 'none',\n }}\n >\n {isLoading ? <XIcon size={14} /> : <SendIcon size={14} />}\n </button>\n </div>\n {renderExpandedBranding('legacy')}\n </div>\n </div>\n </div>\n );\n};\n\nexport default AdMeshIntentAssistant;\n","/**\n * Streaming Events Utilities\n * \n * Custom event system for communicating LLM streaming lifecycle events\n * between the chat frontend and AdMesh WeaveAdFormatContainer.\n * \n * This allows WeaveAdFormatContainer to trigger final link detection\n * when streaming completes, rather than using arbitrary timeouts.\n */\n\nimport { logger } from './logger';\n\nexport const STREAMING_START_EVENT = 'admesh:streamingStart';\nexport const STREAMING_COMPLETE_EVENT = 'admesh:streamingComplete';\n\nexport interface StreamingStartEventDetail {\n messageId: string;\n sessionId: string;\n timestamp: number;\n}\n\nexport interface StreamingCompleteEventDetail {\n messageId: string;\n sessionId: string;\n timestamp: number;\n metadata?: {\n hasRecommendations?: boolean;\n recommendationCount?: number;\n };\n}\n\n/**\n * Dispatch a streaming start event\n * \n * Call this when the backend starts streaming the LLM response.\n * This signals to WeaveAdFormatContainer that content is being received.\n * \n * @param messageId - Unique identifier for the message\n * @param sessionId - Session/chat identifier\n */\nexport function dispatchStreamingStartEvent(\n messageId: string,\n sessionId: string\n): void {\n const detail: StreamingStartEventDetail = {\n messageId,\n sessionId,\n timestamp: Date.now(),\n };\n\n const event = new CustomEvent(STREAMING_START_EVENT, { detail });\n window.dispatchEvent(event);\n\n logger.log('[StreamingEvents] 📢 Dispatched streamingStart event', {\n messageId,\n sessionId\n });\n}\n\n/**\n * Dispatch a streaming complete event\n * \n * Call this when the backend finishes streaming the LLM response.\n * This triggers WeaveAdFormatContainer to perform final link detection.\n * \n * @param messageId - Unique identifier for the message\n * @param sessionId - Session/chat identifier\n * @param metadata - Optional metadata about recommendations\n */\nexport function dispatchStreamingCompleteEvent(\n messageId: string,\n sessionId: string,\n metadata?: {\n hasRecommendations?: boolean;\n recommendationCount?: number;\n }\n): void {\n const detail: StreamingCompleteEventDetail = {\n messageId,\n sessionId,\n timestamp: Date.now(),\n metadata,\n };\n\n const event = new CustomEvent(STREAMING_COMPLETE_EVENT, { detail });\n window.dispatchEvent(event);\n\n logger.log('[StreamingEvents] 📢 Dispatched streamingComplete event', {\n messageId,\n sessionId,\n metadata\n });\n}\n\n/**\n * Listen for streaming start events\n * \n * @param messageId - Filter events by this messageId\n * @param sessionId - Filter events by this sessionId\n * @param callback - Called when matching event is received\n * @returns Cleanup function to remove the event listener\n */\nexport function onStreamingStart(\n messageId: string,\n sessionId: string,\n callback: (detail: StreamingStartEventDetail) => void\n): () => void {\n const handler = (event: Event) => {\n const customEvent = event as CustomEvent<StreamingStartEventDetail>;\n \n // Only trigger callback if this is the message we're waiting for\n if (\n customEvent.detail.messageId === messageId &&\n customEvent.detail.sessionId === sessionId\n ) {\n logger.log('[StreamingEvents] 📨 Received streamingStart event');\n callback(customEvent.detail);\n }\n };\n\n window.addEventListener(STREAMING_START_EVENT, handler);\n\n // Return cleanup function\n return () => {\n window.removeEventListener(STREAMING_START_EVENT, handler);\n };\n}\n\n/**\n * Listen for streaming complete events\n * \n * @param messageId - Filter events by this messageId\n * @param sessionId - Filter events by this sessionId\n * @param callback - Called when matching event is received\n * @returns Cleanup function to remove the event listener\n */\nexport function onStreamingComplete(\n messageId: string,\n sessionId: string,\n callback: (detail: StreamingCompleteEventDetail) => void\n): () => void {\n logger.log('[StreamingEvents] 👂 Setting up streamingComplete listener', {\n expectedMessageId: messageId,\n expectedSessionId: sessionId\n });\n\n const handler = (event: Event) => {\n const customEvent = event as CustomEvent<StreamingCompleteEventDetail>;\n \n logger.log('[StreamingEvents] 📨 Received streamingComplete event (checking match)', {\n receivedMessageId: customEvent.detail.messageId,\n receivedSessionId: customEvent.detail.sessionId,\n expectedMessageId: messageId,\n expectedSessionId: sessionId,\n messageIdMatch: customEvent.detail.messageId === messageId,\n sessionIdMatch: customEvent.detail.sessionId === sessionId\n });\n \n // Only trigger callback if this is the message we're waiting for\n if (\n customEvent.detail.messageId === messageId &&\n customEvent.detail.sessionId === sessionId\n ) {\n logger.log('[StreamingEvents] ✅ Event matched! Calling callback');\n callback(customEvent.detail);\n } else {\n logger.log('[StreamingEvents] ⚠️ Event did not match - ignoring');\n }\n };\n\n window.addEventListener(STREAMING_COMPLETE_EVENT, handler);\n\n // Return cleanup function\n return () => {\n logger.log('[StreamingEvents] 🧹 Removing streamingComplete listener');\n window.removeEventListener(STREAMING_COMPLETE_EVENT, handler);\n };\n}\n","import { logger } from './logger';\n\ninterface InlineExposureTrackerState {\n observer: IntersectionObserver;\n timeoutId: ReturnType<typeof setTimeout> | null;\n viewableStart: number | null;\n}\n\nexport interface InlineExposureTrackingParams {\n exposureUrl?: string;\n recommendationId?: string;\n linkElement?: HTMLElement | null;\n sessionId?: string;\n logPrefix?: string;\n}\n\nexport interface InlineExposureTracker {\n startTracking: (params: InlineExposureTrackingParams) => void;\n cleanup: () => void;\n}\n\n/**\n * Creates an inline exposure tracker that fires AdMesh exposure pixels when\n * detected links meet the MRC viewability threshold (50% visible for 1 second).\n */\nexport const createInlineExposureTracker = (): InlineExposureTracker => {\n const firedKeys = new Set<string>();\n const activeTrackers = new Map<string, InlineExposureTrackerState>();\n\n const cleanupTracker = (key: string) => {\n const tracker = activeTrackers.get(key);\n if (!tracker) {\n return;\n }\n tracker.observer.disconnect();\n if (tracker.timeoutId) {\n clearTimeout(tracker.timeoutId);\n }\n activeTrackers.delete(key);\n };\n\n const startTracking = ({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId,\n logPrefix = '[AdMesh Exposure]'\n }: InlineExposureTrackingParams) => {\n if (typeof window === 'undefined') {\n return;\n }\n\n if (!exposureUrl || !linkElement) {\n if (logPrefix) {\n logger.warn(`${logPrefix} ⚠️ Missing exposure tracking data`);\n }\n return;\n }\n\n const dedupeKey = `${sessionId || 'anonymous'}::${recommendationId || exposureUrl}`;\n\n if (firedKeys.has(dedupeKey) || activeTrackers.has(dedupeKey)) {\n return;\n }\n\n const trackerState: InlineExposureTrackerState = {\n observer: undefined as unknown as IntersectionObserver,\n timeoutId: null,\n viewableStart: null\n };\n\n const fireExposurePixel = () => {\n cleanupTracker(dedupeKey);\n firedKeys.add(dedupeKey);\n\n fetch(exposureUrl, { method: 'GET', keepalive: true })\n .then(() => {\n if (logPrefix) {\n logger.log(`${logPrefix} ✅ Exposure pixel fired`);\n }\n })\n .catch(() => {\n if (logPrefix) {\n logger.warn(`${logPrefix} ⚠️ Failed to fire exposure pixel`);\n }\n firedKeys.delete(dedupeKey);\n });\n };\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const visibility = entry.intersectionRatio;\n\n if (visibility >= 0.5) {\n if (trackerState.viewableStart === null) {\n trackerState.viewableStart = performance.now();\n trackerState.timeoutId = setTimeout(fireExposurePixel, 1000);\n }\n } else {\n trackerState.viewableStart = null;\n if (trackerState.timeoutId) {\n clearTimeout(trackerState.timeoutId);\n trackerState.timeoutId = null;\n }\n }\n });\n },\n {\n threshold: [0, 0.25, 0.5, 0.75, 1],\n rootMargin: '0px'\n }\n );\n\n trackerState.observer = observer;\n observer.observe(linkElement as Element);\n activeTrackers.set(dedupeKey, trackerState);\n };\n\n const cleanup = () => {\n Array.from(activeTrackers.keys()).forEach(cleanupTracker);\n };\n\n return {\n startTracking,\n cleanup\n };\n};\n","'use client';\n\nimport React, { useRef, useState, useEffect, useCallback } from 'react';\nimport { useAdMesh } from '../hooks/useAdMesh';\nimport { WeaveFallbackRecommendations } from './WeaveFallbackRecommendations';\nimport { onStreamingComplete } from '../utils/streamingEvents';\nimport {\n createInlineExposureTracker,\n type InlineExposureTrackingParams\n} from '../utils/inlineExposureTracker';\nimport { WeaveResponseProcessor } from '../sdk/WeaveResponseProcessor';\nimport { logger } from '../utils/logger';\nimport type {\n PlatformResponse,\n} from '../types/index';\n\n/**\n * FinalLinkDetectionCheck - Event-driven link detection component\n *\n * This component waits for the 'admesh:streamingComplete' event from ChatWindow\n * before performing final link detection. This eliminates race conditions where\n * timeout-based detection would trigger before streaming completes.\n */\ninterface FinalLinkDetectionCheckProps {\n containerId: string;\n messageId: string;\n sessionId: string;\n sdk: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n query?: string;\n recommendations?: any[]; // eslint-disable-line @typescript-eslint/no-explicit-any\n onLinksFound: (count: number) => void;\n onNoLinksFound: () => void;\n children: React.ReactNode;\n}\n\nconst FinalLinkDetectionCheck: React.FC<FinalLinkDetectionCheckProps> = ({\n containerId,\n messageId,\n sessionId,\n sdk,\n query,\n recommendations = [],\n onLinksFound,\n onNoLinksFound,\n children\n}) => {\n const [checkComplete, setCheckComplete] = useState(false);\n const [waitingForStreamEnd, setWaitingForStreamEnd] = useState(true);\n const [linksFound, setLinksFound] = useState(false);\n const exposureTrackerRef = useRef(createInlineExposureTracker());\n\n // Use refs to avoid recreating the callback on every render\n const onLinksFoundRef = useRef(onLinksFound);\n const onNoLinksFoundRef = useRef(onNoLinksFound);\n const containerIdRef = useRef(containerId);\n const sdkRef = useRef(sdk);\n const sessionIdRef = useRef(sessionId);\n const queryRef = useRef(query);\n\n // Update refs when values change\n useEffect(() => {\n onLinksFoundRef.current = onLinksFound;\n onNoLinksFoundRef.current = onNoLinksFound;\n containerIdRef.current = containerId;\n sdkRef.current = sdk;\n sessionIdRef.current = sessionId;\n queryRef.current = query;\n }, [onLinksFound, onNoLinksFound, containerId, sdk, sessionId, query]);\n\n useEffect(() => {\n return () => {\n exposureTrackerRef.current.cleanup();\n };\n }, []);\n\n const trackExposurePixel = useCallback(\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) => {\n exposureTrackerRef.current.startTracking({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId: sessionIdRef.current,\n logPrefix: '[FinalLinkDetectionCheck]'\n });\n },\n []\n );\n\n const performFinalCheck = useCallback(() => {\n logger.log('[FinalLinkDetectionCheck] 🔍 Performing final link detection...');\n\n try {\n const container = document.getElementById(containerIdRef.current);\n if (!container) {\n logger.warn('[FinalLinkDetectionCheck] ❌ Container not found');\n setCheckComplete(true);\n onNoLinksFound();\n return;\n }\n\n // Create WeaveResponseProcessor instance\n const weaveProcessor = new WeaveResponseProcessor({\n autoAddLabels: true,\n fireExposurePixels: true\n });\n\n // Use fetched recommendations if available, otherwise fall back to pattern-based detection\n const recsToUse = recommendations.length > 0 ? recommendations : [];\n logger.log(`[FinalLinkDetectionCheck] 📋 Using ${recsToUse.length} recommendations for link detection`);\n \n // Development logging: Log recommendation details used for link detection\n if (recsToUse.length > 0 && process.env.NODE_ENV === 'development') {\n recsToUse.forEach((rec, index) => {\n logger.log(`[FinalLinkDetectionCheck] 📋 Recommendation ${index + 1} (DEV):`, {\n recommendation_id: rec?.recommendation_id,\n click_url:\n rec?.tracking?.click_url ||\n rec?.recommendation?.creative?.landing_page_url,\n format: rec?.recommendation?.format,\n brand_name: rec.render?.creative?.advertiser?.brand_name,\n cta_url: rec.render?.creative?.landing_page_url,\n });\n });\n }\n\n // Scan for AdMesh links one final time\n const detectedLinks = weaveProcessor.scanAndProcessLinks(\n container,\n recsToUse, // Use fetched recommendations for brand URL matching\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) =>\n trackExposurePixel({ exposureUrl, recommendationId, linkElement })\n );\n\n logger.log(`[FinalLinkDetectionCheck] 📊 Final check result: ${detectedLinks.length} links`);\n\n if (detectedLinks.length > 0) {\n // Links found! Cancel fallback\n logger.log('[FinalLinkDetectionCheck] ✅ Links detected - canceling fallback (no API call)');\n setLinksFound(true);\n onLinksFoundRef.current(detectedLinks.length);\n } else {\n // No links found, proceed with fallback\n logger.log(`[FinalLinkDetectionCheck] ⚠️ No links found - rendering fallback (will use ${recsToUse.length} previous recommendation(s) if available)`);\n setLinksFound(false);\n onNoLinksFoundRef.current();\n }\n\n setCheckComplete(true);\n } catch (error) {\n logger.error('[FinalLinkDetectionCheck] ❌ Error during final check');\n setCheckComplete(true);\n onNoLinksFoundRef.current();\n }\n }, [trackExposurePixel, recommendations]);\n\n useEffect(() => {\n logger.log('[FinalLinkDetectionCheck] ⏳ Setting up listener', {\n messageId,\n sessionId,\n recommendationsCount: recommendations.length\n });\n\n let timeoutId: NodeJS.Timeout | null = null;\n let eventReceived = false;\n\n // Listen for the streamingComplete event from ChatWindow\n const cleanup = onStreamingComplete(messageId, sessionId, (detail) => {\n logger.log('[FinalLinkDetectionCheck] 🎯 Received streamingComplete event', {\n messageId: detail.messageId,\n sessionId: detail.sessionId,\n timestamp: detail.timestamp\n });\n eventReceived = true;\n \n // Clear timeout since event was received\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n \n setWaitingForStreamEnd(false);\n\n // Small delay to ensure DOM is fully updated\n setTimeout(() => {\n performFinalCheck();\n }, 100);\n });\n\n // Fallback timeout: If streamingComplete doesn't fire within 5 seconds, trigger check anyway\n // This ensures fallback recommendations display even if event system fails\n timeoutId = setTimeout(() => {\n if (!eventReceived) {\n logger.warn('[FinalLinkDetectionCheck] ⏱️ Timeout: streamingComplete event not received, triggering fallback check anyway');\n setWaitingForStreamEnd(false);\n setTimeout(() => {\n performFinalCheck();\n }, 100);\n }\n }, 5000); // 5 second timeout\n\n return () => {\n logger.log('[FinalLinkDetectionCheck] 🧹 Cleaning up listener');\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n cleanup();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messageId, sessionId]); // performFinalCheck depends on recommendations prop, but recommendations should be stable for a given messageId\n\n // Show loading state while waiting for stream to complete\n if (waitingForStreamEnd) {\n return <></>;\n }\n\n // Show checking state while performing final detection\n if (!checkComplete) {\n return <></>;\n }\n\n // Only render children (fallback) if NO links were found\n if (linksFound) {\n logger.log('[FinalLinkDetectionCheck] 🚫 Links found - NOT rendering fallback');\n return <></>;\n }\n\n logger.log('[FinalLinkDetectionCheck] ✅ No links found - rendering fallback');\n return <>{children}</>;\n};\n\nexport interface WeaveAdFormatContainerProps {\n /** Unique ID for this message container */\n messageId: string;\n\n /** The LLM response content (may contain AdMesh links) */\n children: React.ReactNode;\n\n /** Fallback format if no links detected (default: 'tail') */\n fallbackFormat?: 'product' | 'tail';\n\n /** Optional callback when AdMesh links are detected */\n onLinksDetected?: (count: number) => void;\n\n /** Optional callback when no links are detected (fallback should be rendered) */\n onNoLinksDetected?: () => void;\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /** Optional CSS class for the container */\n className?: string;\n\n /** Optional query text for fallback API calls (used when no links are detected) */\n query?: string;\n\n /** Optional callback to notify parent when fallback state changes */\n onFallbackChange?: (shouldFallback: boolean) => void;\n\n /** Optional callback when weave injection is attempted */\n onWeaveAttempt?: (messageId: string) => void;\n\n /** Optional callback when weave injection outcome is determined */\n onWeaveOutcome?: (messageId: string, success: boolean, reason?: string) => void;\n\n /** Optional container ID for follow-up suggestions */\n followups_container_id?: string;\n\n /** Callback to execute query when follow-up is selected (required for follow-up functionality) */\n onExecuteQuery?: (query: string) => void | Promise<void>;\n\n /** Optional callback when a sponsored followup is detected */\n onFollowupDetected?: (\n followupSuggestion: any, // Will be updated to proper type later\n recommendationId: string,\n ) => void;\n\n /** Signal indicating if the followup container is ready in the DOM */\n isContainerReady?: boolean;\n}\n\n/**\n * WeaveAdFormatContainer - Automatic Weave Ad Format handling component\n *\n * Wraps LLM response content and automatically:\n * - Detects AdMesh links in the content\n * - Fires exposure tracking for detected links\n * - Adds Ad labels to links\n * - Shows \"Why this ad?\" tooltip on hover\n * - Provides context for WeaveFallbackRecommendations component\n *\n * @example\n * ```tsx\n * <WeaveAdFormatContainer\n * messageId={message.id}\n * query={userQuery}\n * onLinksDetected={(count) => console.log(`Found ${count} ads`)}\n * >\n * {llmResponseContent}\n * </WeaveAdFormatContainer>\n * ```\n */\nexport const WeaveAdFormatContainer: React.FC<WeaveAdFormatContainerProps> = ({\n messageId,\n children,\n fallbackFormat = 'tail',\n onLinksDetected,\n onNoLinksDetected,\n onError,\n className,\n query,\n onFallbackChange,\n onWeaveAttempt,\n onWeaveOutcome\n}) => {\n const { sessionId, sdk, language, location, userId, model, messages } = useAdMesh();\n const containerRef = useRef<HTMLDivElement>(null);\n const containerId = `weave-ad-container-${messageId}`;\n const exposureTrackerRef = useRef(createInlineExposureTracker());\n const scannedRef = useRef(false);\n const weaveProcessorRef = useRef<WeaveResponseProcessor | null>(null);\n const [recommendations, setRecommendations] = useState<PlatformResponse[]>([]);\n const recommendationsRef = useRef<PlatformResponse[]>([]);\n\n // Initialize WeaveResponseProcessor once\n useEffect(() => {\n if (!weaveProcessorRef.current) {\n weaveProcessorRef.current = new WeaveResponseProcessor({\n autoAddLabels: true,\n fireExposurePixels: true\n });\n }\n return () => {\n if (weaveProcessorRef.current) {\n weaveProcessorRef.current.stopWatching();\n weaveProcessorRef.current.clearCache();\n }\n };\n }, []);\n\n // Cleanup exposure tracker on unmount\n useEffect(() => {\n return () => {\n exposureTrackerRef.current.cleanup();\n };\n }, []);\n\n // Fetch recommendations from SDK cache if available\n useEffect(() => {\n const fetchRecommendations = async () => {\n if (!sdk || !query?.trim() || !messageId) {\n logger.log('[WeaveAdFormatContainer] ⚠️ Missing SDK, query, or messageId - using pattern-based detection');\n return;\n }\n\n try {\n logger.log('[WeaveAdFormatContainer] 📤 Fetching recommendations from SDK for brand URL matching');\n // Use context values (from AdMeshProvider) for canonical AIP PlatformRequest fields\n const platformResponse = await sdk.fetchPlatformResponse({\n query: query.trim(),\n sessionId: sessionId,\n messageId: messageId,\n language: language,\n location: location,\n userId: userId,\n model: model,\n messages: messages,\n });\n const recs = platformResponse?.status === 'generated' ? [platformResponse] : [];\n setRecommendations(recs);\n recommendationsRef.current = recs; // Update ref to avoid dependency issues\n logger.log('[WeaveAdFormatContainer] 📥 Got platform response:', {\n status: platformResponse?.status,\n recommendationId: platformResponse?.recommendation_id,\n hasRecommendation: !!platformResponse?.recommendation,\n format: platformResponse?.recommendation?.format\n });\n \n if (platformResponse?.recommendation) {\n const creative = platformResponse.recommendation.creative;\n const brandUrl = creative.landing_page_url;\n logger.log('[WeaveAdFormatContainer] 🎯 Found creative in platform response:', {\n brandName: creative.brand_name,\n headline: creative.headline,\n description: creative.description,\n brandUrl: brandUrl\n });\n } else {\n logger.log('[WeaveAdFormatContainer] ⚠️ No recommendation found in platform response');\n }\n } catch (error) {\n logger.warn('[WeaveAdFormatContainer] ⚠️ Failed to fetch recommendations, falling back to pattern-based detection:', error);\n setRecommendations([]);\n }\n };\n\n fetchRecommendations();\n }, [sdk, sessionId, messageId, query]);\n\n // Scan for links immediately when container is ready and on children changes\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !weaveProcessorRef.current) {\n return;\n }\n\n const weaveProcessor = weaveProcessorRef.current;\n\n const trackExposurePixel = ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) => {\n exposureTrackerRef.current.startTracking({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId,\n logPrefix: '[WeaveAdFormatContainer]'\n });\n };\n\n // Scan immediately\n const scanLinks = () => {\n // Emit weave attempt signal\n logger.log('[WeaveAdFormatContainer] 🔍 Weave injection attempt started');\n onWeaveAttempt?.(messageId);\n\n // Use fetched recommendations if available, otherwise fall back to pattern-based detection\n // Use ref to avoid triggering re-runs when recommendations change\n const recsToUse = recommendationsRef.current.length > 0 ? recommendationsRef.current : [];\n logger.log(`[WeaveAdFormatContainer] 📋 Using ${recsToUse.length} recommendations for link detection`);\n\n try {\n const detectedLinks = weaveProcessor.scanAndProcessLinks(\n container,\n recsToUse, // Use fetched recommendations for brand URL matching\n trackExposurePixel\n );\n\n if (detectedLinks.length > 0 && !scannedRef.current) {\n scannedRef.current = true;\n logger.log(`[WeaveAdFormatContainer] ✅ Weave injection succeeded: ${detectedLinks.length} links detected`);\n onWeaveOutcome?.(messageId, true, `Found ${detectedLinks.length} links`);\n onLinksDetected?.(detectedLinks.length);\n onFallbackChange?.(false);\n } else if (!scannedRef.current) {\n // No links found on first scan - will be handled by FinalLinkDetectionCheck\n // But we emit the outcome signal here for immediate feedback\n logger.log('[WeaveAdFormatContainer] ⚠️ Weave injection: no links found on initial scan');\n // Don't emit outcome yet - wait for FinalLinkDetectionCheck to confirm\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`[WeaveAdFormatContainer] ❌ Weave injection failed: ${errorMessage}`);\n onWeaveOutcome?.(messageId, false, errorMessage);\n // Immediately trigger fallback on error\n onNoLinksDetected?.();\n onFallbackChange?.(true);\n }\n };\n\n // Initial scan after a small delay to ensure DOM is ready\n const timeoutId = setTimeout(scanLinks, 100);\n\n // Watch for new links (streaming support)\n // Use ref to avoid triggering re-runs when recommendations change\n weaveProcessor.watchForNewLinks(container, recommendationsRef.current, trackExposurePixel);\n\n return () => {\n clearTimeout(timeoutId);\n weaveProcessor.stopWatching();\n };\n }, [children, sessionId, messageId, onLinksDetected, onFallbackChange, onWeaveAttempt, onWeaveOutcome]); // Removed recommendations from deps to prevent infinite loop\n\n const preferredFormat = recommendations[0]?.recommendation?.format;\n const isWeaveFormat = preferredFormat === 'weave';\n\n // Log when format is weave (for debugging)\n useEffect(() => {\n if (query && isWeaveFormat) {\n logger.log(`[WeaveAdFormatContainer] 🎯 Format is \"weave\" (preferred: ${preferredFormat}) - skipping fallback recommendations`);\n }\n }, [query, isWeaveFormat, preferredFormat]);\n\n return (\n <>\n <div\n ref={containerRef}\n id={containerId}\n className={className}\n data-weave-ad-format=\"true\"\n data-message-id={messageId}\n >\n {children}\n </div>\n\n {/* Event-driven link detection and fallback rendering - only show if format is NOT weave */}\n {query && !isWeaveFormat && (\n <FinalLinkDetectionCheck\n containerId={containerId}\n messageId={messageId}\n sessionId={sessionId}\n sdk={sdk}\n query={query}\n recommendations={recommendations}\n onLinksFound={(count) => {\n logger.log(`[WeaveAdFormatContainer] ✅ Links found (${count}) - no fallback needed`);\n // Emit weave outcome success if not already emitted\n onWeaveOutcome?.(messageId, true, `Found ${count} links in final check`);\n onLinksDetected?.(count);\n onFallbackChange?.(false);\n }}\n onNoLinksFound={() => {\n logger.log(`[WeaveAdFormatContainer] ⚠️ No links found - rendering fallback`);\n logger.log(`[WeaveAdFormatContainer] 📋 Passing ${recommendations.length} recommendation(s) to fallback component`);\n // Emit weave outcome failure\n onWeaveOutcome?.(messageId, false, 'No links detected in final check');\n onNoLinksDetected?.();\n onFallbackChange?.(true);\n }}\n >\n <WeaveFallbackRecommendations\n format={fallbackFormat}\n messageId={messageId}\n query={query}\n fallback={true}\n onError={onError}\n previousRecommendations={recommendations.length > 0 ? recommendations : undefined}\n />\n </FinalLinkDetectionCheck>\n )}\n\n {/* Render follow-up portal if follow-up exists */}\n </>\n );\n};\n\nexport default WeaveAdFormatContainer;\n","'use client';\n\nimport { useEffect, useRef, useCallback } from 'react';\nimport { useAdMesh } from './useAdMesh';\nimport {\n createInlineExposureTracker,\n type InlineExposureTrackingParams\n} from '../utils/inlineExposureTracker';\n\nexport interface UseWeaveAdFormatOptions {\n /** Container ID for the LLM output (where AdMesh links will be detected) */\n llmOutputContainerId: string;\n\n /** Timeout for link detection (default: 900ms) */\n timeoutMs?: number;\n\n /** Fallback format if no links detected (default: 'tail') */\n fallbackFormat?: 'product' | 'tail';\n\n /** Optional callback when AdMesh links are detected */\n onLinksDetected?: (count: number) => void;\n\n /** Optional callback when no links are detected (fallback should be rendered) */\n onNoLinksDetected?: () => void;\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /** Optional query for fallback API calls (used when no links are detected) */\n query?: string;\n\n /** Optional message ID for fallback API calls (used when no links are detected) */\n messageId?: string;\n}\n\n/**\n * useWeaveAdFormat - Hook for automatic Weave Ad Format handling\n * \n * Automatically:\n * - Detects AdMesh links in LLM output\n * - Fires exposure tracking for detected links\n * - Adds Ad labels to links\n * - Shows \"Why this ad?\" tooltip on hover\n * - Renders fallback UI if no links detected\n * \n * @example\n * ```tsx\n * const { isProcessing, detectedLinksCount } = useWeaveAdFormat({\n * llmOutputContainerId: 'llm-output-123',\n * timeoutMs: 1500,\n * fallbackFormat: 'tail'\n * });\n * ```\n */\nexport const useWeaveAdFormat = (options: UseWeaveAdFormatOptions) => {\n const { sdk, sessionId } = useAdMesh();\n const processingRef = useRef(false);\n const detectedLinksRef = useRef(0);\n const linksFoundRef = useRef(false);\n const callbackFiredRef = useRef(false);\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);\n const exposureTrackerRef = useRef(createInlineExposureTracker());\n\n useEffect(() => {\n return () => {\n exposureTrackerRef.current.cleanup();\n };\n }, []);\n\n const trackInlineExposure = useCallback(\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) => {\n exposureTrackerRef.current.startTracking({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId,\n logPrefix: '[useWeaveAdFormat]'\n });\n },\n [sessionId]\n );\n\n // Phase 1: Enhanced Mutation Silence Detection\n // Track when last mutation occurred for silence detection\n const lastMutationTimeRef = useRef<number>(Date.now());\n // Count consecutive silence checks (requires 2 for confirmation)\n const mutationSilenceCountRef = useRef<number>(0);\n // Store interval timer for cleanup\n const silenceCheckIntervalRef = useRef<NodeJS.Timeout | null>(null);\n\n // Phase 2: Adaptive Debounce Detection\n // Track timestamps of recent mutations to calculate adaptive timeout\n const mutationTimestampsRef = useRef<number[]>([]);\n // Store the calculated adaptive timeout value\n const adaptiveTimeoutRef = useRef<number>(300); // Default to 300ms\n\n const processWeaveFormat = useCallback(async () => {\n if (!sdk || !sessionId || processingRef.current) {\n return;\n }\n\n processingRef.current = true;\n detectedLinksRef.current = 0;\n\n try {\n const container = document.getElementById(options.llmOutputContainerId);\n if (!container) {\n \n return;\n }\n\n // Get the WeaveResponseProcessor from SDK\n const weaveProcessor = (sdk as any).getWeaveProcessor?.(); // eslint-disable-line @typescript-eslint/no-explicit-any\n if (!weaveProcessor) {\n return;\n }\n\n // Scan and process AdMesh links in the container\n const detectedLinks = weaveProcessor.scanAndProcessLinks(\n container,\n [], // Recommendations will be fetched from SDK cache\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) =>\n trackInlineExposure({ exposureUrl, recommendationId, linkElement })\n );\n\n detectedLinksRef.current = detectedLinks.length;\n const hasLinks = detectedLinks.length > 0;\n\n // Update the flag indicating whether links were found\n if (hasLinks && !linksFoundRef.current) {\n // Links detected (first time or after streaming)\n linksFoundRef.current = true;\n options.onLinksDetected?.(detectedLinks.length);\n callbackFiredRef.current = true;\n } else if (!hasLinks && linksFoundRef.current) {\n // Links were found before but now they're gone (shouldn't happen in normal flow)\n linksFoundRef.current = false;\n callbackFiredRef.current = false;\n } else if (!hasLinks && !callbackFiredRef.current) {\n // No links found and callback hasn't been fired yet\n // Use enhanced mutation silence detection to wait for streaming to complete\n // This prevents firing the callback too early during streaming\n\n // Clear existing debounce timer\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n\n // Clear existing silence check interval\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n }\n\n // Reset silence counter when starting new detection\n mutationSilenceCountRef.current = 0;\n lastMutationTimeRef.current = Date.now();\n\n // Phase 1 + Phase 2: Enhanced Mutation Silence Detection with Adaptive Timeout\n // Check for mutation silence at adaptive intervals\n // Require 2 consecutive silence checks before declaring streaming complete\n const silenceCheckInterval = Math.max(100, adaptiveTimeoutRef.current / 3); // Check 3x per adaptive timeout\n\n silenceCheckIntervalRef.current = setInterval(() => {\n const timeSinceLastMutation = Date.now() - lastMutationTimeRef.current;\n const SILENCE_THRESHOLD = adaptiveTimeoutRef.current; // Use adaptive timeout as silence threshold\n\n if (timeSinceLastMutation >= SILENCE_THRESHOLD) {\n // Mutation silence detected\n mutationSilenceCountRef.current++;\n\n // Require 2 consecutive silence checks for confirmation\n if (mutationSilenceCountRef.current >= 2) {\n // Clear the interval\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n silenceCheckIntervalRef.current = null;\n }\n\n // Fire callback if no links were found\n if (!linksFoundRef.current && !callbackFiredRef.current) {\n options.onNoLinksDetected?.();\n callbackFiredRef.current = true;\n }\n }\n } else {\n // Mutations still happening, reset counter\n mutationSilenceCountRef.current = 0;\n }\n }, silenceCheckInterval);\n\n // Phase 2: Fallback timeout using adaptive timeout\n // Set a maximum timeout to ensure we eventually fire the callback\n // This handles edge cases where mutations might be very infrequent\n const maxFallbackTimeout = Math.max(1500, adaptiveTimeoutRef.current * 5); // At least 1500ms, or 5x adaptive timeout\n\n debounceTimerRef.current = setTimeout(() => {\n // Clear the silence check interval\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n silenceCheckIntervalRef.current = null;\n }\n\n // Fire callback if no links were found\n if (!linksFoundRef.current && !callbackFiredRef.current) {\n options.onNoLinksDetected?.();\n callbackFiredRef.current = true;\n }\n }, maxFallbackTimeout);\n } else if (hasLinks && callbackFiredRef.current && !linksFoundRef.current) {\n // Links detected after we initially said \"no links found\"\n // This happens when links arrive during streaming\n\n\n // Clear debounce timer since we found links\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = null;\n }\n\n linksFoundRef.current = true;\n options.onLinksDetected?.(detectedLinks.length);\n callbackFiredRef.current = true;\n } else {\n \n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n options.onError?.(err);\n } finally {\n processingRef.current = false;\n }\n }, [sdk, sessionId, options, trackInlineExposure]);\n\n // Phase 2: Calculate adaptive debounce timeout based on mutation frequency\n const calculateAdaptiveTimeout = useCallback(() => {\n const timestamps = mutationTimestampsRef.current;\n\n // Need at least 2 timestamps to calculate interval\n if (timestamps.length < 2) {\n adaptiveTimeoutRef.current = 300; // Default to 300ms\n return;\n }\n\n // Calculate intervals between consecutive mutations\n const intervals: number[] = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i] - timestamps[i - 1]);\n }\n\n // Calculate average interval\n const avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n\n // Adaptive timeout: 3x the average interval, min 100ms, max 1000ms\n const adaptiveTimeout = Math.max(100, Math.min(avgInterval * 3, 1000));\n\n adaptiveTimeoutRef.current = adaptiveTimeout;\n }, []);\n\n // Watch for changes in the LLM output container\n useEffect(() => {\n const container = document.getElementById(options.llmOutputContainerId);\n if (!container) {\n return;\n }\n\n // Initial scan\n processWeaveFormat();\n\n // Set up MutationObserver for streaming responses\n const observer = new MutationObserver(() => {\n const now = Date.now();\n\n // Phase 1: Update last mutation time for silence detection\n lastMutationTimeRef.current = now;\n // Reset silence counter since we detected a mutation\n mutationSilenceCountRef.current = 0;\n\n // Phase 2: Track mutation timestamp for adaptive debounce calculation\n mutationTimestampsRef.current.push(now);\n // Keep only last 10 timestamps to avoid memory bloat\n if (mutationTimestampsRef.current.length > 10) {\n mutationTimestampsRef.current.shift();\n }\n // Recalculate adaptive timeout based on recent mutation pattern\n calculateAdaptiveTimeout();\n\n processWeaveFormat();\n });\n\n observer.observe(container, {\n childList: true,\n subtree: true,\n characterData: false\n });\n\n return () => {\n observer.disconnect();\n // Clean up debounce timer on unmount\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n // Phase 1: Clean up silence check interval on unmount\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n }\n };\n }, [options.llmOutputContainerId, processWeaveFormat, calculateAdaptiveTimeout]);\n\n return {\n isProcessing: processingRef.current,\n detectedLinksCount: detectedLinksRef.current,\n linksFound: linksFoundRef.current,\n shouldRenderFallback: !linksFoundRef.current && callbackFiredRef.current,\n processWeaveFormat\n };\n};\n\nexport default useWeaveAdFormat;\n","/**\n * AdMesh UI SDK - Main Entry Point\n * \n * Zero-code integration for displaying AdMesh recommendations\n */\n\n// Import Tailwind CSS for markdown styling\nimport './styles/globals.css';\n\n// Core SDK\nexport { AdMeshSDK } from './sdk/AdMeshSDK';\nexport type { AdMeshSDKConfig, ShowRecommendationsOptions } from './sdk/AdMeshSDK';\n\n// Tracking\nexport { AdMeshTracker } from './sdk/AdMeshTracker';\nexport type { TrackerConfig } from './sdk/AdMeshTracker';\n\n// Rendering\nexport { AdMeshRenderer } from './sdk/AdMeshRenderer';\nexport type { RenderOptions } from './sdk/AdMeshRenderer';\n\n// ACIE API integration\nexport { callAnalyzeIntentEndpoint } from './utils/acieApi';\nexport type { \n CommercialIntentRequest, \n CommercialIntentResult\n} from './utils/acieApi';\n\n// Weave Response Processing\nexport { WeaveResponseProcessor } from './sdk/WeaveResponseProcessor';\nexport type { DetectedLink, ProcessorConfig } from './sdk/WeaveResponseProcessor';\n\n// Weave format is now integrated into AdMeshSDK\n// Use format: 'weave' option in showRecommendations() method\n\n// Provider Pattern (Simplified Integration)\nexport { AdMeshProvider } from './context/AdMeshProvider';\nexport type { AdMeshProviderProps } from './context/AdMeshProvider';\n\n// Components\nexport { AdMeshRecommendations } from './components/AdMeshRecommendations';\nexport type { AdMeshRecommendationsProps } from './components/AdMeshRecommendations';\nexport { WeaveFallbackRecommendations } from './components/WeaveFallbackRecommendations';\nexport type { WeaveFallbackRecommendationsProps } from './components/WeaveFallbackRecommendations';\n\n// Context\nexport { AdMeshContext, useAdMeshContext } from './context/AdMeshContext';\nexport type { AdMeshContextValue } from './context/AdMeshContext';\nexport { WeaveAdFormatProvider, useWeaveAdFormatContext } from './context/WeaveAdFormatContext';\nexport type { WeaveAdFormatContextType } from './context/WeaveAdFormatContext';\n\n// Components\nexport { AdMeshLayout } from './components/AdMeshLayout';\nexport { AdMeshTailAd } from './components/AdMeshTailAd';\nexport type { AdMeshTailAdProps } from './components/AdMeshTailAd';\nexport { AdMeshCompactCard } from './components/AdMeshCompactCard';\nexport { AdMeshFollowup } from './components/AdMeshFollowup';\nexport type { AdMeshFollowupProps } from './components/AdMeshFollowup';\nexport { AdMeshViewabilityTracker } from './components/AdMeshViewabilityTracker';\nexport { AdMeshLinkTracker } from './components/AdMeshLinkTracker';\nexport { AdMeshBadge } from './components/AdMeshBadge';\nexport { AdMeshIntentAssistant } from './components/AdMeshIntentAssistant';\nexport type { AdMeshIntentAssistantProps } from './components/AdMeshIntentAssistant';\nexport { WeaveAdFormatContainer } from './components/WeaveAdFormatContainer';\nexport type { WeaveAdFormatContainerProps } from './components/WeaveAdFormatContainer';\n\n// Hooks\nexport { useAdMesh } from './hooks/useAdMesh';\nexport { useAdMeshStyles } from './hooks/useAdMeshStyles';\nexport { useViewabilityTracker } from './hooks/useViewabilityTracker';\nexport { useWeaveAdFormat } from './hooks/useWeaveAdFormat';\nexport type { UseWeaveAdFormatOptions } from './hooks/useWeaveAdFormat';\n\n// Types\nexport type { AdMeshTheme, PlatformResponse, DelegationActivationPayload, ActiveDelegationSession } from './types/index';\n\n// Streaming Events (for event-driven link detection)\nexport {\n dispatchStreamingStartEvent,\n dispatchStreamingCompleteEvent,\n onStreamingStart,\n onStreamingComplete,\n STREAMING_START_EVENT,\n STREAMING_COMPLETE_EVENT\n} from './utils/streamingEvents';\nexport type {\n StreamingStartEventDetail,\n StreamingCompleteEventDetail\n} from './utils/streamingEvents';\n\n// Inline exposure tracking helper\nexport {\n createInlineExposureTracker\n} from './utils/inlineExposureTracker';\nexport type {\n InlineExposureTracker,\n InlineExposureTrackingParams\n} from './utils/inlineExposureTracker';\n\n// Headings extraction utility\nexport { extractHeadingsDirectly } from './utils/extractHeadings';\nexport type { HeadingsExtractionResult } from './utils/extractHeadings';\n\n// Version\nexport const VERSION = '1.0.31';\n"],"names":["isProduction","_a","logger","args","calculateMRCStandards","adWidth","adHeight","customStandards","isLargeAd","detectDeviceType","viewportWidth","calculateVisibilityPercentage","element","rect","viewportHeight","elementHeight","elementWidth","visibleTop","visibleBottom","visibleLeft","visibleRight","visibleHeight","visibleWidth","visibleArea","totalArea","calculateScrollDepth","windowHeight","documentHeight","scrollTop","scrollableHeight","getElementPosition","scrollLeft","collectContextMetrics","position","isDarkMode","generateSessionId","meetsViewabilityThreshold","visibilityPercentage","visibleDuration","standards","formatTimestamp","date","calculateAverage","numbers","acc","num","throttle","func","limit","inThrottle","DEFAULT_CONFIG","globalConfig","ANALYTICS_DISABLED","useViewabilityTracker","productId","offerId","agentId","recommendationId","elementRef","customConfig","config","sessionId","useRef","state","setState","useState","mrcStandards","visibilityStartTime","viewableStartTime","hoverStartTime","focusStartTime","visibilityPercentages","eventBatch","batchTimeout","log","useCallback","message","sendEvent","eventType","additionalData","contextMetrics","event","flushBatch","updateVisibility","now","loadTime","prev","newState","wasVisible","isNowVisible","wasViewable","isNowViewable","viewableDuration","useEffect","observer","entries","handleScroll","handleMouseEnter","handleMouseLeave","hoverDuration","handleFocus","handleBlur","focusDuration","handleClick","sessionDuration","AdMeshViewabilityTracker","exposureUrl","triggerExposureUrl","children","className","style","onViewabilityChange","onVisible","onViewable","onClick","exposureFired","viewabilityState","previousViewable","error","previousVisible","jsx","isValidUrl","url","getDisplayText","value","asOptionalString","getCTALabel","ctaLabel","formatProductPrice","price","currency","AdMeshCompactCard","recommendations","theme","onDelegationConsent","onDelegationActivated","onStartDelegation","firstRecommendation","recommendation","creative","tracking","delegation","brandName","headline","description","logoUrl","clickUrl","disclosure","relatedProducts","visibleProducts","hasProductRail","isBridgeRecommendation","hasDelegation","shouldShowDelegationButton","delegationBrandName","delegationCtaText","shouldShowPrimaryCta","compactTitle","compactSummary","normalizedBrandName","normalizedCompactTitle","shouldShowBrandEyebrow","showConsentPrompt","setShowConsentPrompt","consentResolverRef","resolveConsentPrompt","requestConsent","resolve","handleContainerClick","source","e","handleCardClick","handleCardKeyDown","trackDelegationEngagement","apiBaseUrl","response","handleDelegationClick","delegationPayload","logoError","setLogoError","cardBackground","_b","cardBorder","_d","_c","cardShadow","_e","_g","_f","accentColor","mutedText","bodyText","titleText","railCardBackground","textColumnOffset","footerAction","jsxs","_i","_h","product","productName","productLink","productPrice","productImageUrl","displayImage","hasProductLink","AdMeshLayout","validRecs","rec","renderContent","firstRec","preferredFormat","AdMeshTracker","__publicField","key","timeoutId","entry","cleanupTimeout","threshold","engagementUrl","_recommendationId","AdMeshContext","createContext","useAdMeshContext","context","useContext","titleFromPath","pathname","segments","cleaned","char","extractHeadingsDirectly","cleanText","text","getArticleText","selectors","ignoredSelector","clone","selector","node","candidate","a","b","paragraphs","fallbackTitle","title","headings","allHeadings","headingElements","resolvedHeadings","result","isPlatformResponse","normalizeAcieRecommendation","products","_j","_k","normalizeCommercialIntentResult","suggestion","extractArticleSlug","pathSegments","segment","callAnalyzeIntentEndpoint","headingsData","pathTopic","fallbackHeading","articleSlug","normalizedSource","normalizedDomain","payload","apiUrl","errorText","rawAnalysisResult","analysisResult","err","fetchPageContext","base","params","body","isInIframe","getUsableWindowHref","href","isResolvedArticleUrl","trimmed","parsed","titleFromUrlPath","buildUrlFallbackContext","resolveArticleUrlForContext","articleUrl","currentHref","AdMeshProvider","apiKey","extension","language","location","userId","model","messages","pageContext","contextMode","agentDisplayId","sdk","setSdk","processedMessageIds","setProcessedMessageIds","recommendationResults","setRecommendationResults","activeDelegationSession","setActiveDelegationSessionState","suggestions","setSuggestions","isAnalyzingIntent","setIsAnalyzingIntent","intentError","setIntentError","isResolvingPageContext","setIsResolvingPageContext","hasAttemptedInitialAnalysisRef","usesAdSlotContext","resolveHeadingsForAnalysis","targetUrl","prependSponsoredSuggestion","currentSuggestions","sponsoredSuggestion","organicSuggestions","mergeOrganicSuggestions","nextOrganicSuggestions","sdkInstance","AdMeshSDK","performIntentAnalysis","prefetchedHeadingsData","current","prefetchSponsoredSuggestion","query","platformResult","suggestionText","retryIntentAnalysis","isDelegationSessionActive","session","expiresAtMs","postDelegationEvent","endpoint","metadata","sessionOverride","timestamp","errorBody","updatedSession","interval","contextValue","messageId","updated","next","reason","analyticsError","AdMeshRenderer","options","container","existingRoot","root","ReactDOM","containerId","normalizeCountryCode","_AdMeshSDK","configuredDomain","random","outcomeType","renderer","tracker","cacheKey","inFlightResponse","turnIndex","devicePlatform","formFactor","countryCode","resolvedUserId","jsonBody","_m","_l","headers","sourceDomain","requestPromise","errorMessage","data","WeaveResponseProcessor","optimizedLinks","onExposurePixel","detectedLinks","links","clickUrlMap","r","brandUrlMap","redirectUrl","normalizedUrl","link","linkKey","actualHref","normalizedHref","recommendationClickUrl","detectedLink","childElements","child","prevNode","tagName","nextNode","parentNode","subLabel","isTooltipVisible","closeTooltipOnClickOutside","nextSibling","domain","match","useAdMesh","PlusIcon","size","AdMeshFollowup","_theme","onExecuteQuery","followupSuggestion","followupQuery","followupEngagementUrl","followupExposureUrl","handleFollowupClick","AdMeshRecommendations","onRecommendationsShown","onError","propUserId","initialRecommendation","followups_container_id","onPasteToInput","onFollowupDetected","isContainerReady","contextUserId","getRecommendationResult","hasRecommendationResult","setRecommendationResult","setActiveDelegationSession","hasActiveDelegationSession","isFilledAuctionResponse","setPlatformResult","detectedFormat","setDetectedFormat","isLoading","setIsLoading","setError","fetchedMessageIdRef","isFetchingRef","reusedInitialRecommendationRef","onRecommendationsShownRef","onErrorRef","hasActiveDelegatedSessionForConversation","storedResult","selectedFormat","canonicalResponse","initialStatus","resultStatus","handleSdkDelegationActivated","activation","resolvedPayload","activeSession","eventError","callbackError","followupContainer","Fragment","createPortal","WeaveFallbackRecommendations","format","fallback","previousRecommendations","containerRef","setContainerId","hasPreviousRecs","aipResponse","sdkAny","getRendererMethod","getTrackerMethod","sdkTheme","WeaveAdFormatContext","WeaveAdFormatProvider","shouldRenderFallback","useWeaveAdFormatContext","truncateWords","maxWords","words","formatProductDiscount","discount","discountType","normalizedType","TAIL_AD_COLORS","AdMeshTailAd","shortDescription","_n","_p","_o","_r","_q","_t","_s","recommendationFormat","_u","_v","_w","headlineText","headlineSuffix","_x","_z","_y","handleBrandNameClick","handleCTAClick","handleLogoClick","fallbackPrompt","brandInitial","cardBorderRadius","_B","_A","defaultShadow","hoverShadow","_C","_E","_D","cardHoverShadow","_F","_G","productDescription","productDiscount","fallbackLogoUrl","displayProductImageUrl","productCtaLabel","AdMeshLinkTracker","admeshLink","_productId","_trackingData","hasOwn","classNames","classes","i","arg","appendClass","parseValue","newClass","module","badgeTypeVariants","badgeTypeIcons","AdMeshBadge","type","variant","effectiveVariant","icon","badgeClasses","mergeClasses","index","array","toKebabCase","string","toCamelCase","p1","p2","toPascalCase","camelCase","defaultAttributes","hasA11yProp","props","prop","Icon","forwardRef","color","strokeWidth","absoluteStrokeWidth","iconNode","rest","ref","createElement","tag","attrs","createLucideIcon","iconName","Component","__iconNode","Maximize2","Minimize2","Send","ThumbsDown","ThumbsUp","X","ADMESH_STYLE_ID","ADMESH_RESET_ID","ADMESH_CSS_RESET","ADMESH_CORE_STYLES","injectAdMeshStyles","resetStyle","coreStyle","ADMESH_STYLES","stylesInjected","useAdMeshStyles","styleElement","formatGenerationDuration","totalSeconds","seconds","minutes","remainder","formatGenerationDurationFromMs","durationMs","CustomMarkdownRenderer","content","fontSize","renderInlineFormatting","part","parseTableRow","line","cell","cells","isTableSeparator","splitTablePrefixHeading","pipeIndex","prefix","normalizeTableSeparator","headerLine","separatorLine","headerCount","separatorCount","normalizeTableLines","lines","heading","normalizedHeader","normalizedSeparator","isMarkdownTable","normalizedLines","expandInlineTableLine","working","_match","separatorRow","normalizeCompactMarkdownTables","markdown","normalized","blocks","output","nextLine","block","blockIndex","isBulletList","isNumberedList","isHeading","isTable","tableLines","rows","row","header","rowIndex","cellIndex","ListTag","lineIndex","toCssSize","normalizeSuggestionText","mergeSuggestionsPreservingOrganic","nextSuggestions","currentOrganicSuggestions","buildFollowupSuggestionsFromAnswer","answer","sourceLinks","relatedItems","seen","pushSuggestion","topics","collectTopic","item","cleanQuery","topicList","detectAssistantDeviceType","width","isResolvedPageUrl","getAssistantPageContext","pageUrlOverride","resolvedPageUrl","page_path","buildSponsoredSuggestionFromRecommendation","prioritizeSponsoredSuggestions","items","left","right","leftSponsored","rightSponsored","defaultTheme","sizeConfig","positionConfig","AdMeshIntentAssistant","propTheme","triggerLabel","headerTitle","headerLogoUrl","showHeaderTitle","showSubtitle","layout","surface","panelWidth","panelHeight","analyticsPageUrl","fontScale","defaultOpen","open","onOpenChange","autoOpen","showWelcomeMessage","welcomeMessage","placeholder","adsEnabled","propSuggestions","maxSuggestions","suggestionStyle","onlyShowWhenSponsored","queryHandler","suggestionsLoader","disclaimerText","poweredByLabel","subtitle","onOpen","onClose","contextTheme","contextSuggestions","stopDelegationSession","refreshDelegationActivity","themeMode","isAdSlotSurface","internalOpen","setInternalOpen","isControlled","isOpen","inputValue","setInputValue","setMessages","isExpanded","setIsExpanded","sponsoredClickedMessages","setSponsoredClickedMessages","resolvedSuggestions","setResolvedSuggestions","loadingLabelIndex","setLoadingLabelIndex","generationElapsedSec","setGenerationElapsedSec","messageFeedback","setMessageFeedback","generationStartedAtRef","currentMessageIsSponsored","currentSponsoredSuggestionRef","suggestionButtonRefs","suggestionExposureCleanupRef","messagesScrollRef","activeSubmittedMessageRef","activeSubmittedMessageIdRef","shouldAnchorSubmittedMessageRef","suppressAutoScrollToBottomRef","adSlotRootRef","messagesEndRef","suggestionsScrollRef","generationAbortRef","activeAssistantMessageIdRef","canScrollSuggestionsLeft","setCanScrollSuggestionsLeft","canScrollSuggestionsRight","setCanScrollSuggestionsRight","canUseDirectAdMeshFetch","connectedDelegationSession","trackedSuggestionExposureKeysRef","trackedRecommendationKeysRef","loadedTrackedRef","shouldExpandAdSlot","adSlotWidthCss","adSlotHeightCss","setSuggestionButtonRef","suggestionId","trackAssistantEvent","event_name","handleRecommendationShown","trackKey","refreshSuggestionsForResponse","followupSuggestions","generated","normalizedText","upsertSponsoredFollowupSuggestion","organic","scrollSubmittedMessageToTop","scroller","activeMessage","scrollerRect","activeMessageRect","targetTop","useLayoutEffect","mountNode","nextHeight","host","cancelled","loadError","tick","startedAt","handleOpenChange","newOpen","handleOpenClick","handleCloseClick","handleToggleExpand","callAssistantAPI","onContentChunk","onStreamStart","sponsoredRecommendation","signal","activityError","reader","decoder","fullResponse","finalSourceLinks","finalRelatedItems","finalFollowupSuggestions","finalUsedCapability","finalResponseTimeMs","done","parsedData","handleStopGeneration","controller","activeAssistantMessageId","msg","handleSendMessage","normalizedMessage","userMessageId","generationController","activeSponsoredSuggestion","activeSponsoredRecommendation","userMessage","assistantMessageId","initialAssistantMessage","queryError","errorResponse","assistantMessage","sponsoredRecommendationForMessage","contentChunk","resolvedResponseTimeMs","hasSponsoredSuggestions","useMemo","s","safeSuggestions","orderedSuggestions","handleSuggestionClick","suggestionPosition","positionStyle","sizeStyle","cleanup","exposureKey","viewableTimer","fireSuggestionExposure","fontSizes","genericDisclaimer","loadingSteps","renderGeneratingIndicator","accent","publisherAccent","meta","publisherMeta","includeSteps","timerLabel","statusLabel","withAlpha","brandPrimary","handleAnswerFeedback","helpful","feedbackValue","renderAnswerFooter","selectedFeedback","hasTiming","updateSuggestionScrollState","maxScrollLeft","scrollSuggestions","direction","hex","alpha","raw","full","red","green","blue","brandBorder","brandText","brandMuted","purpleBorderSoft","purpleShadowSoft","publisherPanelWidth","publisherPanelHeight","publisherPanelMaxWidth","publisherPanelMaxHeight","publisherMessageFontSize","publisherSurfaceBg","assistantSubtitle","shouldShowSuggestionSkeletons","expandedShellBackground","expandedHeaderBackground","expandedBorder","expandedBorderStrong","expandedShadow","expandedMutedText","expandedSubtleText","expandedUserBubble","expandedComposerBackground","expandedComposerShadow","expandedOverlay","renderDelegationBanner","mode","renderExpandedBranding","compact","renderSuggestionSkeletons","skeletonWidths","renderPublisherSuggestions","visibleSuggestions","renderSourceLinks","renderRelatedItems","renderPublisherMessages","isActiveSubmittedMessage","shouldShowRecommendations","recommendationError","teaser","XIcon","SendIcon","STREAMING_START_EVENT","STREAMING_COMPLETE_EVENT","dispatchStreamingStartEvent","detail","dispatchStreamingCompleteEvent","onStreamingStart","callback","handler","customEvent","onStreamingComplete","createInlineExposureTracker","firedKeys","activeTrackers","cleanupTracker","linkElement","logPrefix","dedupeKey","trackerState","fireExposurePixel","FinalLinkDetectionCheck","onLinksFound","onNoLinksFound","checkComplete","setCheckComplete","waitingForStreamEnd","setWaitingForStreamEnd","linksFound","setLinksFound","exposureTrackerRef","onLinksFoundRef","onNoLinksFoundRef","containerIdRef","sdkRef","sessionIdRef","queryRef","trackExposurePixel","performFinalCheck","weaveProcessor","recsToUse","eventReceived","WeaveAdFormatContainer","fallbackFormat","onLinksDetected","onNoLinksDetected","onFallbackChange","onWeaveAttempt","onWeaveOutcome","scannedRef","weaveProcessorRef","setRecommendations","recommendationsRef","platformResponse","recs","brandUrl","isWeaveFormat","count","useWeaveAdFormat","processingRef","detectedLinksRef","linksFoundRef","callbackFiredRef","debounceTimerRef","trackInlineExposure","lastMutationTimeRef","mutationSilenceCountRef","silenceCheckIntervalRef","mutationTimestampsRef","adaptiveTimeoutRef","processWeaveFormat","hasLinks","silenceCheckInterval","timeSinceLastMutation","SILENCE_THRESHOLD","maxFallbackTimeout","calculateAdaptiveTimeout","timestamps","intervals","avgInterval","adaptiveTimeout","VERSION"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","x_google_ignoreList":[22,24,25,26,27,28,29,30,31,32,33,34,35,36,37]}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/logger.ts","../src/utils/viewabilityTracker.ts","../src/hooks/useViewabilityTracker.ts","../src/components/AdMeshViewabilityTracker.tsx","../src/components/AdMeshCompactCard.tsx","../src/components/AdMeshLayout.tsx","../src/sdk/AdMeshTracker.ts","../src/context/AdMeshContext.ts","../src/utils/extractHeadings.ts","../src/utils/acieApi.ts","../src/utils/pageContextApi.ts","../src/context/AdMeshProvider.tsx","../src/sdk/AdMeshRenderer.tsx","../src/sdk/AdMeshSDK.ts","../src/sdk/WeaveResponseProcessor.ts","../src/hooks/useAdMesh.ts","../src/components/AdMeshFollowup.tsx","../src/components/AdMeshRecommendations.tsx","../src/components/WeaveFallbackRecommendations.tsx","../src/context/WeaveAdFormatContext.tsx","../src/components/AdMeshTailAd.tsx","../src/components/AdMeshLinkTracker.tsx","../../node_modules/classnames/index.js","../src/components/AdMeshBadge.tsx","../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.js","../../node_modules/lucide-react/dist/esm/defaultAttributes.js","../../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.js","../../node_modules/lucide-react/dist/esm/Icon.js","../../node_modules/lucide-react/dist/esm/createLucideIcon.js","../../node_modules/lucide-react/dist/esm/icons/maximize-2.js","../../node_modules/lucide-react/dist/esm/icons/minimize-2.js","../../node_modules/lucide-react/dist/esm/icons/send.js","../../node_modules/lucide-react/dist/esm/icons/thumbs-down.js","../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js","../../node_modules/lucide-react/dist/esm/icons/x.js","../src/utils/styleInjection.ts","../src/hooks/useAdMeshStyles.ts","../src/components/AdMeshIntentAssistant.tsx","../src/utils/streamingEvents.ts","../src/utils/inlineExposureTracker.ts","../src/components/WeaveAdFormatContainer.tsx","../src/hooks/useWeaveAdFormat.ts","../src/index.ts"],"sourcesContent":["/**\n * Logger utility for AdMesh UI SDK\n * Disables all logs in production environment\n */\n\n// Check for production environment\n// Supports both Vite (import.meta.env) and standard Node.js (process.env)\nlet isProduction = false;\ntry {\n // Check for Vite's import.meta.env (only available in ESM modules)\n if (typeof (globalThis as any).importMeta !== 'undefined' && (globalThis as any).importMeta.env?.PROD) {\n isProduction = true;\n }\n} catch (e) {\n // import.meta not available, continue with other checks\n}\n\nif (!isProduction) {\n isProduction = \n (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') ||\n (typeof process !== 'undefined' && process.env.ADMESH_ENV === 'production');\n}\n\nexport const logger = {\n log: (...args: any[]) => {\n if (!isProduction) {\n console.log(...args);\n }\n },\n \n warn: (...args: any[]) => {\n if (!isProduction) {\n console.warn(...args);\n }\n },\n \n error: (...args: any[]) => {\n // Errors are always logged, even in production, as they're critical\n console.error(...args);\n },\n \n info: (...args: any[]) => {\n if (!isProduction) {\n console.info(...args);\n }\n },\n \n debug: (...args: any[]) => {\n if (!isProduction) {\n console.debug(...args);\n }\n },\n};\n\n","/**\n * AdMesh UI SDK - MRC Viewability Tracker Utilities\n * Implements Media Rating Council (MRC) viewability standards\n */\n\nimport type {\n MRCViewabilityStandards,\n DeviceType,\n ViewabilityContextMetrics,\n ViewabilityAnalyticsEvent\n} from '../types/analytics';\nimport { logger } from './logger';\n\n/**\n * Calculate MRC viewability standards based on ad size\n */\nexport function calculateMRCStandards(\n adWidth: number,\n adHeight: number,\n customStandards?: Partial<MRCViewabilityStandards>\n): MRCViewabilityStandards {\n const adPixels = adWidth * adHeight;\n const isLargeAd = adPixels > 242500; // MRC threshold for large ads\n\n const defaults: MRCViewabilityStandards = {\n visibilityThreshold: isLargeAd ? 0.3 : 0.5, // 30% for large, 50% for standard\n minimumDuration: 1000, // 1 second in milliseconds\n isLargeAd\n };\n\n return { ...defaults, ...customStandards };\n}\n\n/**\n * Detect device type based on viewport width\n */\nexport function detectDeviceType(viewportWidth: number): DeviceType {\n if (viewportWidth < 768) return 'mobile';\n if (viewportWidth < 1024) return 'tablet';\n return 'desktop';\n}\n\n/**\n * Calculate visibility percentage of element in viewport\n */\nexport function calculateVisibilityPercentage(element: HTMLElement): number {\n const rect = element.getBoundingClientRect();\n const viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n const viewportWidth = window.innerWidth || document.documentElement.clientWidth;\n\n // Element dimensions\n const elementHeight = rect.height;\n const elementWidth = rect.width;\n\n if (elementHeight === 0 || elementWidth === 0) return 0;\n\n // Calculate visible portion\n const visibleTop = Math.max(0, rect.top);\n const visibleBottom = Math.min(viewportHeight, rect.bottom);\n const visibleLeft = Math.max(0, rect.left);\n const visibleRight = Math.min(viewportWidth, rect.right);\n\n const visibleHeight = Math.max(0, visibleBottom - visibleTop);\n const visibleWidth = Math.max(0, visibleRight - visibleLeft);\n\n const visibleArea = visibleHeight * visibleWidth;\n const totalArea = elementHeight * elementWidth;\n\n return totalArea > 0 ? (visibleArea / totalArea) : 0;\n}\n\n/**\n * Calculate current scroll depth as percentage\n */\nexport function calculateScrollDepth(): number {\n const windowHeight = window.innerHeight;\n const documentHeight = document.documentElement.scrollHeight;\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n\n const scrollableHeight = documentHeight - windowHeight;\n if (scrollableHeight <= 0) return 100;\n\n return Math.min(100, (scrollTop / scrollableHeight) * 100);\n}\n\n/**\n * Get element position on page\n */\nexport function getElementPosition(element: HTMLElement): { top: number; left: number } {\n const rect = element.getBoundingClientRect();\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop;\n const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;\n\n return {\n top: rect.top + scrollTop,\n left: rect.left + scrollLeft\n };\n}\n\n/**\n * Collect context metrics\n */\nexport function collectContextMetrics(element: HTMLElement): ViewabilityContextMetrics {\n const rect = element.getBoundingClientRect();\n const position = getElementPosition(element);\n const viewportWidth = window.innerWidth || document.documentElement.clientWidth;\n const viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n\n // Detect dark mode\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n\n return {\n pageUrl: window.location.href,\n pageTitle: document.title,\n referrer: document.referrer,\n deviceType: detectDeviceType(viewportWidth),\n viewportWidth,\n viewportHeight,\n adWidth: rect.width,\n adHeight: rect.height,\n adPositionTop: position.top,\n adPositionLeft: position.left,\n isDarkMode,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone\n };\n}\n\n/**\n * Generate unique session ID for INTERNAL viewability tracking only.\n * \n * IMPORTANT: This is NOT the main sessionId used for recommendations.\n * This is only used internally by the viewability tracker for tracking\n * viewability events. The main sessionId MUST be provided by the platform\n * and passed to AdMeshProvider and SDK methods.\n */\nexport function generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * Generate unique batch ID\n */\nexport function generateBatchId(): string {\n return `batch_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * Check if ad meets MRC viewability threshold\n */\nexport function meetsViewabilityThreshold(\n visibilityPercentage: number,\n visibleDuration: number,\n standards: MRCViewabilityStandards\n): boolean {\n return (\n visibilityPercentage >= standards.visibilityThreshold &&\n visibleDuration >= standards.minimumDuration\n );\n}\n\n/**\n * Format timestamp to ISO 8601\n */\nexport function formatTimestamp(date: Date = new Date()): string {\n return date.toISOString();\n}\n\n/**\n * Calculate average from array of numbers\n */\nexport function calculateAverage(numbers: number[]): number {\n if (numbers.length === 0) return 0;\n const sum = numbers.reduce((acc, num) => acc + num, 0);\n return sum / numbers.length;\n}\n\n/**\n * Debounce function for performance optimization\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: NodeJS.Timeout | null = null;\n\n return function executedFunction(...args: Parameters<T>) {\n const later = () => {\n timeout = null;\n func(...args);\n };\n\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n}\n\n/**\n * Throttle function for performance optimization\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle: boolean;\n\n return function executedFunction(...args: Parameters<T>) {\n if (!inThrottle) {\n func(...args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\n/**\n * Send analytics event to API\n *\n * NOTE: If apiEndpoint is empty, the event is silently discarded (no error).\n * This allows the SDK to collect analytics without sending them to a backend.\n */\nexport async function sendAnalyticsEvent(\n event: ViewabilityAnalyticsEvent,\n apiEndpoint: string,\n retryAttempts: number = 3,\n retryDelay: number = 1000\n): Promise<boolean> {\n // If no endpoint is configured, silently skip sending\n if (!apiEndpoint || apiEndpoint.trim() === '') {\n return true;\n }\n\n for (let attempt = 0; attempt < retryAttempts; attempt++) {\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(event),\n keepalive: true\n });\n\n if (response.ok) {\n return true;\n }\n\n // Log error details for debugging\n await response.text().catch(() => '');\n } catch (error) {\n // Error caught, will retry\n }\n\n // Wait before retry (exponential backoff)\n if (attempt < retryAttempts - 1) {\n await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));\n }\n }\n\n logger.error('[AdMesh Viewability] Failed to send analytics event');\n return false;\n}\n\n/**\n * Send batched analytics events to API\n *\n * NOTE: If apiEndpoint is empty, the batch is silently discarded (no error).\n * This allows the SDK to collect analytics without sending them to a backend.\n */\nexport async function sendAnalyticsBatch(\n events: ViewabilityAnalyticsEvent[],\n sessionId: string,\n apiEndpoint: string,\n retryAttempts: number = 3,\n retryDelay: number = 1000\n): Promise<boolean> {\n if (events.length === 0) return true;\n\n // If no endpoint is configured, silently skip sending\n if (!apiEndpoint || apiEndpoint.trim() === '') {\n return true;\n }\n\n const batch = {\n batchId: generateBatchId(),\n sessionId,\n createdAt: formatTimestamp(),\n events,\n eventCount: events.length\n };\n\n for (let attempt = 0; attempt < retryAttempts; attempt++) {\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(batch),\n keepalive: true\n });\n\n if (response.ok) {\n return true;\n }\n\n // Log error details for debugging\n await response.text().catch(() => '');\n } catch (error) {\n // Error caught, will retry\n }\n\n // Wait before retry (exponential backoff)\n if (attempt < retryAttempts - 1) {\n await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt)));\n }\n }\n\n logger.error('[AdMesh Viewability] Failed to send analytics batch');\n return false;\n}\n\n/**\n * Sanitize URL to remove PII (query parameters, fragments)\n */\nexport function sanitizeUrl(url: string): string {\n try {\n const urlObj = new URL(url);\n // Remove query parameters and hash\n return `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;\n } catch {\n return url;\n }\n}\n\n/**\n * Check if element is in viewport\n */\nexport function isElementInViewport(element: HTMLElement): boolean {\n const rect = element.getBoundingClientRect();\n return (\n rect.top < (window.innerHeight || document.documentElement.clientHeight) &&\n rect.bottom > 0 &&\n rect.left < (window.innerWidth || document.documentElement.clientWidth) &&\n rect.right > 0\n );\n}\n","/**\n * AdMesh UI SDK - MRC Viewability Tracker Hook\n * React hook for tracking ad viewability according to MRC standards\n */\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { logger } from '../utils/logger';\nimport type {\n ViewabilityTrackerConfig,\n ViewabilityTrackerState,\n ViewabilityAnalyticsEvent,\n ViewabilityEventType,\n MRCViewabilityStandards\n} from '../types/analytics';\nimport {\n calculateMRCStandards,\n calculateVisibilityPercentage,\n calculateScrollDepth,\n collectContextMetrics,\n generateSessionId,\n meetsViewabilityThreshold,\n formatTimestamp,\n calculateAverage,\n throttle\n} from '../utils/viewabilityTracker';\n\n// Default configuration\nconst DEFAULT_CONFIG: ViewabilityTrackerConfig = {\n enabled: true,\n // Analytics endpoint disabled - no analytics will be sent\n apiEndpoint: '', // Empty string disables analytics sending\n enableBatching: false, // Disabled since no endpoint\n batchSize: 10,\n batchTimeout: 5000, // 5 seconds\n debug: false,\n enableRetry: false,\n maxRetries: 3,\n retryDelay: 1000\n};\n\n// Global config that can be set by consuming application\nlet globalConfig: ViewabilityTrackerConfig = DEFAULT_CONFIG;\n\n// TEMPORARY: Global flag to disable all analytics sending\n// Set this to true to prevent any viewability analytics from being sent to the backend\n// This is a temporary measure and can be easily reverted by setting to false\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nlet ANALYTICS_DISABLED = false;\n\nexport const setViewabilityTrackerConfig = (config: Partial<ViewabilityTrackerConfig>) => {\n globalConfig = { ...globalConfig, ...config };\n};\n\n/**\n * TEMPORARY: Disable/enable all viewability analytics sending\n * @param disabled - Set to true to disable analytics, false to enable\n *\n * Usage:\n * disableViewabilityAnalytics(true); // Disable all analytics\n * disableViewabilityAnalytics(false); // Re-enable analytics\n */\nexport const disableViewabilityAnalytics = (disabled: boolean) => {\n ANALYTICS_DISABLED = disabled;\n if (disabled) {\n logger.warn('[AdMesh Viewability] Analytics sending is DISABLED - no data will be sent to backend');\n } else {\n logger.log('[AdMesh Viewability] Analytics sending is ENABLED');\n }\n};\n\ninterface UseViewabilityTrackerProps {\n /** Product ID */\n productId?: string;\n /** Offer ID */\n offerId?: string;\n /** Agent ID */\n agentId?: string;\n /** Recommendation ID (from recommendations collection) */\n recommendationId: string;\n /** HTML element to track */\n elementRef: React.RefObject<HTMLElement>;\n /** Custom configuration */\n config?: Partial<ViewabilityTrackerConfig>;\n}\n\nexport function useViewabilityTracker({\n productId,\n offerId,\n agentId,\n recommendationId,\n elementRef,\n config: customConfig\n}: UseViewabilityTrackerProps): ViewabilityTrackerState {\n const config = { ...globalConfig, ...customConfig };\n\n // Session ID (persists for component lifetime)\n const sessionId = useRef(generateSessionId());\n\n // State\n const [state, setState] = useState<ViewabilityTrackerState>({\n isVisible: false,\n isViewable: false,\n visibilityPercentage: 0,\n timeMetrics: {\n loadedAt: formatTimestamp(),\n totalVisibleDuration: 0,\n totalViewableDuration: 0,\n totalHoverDuration: 0,\n totalFocusDuration: 0\n },\n engagementMetrics: {\n currentScrollDepth: 0,\n viewportEnterCount: 0,\n viewportExitCount: 0,\n hoverCount: 0,\n wasClicked: false,\n maxVisibilityPercentage: 0,\n averageVisibilityPercentage: 0\n },\n isTracking: config.enabled\n });\n\n // Refs for tracking\n const mrcStandards = useRef<MRCViewabilityStandards | null>(null);\n const visibilityStartTime = useRef<number | null>(null);\n const viewableStartTime = useRef<number | null>(null);\n const hoverStartTime = useRef<number | null>(null);\n const focusStartTime = useRef<number | null>(null);\n const visibilityPercentages = useRef<number[]>([]);\n const eventBatch = useRef<ViewabilityAnalyticsEvent[]>([]);\n const batchTimeout = useRef<NodeJS.Timeout | null>(null);\n\n // Log helper\n const log = useCallback((message: string) => {\n if (config.debug) {\n logger.log(`[AdMesh Viewability] ${message}`);\n }\n }, [config.debug]);\n\n // Send event (analytics disabled - no events sent to backend)\n // Viewability tracking still works for exposure pixels (handled separately)\n const sendEvent = useCallback(async (eventType: ViewabilityEventType, additionalData?: Record<string, unknown>) => {\n if (!config.enabled || ANALYTICS_DISABLED || !elementRef.current || !mrcStandards.current) return;\n\n // Analytics disabled - no events sent to backend\n // Viewability tracking still works internally for exposure pixel firing\n log(`Analytics disabled - skipping event: ${eventType}`);\n \n // Call custom callback if provided (for local tracking)\n if (config.onEvent) {\n const contextMetrics = collectContextMetrics(elementRef.current);\n const event: ViewabilityAnalyticsEvent = {\n eventType,\n timestamp: formatTimestamp(),\n sessionId: sessionId.current,\n productId,\n offerId,\n agentId,\n recommendationId,\n timeMetrics: state.timeMetrics,\n engagementMetrics: state.engagementMetrics,\n contextMetrics,\n mrcStandards: mrcStandards.current,\n isViewable: state.isViewable,\n metadata: additionalData\n };\n config.onEvent(event);\n }\n }, [config, productId, offerId, agentId, recommendationId, elementRef, state, log]);\n\n // Flush event batch (disabled - analytics not sent)\n const flushBatch = useCallback(async () => {\n if (eventBatch.current.length === 0) return;\n\n // Analytics disabled - clear batch without sending\n log('Analytics disabled - clearing batch without sending');\n eventBatch.current = [];\n if (batchTimeout.current) {\n clearTimeout(batchTimeout.current);\n batchTimeout.current = null;\n }\n return;\n }, [log]);\n\n // Update visibility\n const updateVisibility = useCallback(throttle(() => {\n if (!elementRef.current) return;\n\n const visibilityPercentage = calculateVisibilityPercentage(elementRef.current);\n const now = Date.now();\n const loadTime = new Date(state.timeMetrics.loadedAt).getTime();\n\n setState(prev => {\n const newState = { ...prev };\n\n // Track visibility percentages for average calculation\n if (visibilityPercentage > 0) {\n visibilityPercentages.current.push(visibilityPercentage);\n }\n\n // Update visibility state\n const wasVisible = prev.isVisible;\n const isNowVisible = visibilityPercentage > 0;\n\n if (isNowVisible && !wasVisible) {\n // Became visible\n visibilityStartTime.current = now;\n newState.engagementMetrics.viewportEnterCount++;\n\n if (!newState.timeMetrics.timeToFirstVisible) {\n newState.timeMetrics.timeToFirstVisible = now - loadTime;\n newState.engagementMetrics.scrollDepthAtFirstVisible = calculateScrollDepth();\n sendEvent('ad_visible');\n }\n } else if (!isNowVisible && wasVisible) {\n // Became hidden\n if (visibilityStartTime.current) {\n const visibleDuration = now - visibilityStartTime.current;\n newState.timeMetrics.totalVisibleDuration += visibleDuration;\n visibilityStartTime.current = null;\n }\n newState.engagementMetrics.viewportExitCount++;\n sendEvent('ad_hidden');\n } else if (isNowVisible && wasVisible && visibilityStartTime.current) {\n // Still visible, update duration\n const visibleDuration = now - visibilityStartTime.current;\n newState.timeMetrics.totalVisibleDuration += visibleDuration;\n visibilityStartTime.current = now;\n }\n\n newState.isVisible = isNowVisible;\n newState.visibilityPercentage = visibilityPercentage;\n\n // Update max visibility\n if (visibilityPercentage > newState.engagementMetrics.maxVisibilityPercentage) {\n newState.engagementMetrics.maxVisibilityPercentage = visibilityPercentage;\n }\n\n // Update average visibility\n if (visibilityPercentages.current.length > 0) {\n newState.engagementMetrics.averageVisibilityPercentage = calculateAverage(visibilityPercentages.current);\n }\n\n // Check MRC viewability threshold\n if (mrcStandards.current) {\n const wasViewable = prev.isViewable;\n const isNowViewable = meetsViewabilityThreshold(\n visibilityPercentage,\n newState.timeMetrics.totalVisibleDuration,\n mrcStandards.current\n );\n\n if (isNowViewable && !wasViewable) {\n // Met viewability threshold\n newState.isViewable = true;\n newState.timeMetrics.timeToViewable = now - loadTime;\n viewableStartTime.current = now;\n sendEvent('ad_viewable');\n } else if (isNowViewable && wasViewable && viewableStartTime.current) {\n // Still viewable, update duration\n const viewableDuration = now - viewableStartTime.current;\n newState.timeMetrics.totalViewableDuration += viewableDuration;\n viewableStartTime.current = now;\n }\n }\n\n // Update scroll depth\n newState.engagementMetrics.currentScrollDepth = calculateScrollDepth();\n\n return newState;\n });\n }, 100), [elementRef, state.timeMetrics.loadedAt, sendEvent]);\n\n // Initialize MRC standards\n useEffect(() => {\n if (!elementRef.current) return;\n\n const rect = elementRef.current.getBoundingClientRect();\n mrcStandards.current = calculateMRCStandards(rect.width, rect.height, config.mrcStandards);\n\n log('Initialized MRC standards');\n sendEvent('ad_loaded');\n }, [elementRef, config.mrcStandards, log, sendEvent]);\n\n // Set up Intersection Observer\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach(() => {\n updateVisibility();\n });\n },\n {\n threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],\n rootMargin: '0px'\n }\n );\n\n observer.observe(elementRef.current);\n\n return () => {\n observer.disconnect();\n };\n }, [config.enabled, elementRef, updateVisibility]);\n\n // Track scroll events\n useEffect(() => {\n if (!config.enabled) return;\n\n const handleScroll = throttle(() => {\n updateVisibility();\n }, 100);\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, [config.enabled, updateVisibility]);\n\n // Track hover events\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const element = elementRef.current;\n\n const handleMouseEnter = () => {\n hoverStartTime.current = Date.now();\n setState(prev => ({\n ...prev,\n engagementMetrics: {\n ...prev.engagementMetrics,\n hoverCount: prev.engagementMetrics.hoverCount + 1\n }\n }));\n sendEvent('ad_hover_start');\n };\n\n const handleMouseLeave = () => {\n if (hoverStartTime.current) {\n const hoverDuration = Date.now() - hoverStartTime.current;\n setState(prev => ({\n ...prev,\n timeMetrics: {\n ...prev.timeMetrics,\n totalHoverDuration: prev.timeMetrics.totalHoverDuration + hoverDuration\n }\n }));\n hoverStartTime.current = null;\n sendEvent('ad_hover_end', { hoverDuration });\n }\n };\n\n element.addEventListener('mouseenter', handleMouseEnter);\n element.addEventListener('mouseleave', handleMouseLeave);\n\n return () => {\n element.removeEventListener('mouseenter', handleMouseEnter);\n element.removeEventListener('mouseleave', handleMouseLeave);\n };\n }, [config.enabled, elementRef, sendEvent]);\n\n // Track focus events\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const element = elementRef.current;\n\n const handleFocus = () => {\n focusStartTime.current = Date.now();\n sendEvent('ad_focus');\n };\n\n const handleBlur = () => {\n if (focusStartTime.current) {\n const focusDuration = Date.now() - focusStartTime.current;\n setState(prev => ({\n ...prev,\n timeMetrics: {\n ...prev.timeMetrics,\n totalFocusDuration: prev.timeMetrics.totalFocusDuration + focusDuration\n }\n }));\n focusStartTime.current = null;\n sendEvent('ad_blur', { focusDuration });\n }\n };\n\n element.addEventListener('focus', handleFocus);\n element.addEventListener('blur', handleBlur);\n\n return () => {\n element.removeEventListener('focus', handleFocus);\n element.removeEventListener('blur', handleBlur);\n };\n }, [config.enabled, elementRef, sendEvent]);\n\n // Track click events\n useEffect(() => {\n if (!config.enabled || !elementRef.current) return;\n\n const element = elementRef.current;\n\n const handleClick = () => {\n setState(prev => ({\n ...prev,\n engagementMetrics: {\n ...prev.engagementMetrics,\n wasClicked: true\n }\n }));\n sendEvent('ad_click');\n };\n\n element.addEventListener('click', handleClick);\n\n return () => {\n element.removeEventListener('click', handleClick);\n };\n }, [config.enabled, elementRef, sendEvent]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n // Calculate session duration\n const now = Date.now();\n const loadTime = new Date(state.timeMetrics.loadedAt).getTime();\n const sessionDuration = now - loadTime;\n\n setState(prev => ({\n ...prev,\n timeMetrics: {\n ...prev.timeMetrics,\n sessionDuration\n }\n }));\n\n // Send final event\n sendEvent('ad_unloaded', { sessionDuration });\n\n // Flush any remaining batched events\n flushBatch();\n };\n }, []);\n\n return state;\n}\n","/**\n * AdMesh Viewability Tracker Component\n * Wraps any ad component with MRC viewability tracking\n */\n\nimport { useRef, useEffect, type CSSProperties, type FC, type ReactNode, type RefObject } from 'react';\nimport { logger } from '../utils/logger';\nimport { useViewabilityTracker } from '../hooks/useViewabilityTracker';\nimport type { ViewabilityTrackerConfig } from '../types/analytics';\n\nexport interface AdMeshViewabilityTrackerProps {\n /** Product ID */\n productId?: string;\n /** Offer ID */\n offerId?: string;\n /** Agent ID */\n agentId?: string;\n /** Recommendation ID (for exposure tracking) */\n recommendationId: string;\n /** Exposure URL (for MRC-compliant exposure pixel firing) */\n exposureUrl?: string;\n /** Session ID (for exposure tracking) */\n sessionId?: string;\n /** Whether to fire exposure URL when ad becomes viewable (defaults to true) */\n triggerExposureUrl?: boolean;\n /** Children to wrap with viewability tracking */\n children: ReactNode;\n /** Custom viewability tracker configuration */\n config?: Partial<ViewabilityTrackerConfig>;\n /** CSS class name */\n className?: string;\n /** Inline styles */\n style?: CSSProperties;\n /** Callback when viewability state changes */\n onViewabilityChange?: (isViewable: boolean) => void;\n /** Callback when ad becomes visible */\n onVisible?: () => void;\n /** Callback when ad becomes viewable (meets MRC threshold) */\n onViewable?: () => void;\n /** Callback when ad is clicked */\n onClick?: () => void;\n}\n\n/**\n * AdMeshViewabilityTracker Component\n * \n * Wraps ad components with comprehensive MRC viewability tracking.\n * Automatically tracks:\n * - Viewability (50% visible for 1 second)\n * - Time metrics (time to viewable, total visible duration, etc.)\n * - Engagement metrics (hover, focus, clicks, scroll depth)\n * - Context metrics (device type, viewport size, ad position)\n * \n * @example\n * ```tsx\n * <AdMeshViewabilityTracker\n * recommendationId=\"rec_123\"\n * productId=\"prod_456\"\n * offerId=\"offer_789\"\n * onViewable={() => logger.log('Ad is viewable!')}\n * >\n * <YourAdComponent />\n * </AdMeshViewabilityTracker>\n * ```\n */\nexport const AdMeshViewabilityTracker: FC<AdMeshViewabilityTrackerProps> = ({\n productId,\n offerId,\n agentId,\n recommendationId,\n exposureUrl,\n sessionId,\n triggerExposureUrl = true,\n children,\n config,\n className,\n style,\n onViewabilityChange,\n onVisible,\n onViewable,\n onClick\n}) => {\n const elementRef = useRef<HTMLElement>(null);\n const exposureFired = useRef(false);\n\n // Use viewability tracker hook\n const viewabilityState = useViewabilityTracker({\n productId,\n offerId,\n agentId,\n recommendationId,\n elementRef: elementRef as RefObject<HTMLElement>,\n config\n });\n\n // Track viewability changes and fire exposure pixel\n const previousViewable = useRef(viewabilityState.isViewable);\n\n useEffect(() => {\n exposureFired.current = false;\n previousViewable.current = false;\n }, [exposureUrl, recommendationId, sessionId]);\n\n useEffect(() => {\n if (viewabilityState.isViewable !== previousViewable.current) {\n previousViewable.current = viewabilityState.isViewable;\n\n if (onViewabilityChange) {\n onViewabilityChange(viewabilityState.isViewable);\n }\n\n if (viewabilityState.isViewable && onViewable) {\n onViewable();\n }\n\n // Fire exposure pixel when ad becomes viewable (MRC-compliant)\n // Only fire if we have the required data and haven't fired yet\n if (viewabilityState.isViewable && !exposureFired.current && triggerExposureUrl) {\n logger.log('[AdMeshViewabilityTracker] 🎯 Ad is viewable, checking exposure pixel requirements:', {\n exposureUrl: exposureUrl ? 'present' : 'MISSING',\n sessionId: sessionId ? 'present' : 'MISSING',\n recommendationId\n });\n\n if (exposureUrl && sessionId) {\n exposureFired.current = true;\n\n logger.log('[AdMeshViewabilityTracker] 🔥 Firing exposure pixel:', exposureUrl);\n\n // Fire the exposure pixel using fetch with keepalive\n fetch(exposureUrl, { method: 'GET', keepalive: true })\n .then(() => {\n logger.log('[AdMesh] ✅ Exposure pixel fired successfully');\n })\n .catch((error) => {\n logger.warn('[AdMesh] ⚠️ Failed to fire exposure pixel:', error);\n // Reset flag to allow retry\n exposureFired.current = false;\n });\n } else {\n logger.warn('[AdMeshViewabilityTracker] ⚠️ Cannot fire exposure pixel - missing required data:', {\n hasExposureUrl: !!exposureUrl,\n hasSessionId: !!sessionId\n });\n }\n }\n }\n }, [viewabilityState.isViewable, onViewabilityChange, onViewable, exposureUrl, sessionId, recommendationId, triggerExposureUrl]);\n\n // Track visibility changes\n const previousVisible = useRef(viewabilityState.isVisible);\n \n useEffect(() => {\n if (viewabilityState.isVisible !== previousVisible.current) {\n previousVisible.current = viewabilityState.isVisible;\n \n if (viewabilityState.isVisible && onVisible) {\n onVisible();\n }\n }\n }, [viewabilityState.isVisible, onVisible]);\n\n // Handle click\n const handleClick = () => {\n if (onClick) {\n onClick();\n }\n \n // Allow event to propagate to children\n };\n\n return (\n <div\n ref={elementRef as RefObject<HTMLDivElement>}\n className={className}\n style={style}\n onClick={handleClick}\n data-admesh-viewability-tracker\n data-recommendation-id={recommendationId}\n data-is-viewable={viewabilityState.isViewable}\n data-is-visible={viewabilityState.isVisible}\n data-visibility-percentage={viewabilityState.visibilityPercentage.toFixed(2)}\n >\n {children}\n </div>\n );\n};\n\nAdMeshViewabilityTracker.displayName = 'AdMeshViewabilityTracker';\n","import { useEffect, useRef, useState, type FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { DelegationActivationPayload } from '../types/index';\nimport { AdMeshViewabilityTracker } from './AdMeshViewabilityTracker';\nimport type { AdMeshTailAdProps } from './AdMeshTailAd';\n\nconst isValidUrl = (url: string): boolean => {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n};\n\nconst getDisplayText = (value: unknown): string => {\n if (typeof value === 'string') {\n return value.trim();\n }\n if (typeof value === 'number') {\n return String(value);\n }\n return '';\n};\n\nconst asOptionalString = (value: unknown): string | undefined => {\n const text = getDisplayText(value);\n return text || undefined;\n};\n\nconst getCTALabel = (ctaLabel?: string): string => {\n if (ctaLabel && ctaLabel.trim()) {\n return ctaLabel.trim();\n }\n return '';\n};\n\nconst formatProductPrice = (price: unknown, currency?: string): string => {\n if (price === null || price === undefined || price === '') {\n return '';\n }\n\n if (typeof price === 'number') {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: 2,\n }).format(price);\n } catch {\n return String(price);\n }\n }\n\n return getDisplayText(price);\n};\n\nexport const AdMeshCompactCard: FC<AdMeshTailAdProps> = ({\n recommendations,\n theme,\n className = '',\n style = {},\n sessionId,\n triggerExposureUrl = true,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n}) => {\n if (!recommendations || recommendations.length === 0) {\n logger.log('[AdMesh Compact Tail Ad] No recommendations provided - not rendering');\n return null;\n }\n\n const firstRecommendation = recommendations[0];\n const recommendation = firstRecommendation?.recommendation;\n const creative = recommendation?.creative;\n const tracking = firstRecommendation?.tracking;\n const delegation = firstRecommendation?.delegation;\n\n const recommendationId = firstRecommendation?.recommendation_id || '';\n const productId = recommendation?.offerId || '';\n const brandName = creative?.brand_name || '';\n const headline = creative?.headline || '';\n const description = creative?.description || '';\n const logoUrl = creative?.logo_url || '';\n const clickUrl = tracking?.click_url || creative?.landing_page_url || '';\n const exposureUrl = tracking?.exposure_url || '';\n const disclosure = recommendation?.disclosure || 'Sponsored';\n const relatedProducts = creative?.products || [];\n const visibleProducts = relatedProducts.slice(0, 4);\n const hasProductRail = relatedProducts.length > 1;\n const recommendationFormat = recommendation?.format || 'tail';\n const isBridgeRecommendation = recommendationFormat === 'bridge';\n const hasDelegation = delegation?.available === true;\n const shouldShowDelegationButton = isBridgeRecommendation && hasDelegation;\n const delegationBrandName = delegation?.brand_name || brandName;\n const delegationCtaText = 'Talk to Agent';\n const ctaLabel = getCTALabel(creative?.cta_text);\n const shouldShowPrimaryCta = !hasProductRail && !!ctaLabel && !!clickUrl;\n\n if (!brandName && !headline && !description) {\n logger.log('[AdMesh Compact Tail Ad] No valid recommendation data provided - not rendering', {\n recommendationId,\n });\n return null;\n }\n\n const compactTitle = headline && headline !== brandName ? headline : brandName;\n const compactSummary = description;\n const normalizedBrandName = brandName.trim().toLowerCase();\n const normalizedCompactTitle = compactTitle.trim().toLowerCase();\n const shouldShowBrandEyebrow = Boolean(brandName) && normalizedBrandName !== normalizedCompactTitle;\n\n const requestDefaultConsent = (): boolean => {\n return true;\n };\n\n const [showConsentPrompt, setShowConsentPrompt] = useState(false);\n const consentResolverRef = useRef<((value: boolean) => void) | null>(null);\n\n useEffect(() => {\n return () => {\n if (consentResolverRef.current) {\n consentResolverRef.current(false);\n consentResolverRef.current = null;\n }\n };\n }, []);\n\n const resolveConsentPrompt = (value: boolean) => {\n consentResolverRef.current?.(value);\n consentResolverRef.current = null;\n setShowConsentPrompt(false);\n };\n\n const requestConsent = async (): Promise<boolean> => {\n if (onDelegationConsent) {\n return await onDelegationConsent(firstRecommendation);\n }\n if (!requestDefaultConsent()) {\n return false;\n }\n return await new Promise<boolean>((resolve) => {\n consentResolverRef.current = resolve;\n setShowConsentPrompt(true);\n });\n };\n\n const handleContainerClick = (source: string, e?: React.MouseEvent) => {\n if (e) {\n e.stopPropagation();\n }\n\n if (typeof window !== 'undefined' && (window as any).admeshTracker) {\n (window as any).admeshTracker.trackClick({\n recommendationId,\n productId,\n clickUrl,\n source,\n }).catch(() => {\n logger.error(`[AdMesh] Failed to track ${source} click`);\n });\n }\n };\n\n const handleCardClick = () => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n handleContainerClick('compact_tail_ad_card');\n if (typeof window !== 'undefined') {\n window.open(clickUrl, '_blank', 'noopener,noreferrer');\n }\n };\n\n const handleCardKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleCardClick();\n }\n };\n\n const trackDelegationEngagement = async () => {\n if (!(recommendationId && sessionId)) {\n return;\n }\n\n try {\n const apiBaseUrl =\n (typeof window !== 'undefined' && (window as any).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n\n const response = await fetch(`${apiBaseUrl}/click/bridge-engagement`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n recommendation_id: recommendationId,\n session_id: sessionId,\n is_test: false,\n }),\n });\n\n if (!response.ok) {\n logger.warn('[AdMesh Compact Tail Ad] Delegation engagement tracking failed:', response.statusText);\n }\n } catch (error) {\n logger.error('[AdMesh Compact Tail Ad] Error tracking delegation engagement:', error);\n }\n };\n\n const handleDelegationClick = async (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (!firstRecommendation || !shouldShowDelegationButton) {\n return;\n }\n\n handleContainerClick('compact_tail_ad_delegation_cta');\n await trackDelegationEngagement();\n\n const consentGranted = await requestConsent();\n if (!consentGranted) {\n return;\n }\n\n const delegationPayload: DelegationActivationPayload | null =\n delegation?.available\n ? {\n recommendation_id: firstRecommendation.recommendation_id,\n brand_id: asOptionalString(delegation.brand_id),\n brand_name: asOptionalString(delegation.brand_name || creative?.brand_name),\n eligibility_reason: asOptionalString(delegation.eligibility_reason),\n delegate_reason: asOptionalString(delegation.delegate_reason),\n session_goal: asOptionalString(delegation.session_goal),\n desired_outcome_type: delegation.desired_outcome_type,\n required_user_inputs: Array.isArray(delegation.required_user_inputs)\n ? delegation.required_user_inputs.filter((value): value is string => typeof value === 'string')\n : [],\n required_consent_types: Array.isArray(delegation.required_consent_types)\n ? delegation.required_consent_types.filter((value): value is string => typeof value === 'string')\n : [],\n success_outcome: asOptionalString(delegation.success_outcome),\n fallback_message: asOptionalString(delegation.fallback_message),\n session_mode: asOptionalString(delegation.session_mode),\n status: asOptionalString(delegation.status),\n capabilities: delegation.capabilities || [],\n allowed_data_types: delegation.allowed_data_types || [],\n consent_requirements: delegation.consent_requirements || [],\n auth_model: asOptionalString(delegation.auth_model),\n handoff_protocol:\n delegation.handoff_protocol && typeof delegation.handoff_protocol === 'object'\n ? delegation.handoff_protocol\n : undefined,\n supported_actions: delegation.supported_actions || [],\n metadata:\n delegation.metadata && typeof delegation.metadata === 'object'\n ? delegation.metadata\n : undefined,\n platform_response: firstRecommendation,\n }\n : null;\n\n if (onDelegationActivated && delegationPayload) {\n await onDelegationActivated(delegationPayload);\n return;\n }\n\n if (onStartDelegation) {\n await onStartDelegation(firstRecommendation);\n return;\n }\n\n };\n\n const [logoError, setLogoError] = useState(false);\n\n const isDarkMode =\n theme?.mode === 'dark' ||\n (typeof window !== 'undefined' &&\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches);\n\n const cardBackground =\n theme?.surfaceColor ||\n theme?.components?.card?.backgroundColor ||\n (isDarkMode ? '#111827' : '#ffffff');\n const cardBorder =\n theme?.borderColor ||\n theme?.components?.card?.borderColor ||\n (isDarkMode ? 'rgba(255, 255, 255, 0.10)' : 'rgba(15, 23, 42, 0.08)');\n const cardShadow =\n theme?.shadows?.medium ||\n theme?.components?.card?.boxShadow ||\n (isDarkMode\n ? '0 8px 18px rgba(0, 0, 0, 0.28)'\n : '0 8px 18px rgba(15, 23, 42, 0.08)');\n const accentColor = '#2563eb';\n const mutedText = isDarkMode ? '#9ca3af' : '#6b7280';\n const bodyText = isDarkMode ? '#e5e7eb' : '#374151';\n const titleText = isDarkMode ? '#f9fafb' : '#0f172a';\n const railCardBackground = isDarkMode ? 'rgba(255, 255, 255, 0.04)' : '#f8fafc';\n const textColumnOffset = '50px';\n const footerAction =\n shouldShowDelegationButton || shouldShowPrimaryCta ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flexWrap: 'wrap' }}>\n {shouldShowDelegationButton ? (\n <button\n type=\"button\"\n onClick={handleDelegationClick}\n style={{\n background: 'none',\n border: 'none',\n padding: 0,\n color: accentColor,\n fontSize: '12px',\n fontWeight: 500,\n cursor: 'pointer',\n textDecoration: 'none',\n }}\n >\n {delegationCtaText}\n </button>\n ) : null}\n {shouldShowPrimaryCta ? (\n <a\n href={clickUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(e) => handleContainerClick('compact_tail_ad_cta', e)}\n style={{\n color: accentColor,\n fontSize: '12px',\n fontWeight: 600,\n textDecoration: 'none',\n }}\n >\n {ctaLabel}\n </a>\n ) : null}\n </div>\n ) : null;\n\n return (\n <AdMeshViewabilityTracker\n productId={productId}\n recommendationId={recommendationId}\n exposureUrl={exposureUrl}\n sessionId={sessionId}\n triggerExposureUrl={triggerExposureUrl}\n className={`admesh-compact-tail-ad ${className}`}\n style={{\n all: 'initial',\n boxSizing: 'border-box',\n display: 'block',\n fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n lineHeight: 1.4,\n ...style,\n }}\n >\n <style>{`\n .admesh-compact-tail-ad,\n .admesh-compact-tail-ad * {\n box-sizing: border-box;\n }\n\n .admesh-compact-line-clamp-1 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 1;\n }\n\n .admesh-compact-line-clamp-2 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n }\n\n .admesh-compact-tail-scroll {\n -ms-overflow-style: none;\n scrollbar-width: none;\n }\n\n .admesh-compact-tail-scroll::-webkit-scrollbar {\n display: none;\n }\n `}</style>\n <div\n role={!hasProductRail && clickUrl ? 'link' : undefined}\n tabIndex={!hasProductRail && clickUrl ? 0 : undefined}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '10px',\n padding: '12px',\n borderRadius: theme?.borderRadius || theme?.components?.card?.borderRadius || '14px',\n border: `1px solid ${cardBorder}`,\n background: cardBackground,\n boxShadow: cardShadow,\n minWidth: 0,\n cursor: !hasProductRail && clickUrl ? 'pointer' : undefined,\n }}\n onClick={handleCardClick}\n onKeyDown={handleCardKeyDown}\n >\n <div style={{ display: 'flex', gap: '10px', alignItems: 'flex-start', minWidth: 0 }}>\n <div\n style={{\n width: '40px',\n height: '40px',\n borderRadius: '10px',\n flexShrink: 0,\n overflow: 'hidden',\n background: isDarkMode ? '#1f2937' : '#eff6ff',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {!logoError && logoUrl && isValidUrl(logoUrl) ? (\n <img\n src={logoUrl}\n alt={`${brandName} logo`}\n style={{\n width: '100%',\n height: '100%',\n objectFit: 'contain',\n padding: '6px',\n background: '#ffffff',\n }}\n onError={() => setLogoError(true)}\n />\n ) : (\n <span style={{ fontSize: '14px', fontWeight: 700, color: mutedText }}>\n {(brandName || 'A').charAt(0).toUpperCase()}\n </span>\n )}\n </div>\n\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n marginBottom: '4px',\n }}\n >\n <div className=\"admesh-compact-line-clamp-1\" style={{ fontSize: '11px', color: mutedText }}>\n {shouldShowBrandEyebrow ? brandName : ''}\n </div>\n <div\n style={{\n flexShrink: 0,\n fontSize: '10px',\n color: mutedText,\n textTransform: 'uppercase',\n letterSpacing: '0.08em',\n }}\n >\n {disclosure}\n </div>\n </div>\n\n {!hasProductRail && (\n <div\n className=\"admesh-compact-line-clamp-2\"\n style={{\n fontSize: '14px',\n lineHeight: 1.3,\n fontWeight: 700,\n color: titleText,\n marginBottom: '4px',\n }}\n title={compactTitle}\n >\n {compactTitle}\n </div>\n )}\n\n {compactSummary && (\n <p\n className=\"admesh-compact-line-clamp-2\"\n style={{\n margin: 0,\n fontSize: '12px',\n lineHeight: 1.35,\n color: bodyText,\n }}\n title={compactSummary}\n >\n {compactSummary}\n </p>\n )}\n </div>\n </div>\n\n {hasProductRail && (\n <div\n className=\"admesh-compact-tail-scroll\"\n style={{\n display: 'flex',\n gap: '8px',\n overflowX: 'auto',\n paddingBottom: '2px',\n }}\n >\n {visibleProducts.map((product) => {\n const productName = getDisplayText(product.product_name) || 'Product';\n const productLink =\n getDisplayText(product.product_link) ||\n getDisplayText(product.product_url) ||\n clickUrl ||\n '#';\n const productPrice = formatProductPrice(product.product_price, product.product_currency);\n const productImageUrl = getDisplayText(product.product_image_url);\n const displayImage = productImageUrl && isValidUrl(productImageUrl) ? productImageUrl : '';\n const hasProductLink = productLink !== '#';\n\n return (\n <a\n key={product.product_id || `${recommendationId}-${productName}`}\n href={productLink}\n target={hasProductLink ? '_blank' : undefined}\n rel={hasProductLink ? 'noopener noreferrer' : undefined}\n onClick={(e) => handleContainerClick(`compact_tail_ad_product_${product.product_id || 'item'}`, e)}\n style={{\n minWidth: '220px',\n maxWidth: '220px',\n display: 'block',\n textDecoration: 'none',\n color: 'inherit',\n border: `1px solid ${cardBorder}`,\n borderRadius: '12px',\n background: railCardBackground,\n padding: '8px',\n flexShrink: 0,\n }}\n >\n <div style={{ display: 'flex', gap: '8px', alignItems: 'flex-start' }}>\n <div\n style={{\n width: '34px',\n height: '34px',\n borderRadius: '8px',\n overflow: 'hidden',\n flexShrink: 0,\n background: isDarkMode ? '#374151' : '#e5e7eb',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: mutedText,\n fontSize: '12px',\n fontWeight: 700,\n }}\n >\n {displayImage ? (\n <img src={displayImage} alt={productName} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />\n ) : (\n productName.charAt(0).toUpperCase()\n )}\n </div>\n\n <div style={{ minWidth: 0, flex: 1 }}>\n <div\n style={{\n fontSize: '12px',\n lineHeight: 1.25,\n fontWeight: 600,\n color: titleText,\n marginBottom: '4px',\n whiteSpace: 'normal',\n wordBreak: 'break-word',\n }}\n title={productName}\n >\n {productName}\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'wrap' }}>\n {productPrice && (\n <span style={{ fontSize: '12px', fontWeight: 700, color: titleText }}>\n {productPrice}\n </span>\n )}\n </div>\n </div>\n </div>\n </a>\n );\n })}\n </div>\n )}\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n flexWrap: 'wrap',\n marginLeft: hasProductRail ? 0 : textColumnOffset,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px', minWidth: 0, flexWrap: 'wrap' }}>\n {footerAction}\n </div>\n\n {hasProductRail && relatedProducts.length > visibleProducts.length ? (\n <span style={{ fontSize: '10px', color: mutedText }}>\n +{relatedProducts.length - visibleProducts.length} more\n </span>\n ) : null}\n </div>\n\n {showConsentPrompt ? (\n <div\n style={{\n marginTop: '2px',\n border: `1px solid ${cardBorder}`,\n borderRadius: '12px',\n background: railCardBackground,\n padding: '12px',\n display: 'flex',\n flexDirection: 'column',\n gap: '10px',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <div\n style={{\n fontSize: '11px',\n fontWeight: 700,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n color: accentColor,\n }}\n >\n Confirm Agent Access\n </div>\n <div style={{ fontSize: '13px', lineHeight: 1.4, color: titleText, fontWeight: 600 }}>\n Allow {delegationBrandName || 'this brand'} to start a delegated session?\n </div>\n <div style={{ fontSize: '12px', lineHeight: 1.45, color: bodyText }}>\n The agent will only use the details you choose to share for this request.\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(false);\n }}\n style={{\n borderRadius: '10px',\n border: `1px solid ${cardBorder}`,\n background: cardBackground,\n color: titleText,\n fontSize: '12px',\n fontWeight: 600,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Not now\n </button>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(true);\n }}\n style={{\n borderRadius: '10px',\n border: 'none',\n background: accentColor,\n color: '#ffffff',\n fontSize: '12px',\n fontWeight: 700,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Allow agent\n </button>\n </div>\n </div>\n ) : null}\n </div>\n </AdMeshViewabilityTracker>\n );\n};\n\nexport default AdMeshCompactCard;\n","import type { FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { AdMeshLayoutProps } from '../types/index';\nimport { AdMeshCompactCard } from './AdMeshCompactCard';\n\nexport const AdMeshLayout: FC<AdMeshLayoutProps> = ({\n recommendations,\n theme,\n className,\n style,\n sessionId,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n}) => {\n const validRecs = recommendations.filter(\n (rec) => rec && typeof rec === 'object' && typeof rec.recommendation_id === 'string' && rec.recommendation_id.length > 0,\n );\n\n // Validate that valid recommendations are provided\n if (!validRecs || validRecs.length === 0) {\n logger.log('[AdMeshLayout] Empty or invalid recommendations array - not rendering anything');\n return null;\n }\n\n logger.log(`[AdMeshLayout] Rendering with ${validRecs.length} valid recommendations`);\n\n // Render based on layout type (default to tail)\n const renderContent = () => {\n if (validRecs.length > 0) {\n const firstRec = validRecs[0];\n const preferredFormat = firstRec.recommendation?.format;\n \n logger.log('[AdMeshLayout] 🔍 Checking format:', {\n preferredFormat,\n recommendationKeys: Object.keys(firstRec || {})\n });\n\n if (preferredFormat === 'product_card' || preferredFormat === 'weave' || preferredFormat === 'bridge') {\n logger.warn(`[AdMeshLayout] ${preferredFormat} format requested, falling back to tail for canonical render payload`);\n }\n }\n\n return (\n <AdMeshCompactCard\n recommendations={validRecs}\n theme={theme}\n sessionId={sessionId}\n onDelegationConsent={onDelegationConsent}\n onDelegationActivated={onDelegationActivated}\n onStartDelegation={onStartDelegation}\n />\n );\n };\n\n return (\n <div\n className={`admesh-layout ${className}`}\n style={{\n fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n ...style\n }}\n >\n {renderContent()}\n </div>\n );\n};\n\nexport default AdMeshLayout;\n","/**\n * AdMesh Tracker\n *\n * Handles MRC-compliant exposure tracking for recommendations\n *\n * MRC Viewability Standards:\n * - Display Ads: 50% of pixels visible for at least 1 continuous second\n * - Large Display Ads (>242,500 pixels): 30% of pixels visible for at least 1 continuous second\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface TrackerConfig {\n apiKey: string;\n debug?: boolean;\n}\n\n/**\n * MRC Viewability threshold configuration\n */\ninterface MRCThreshold {\n visibilityPercentage: number; // 50% for standard ads, 30% for large ads\n minimumDurationMs: number; // 1000ms (1 second)\n}\n\nexport class AdMeshTracker {\n private firedExposures: Set<string> = new Set();\n private debug: boolean = false;\n private mrcThreshold: MRCThreshold = {\n visibilityPercentage: 50,\n minimumDurationMs: 1000\n };\n\n constructor(config: TrackerConfig) {\n this.debug = config.debug || false;\n }\n\n /**\n * Fire an exposure tracking pixel with MRC viewability compliance\n *\n * This method should be called when an ad element becomes viewable according to MRC standards.\n * The caller is responsible for ensuring the ad meets the MRC threshold before calling this method.\n *\n * Prevents duplicate firing for the same ad in the same session.\n *\n * @param exposureUrl - The tracking pixel URL to fire\n * @param recommendationId - The recommendation ID for deduplication\n * @param sessionId - The session ID for deduplication\n */\n fireExposure(exposureUrl: string, recommendationId: string, sessionId: string): void {\n const key = `${sessionId}_${recommendationId}`;\n\n // Prevent duplicate exposures\n if (this.firedExposures.has(key)) {\n if (this.debug) {\n logger.log('[Tracker] Exposure already fired');\n }\n return;\n }\n\n this.firedExposures.add(key);\n\n try {\n // Fire the exposure pixel\n // Note: The caller should ensure MRC compliance before calling this method\n fetch(exposureUrl, { method: 'GET', keepalive: true }).catch(() => {\n if (this.debug) {\n logger.warn('[Tracker] Failed to fire exposure');\n }\n });\n\n if (this.debug) {\n logger.log('[Tracker] Fired MRC-compliant exposure');\n }\n } catch (error) {\n if (this.debug) {\n logger.error('[Tracker] Error firing exposure');\n }\n }\n }\n\n /**\n * Fire an exposure pixel with MRC viewability verification\n *\n * This method monitors an element for MRC viewability compliance before firing the exposure pixel.\n * It uses Intersection Observer API to track visibility and ensures the ad meets the threshold\n * (50% visible for 1 continuous second) before firing.\n *\n * @param exposureUrl - The tracking pixel URL to fire\n * @param recommendationId - The recommendation ID for deduplication\n * @param sessionId - The session ID for deduplication\n * @param element - The DOM element to monitor for viewability\n * @returns Promise that resolves when exposure is fired or timeout occurs\n */\n async fireExposureWithMRCCompliance(\n exposureUrl: string,\n recommendationId: string,\n sessionId: string,\n element: HTMLElement\n ): Promise<void> {\n const key = `${sessionId}_${recommendationId}`;\n\n // Prevent duplicate exposures\n if (this.firedExposures.has(key)) {\n if (this.debug) {\n logger.log('[Tracker] MRC exposure already fired');\n }\n return;\n }\n\n return new Promise((resolve) => {\n let viewableStartTime: number | null = null;\n let timeoutId: NodeJS.Timeout | null = null;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const visibilityPercentage = (entry.intersectionRatio * 100);\n\n if (visibilityPercentage >= this.mrcThreshold.visibilityPercentage) {\n // Ad is visible enough\n if (viewableStartTime === null) {\n // Start tracking viewable duration\n viewableStartTime = Date.now();\n\n if (this.debug) {\n logger.log('[Tracker] Ad reached MRC visibility threshold');\n }\n\n // Set timeout to fire exposure after minimum duration\n timeoutId = setTimeout(() => {\n // Fire the exposure pixel\n this.fireExposure(exposureUrl, recommendationId, sessionId);\n observer.disconnect();\n resolve();\n }, this.mrcThreshold.minimumDurationMs);\n }\n } else {\n // Ad visibility dropped below threshold\n if (viewableStartTime !== null) {\n // Reset tracking\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n viewableStartTime = null;\n\n if (this.debug) {\n logger.log('[Tracker] Ad visibility dropped below MRC threshold');\n }\n }\n }\n });\n },\n {\n threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],\n rootMargin: '0px'\n }\n );\n\n observer.observe(element);\n\n // Cleanup on unmount or after reasonable timeout\n const maxWaitTime = 30000; // 30 seconds max wait\n const cleanupTimeout = setTimeout(() => {\n observer.disconnect();\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n resolve();\n }, maxWaitTime);\n\n // Store cleanup function for manual cleanup if needed\n (element as any).__admeshTrackerCleanup = () => {\n observer.disconnect();\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n clearTimeout(cleanupTimeout);\n };\n });\n }\n\n /**\n * Clear fired exposures (useful for testing or session reset)\n */\n clearFiredExposures(): void {\n this.firedExposures.clear();\n }\n\n /**\n * Get MRC threshold configuration\n */\n getMRCThreshold(): MRCThreshold {\n return { ...this.mrcThreshold };\n }\n\n /**\n * Set custom MRC threshold (for testing or special cases)\n */\n setMRCThreshold(threshold: Partial<MRCThreshold>): void {\n this.mrcThreshold = {\n ...this.mrcThreshold,\n ...threshold\n };\n }\n\n /**\n * Fire exposure pixel for sponsored followup\n * Uses same logic as regular exposure tracking\n * \n * @param exposureUrl - The tracking pixel URL to fire (can use regular exposure_url)\n * @param recommendationId - The recommendation ID for deduplication\n * @param sessionId - The session ID for deduplication\n */\n fireFollowupExposure(\n exposureUrl: string,\n recommendationId: string,\n sessionId: string\n ): void {\n // Reuse existing fireExposure() method\n this.fireExposure(exposureUrl, recommendationId, sessionId);\n }\n\n /**\n * Fire engagement tracking for sponsored followup\n * \n * @param engagementUrl - The engagement tracking URL to fire\n * @param recommendationId - The recommendation ID\n * @param sessionId - The session ID (sent in POST body for analytics joining)\n * @returns Promise that resolves when engagement is fired\n */\n fireFollowupEngagement(\n engagementUrl: string,\n _recommendationId: string,\n sessionId: string\n ): Promise<void> {\n // Use fetch with keepalive and POST method\n // Always resolve the promise even on error to prevent unhandled rejections\n return fetch(engagementUrl, {\n method: 'POST',\n keepalive: true,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ session_id: sessionId })\n }).catch((error) => {\n // Log error silently (only in debug mode) - network errors are expected and shouldn't break the flow\n if (this.debug) {\n logger.warn('[Tracker] Failed to fire followup engagement (non-critical):', error);\n }\n // Return undefined to resolve the promise successfully\n // This prevents the error from propagating to callers\n return undefined;\n }).then(() => {\n // Ensure promise always resolves with void (no return value)\n // This makes the return type consistent: Promise<void>\n });\n }\n}\n","import { createContext, useContext } from 'react';\nimport { AdMeshSDK } from '../sdk/AdMeshSDK';\nimport type { AdMeshTheme, PlatformResponse, ActiveDelegationSession } from '../types/index';\nimport type { Suggestion } from '../components/AdMeshIntentAssistant';\n\n/**\n * Context value provided by AdMeshProvider\n */\nexport interface AdMeshContextValue {\n // SDK instance\n sdk: AdMeshSDK | null;\n\n // Configuration\n apiKey: string;\n sessionId: string;\n theme?: AdMeshTheme;\n\n // Canonical AIP PlatformRequest inputs (optional, passed from frontend)\n language?: string; // User language in BCP 47 format (e.g., \"en-US\")\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string; // Anonymous hashed user ID\n model?: string; // AI model identifier (e.g., \"gpt-4o\")\n messages?: Array<{ role: string; content: string; id?: string }>; // Conversation history\n\n // Tracking state\n processedMessageIds: Set<string>;\n recommendationResults: Map<string, PlatformResponse | null>;\n activeDelegationSession: ActiveDelegationSession | null;\n\n // Suggestion state\n suggestions: Suggestion[];\n isAnalyzingIntent: boolean;\n intentError: string | null;\n\n // Methods\n markMessageAsProcessed: (messageId: string) => void;\n isMessageProcessed: (messageId: string) => boolean;\n setRecommendationResult: (messageId: string, result: PlatformResponse | null) => void;\n getRecommendationResult: (messageId: string) => PlatformResponse | null | undefined;\n hasRecommendationResult: (messageId: string) => boolean;\n setActiveDelegationSession: (session: ActiveDelegationSession | null) => void;\n getActiveDelegationSession: () => ActiveDelegationSession | null;\n hasActiveDelegationSession: () => boolean;\n refreshDelegationActivity: (eventType?: string, metadata?: Record<string, unknown>) => Promise<void>;\n stopDelegationSession: (reason?: string, metadata?: Record<string, unknown>) => Promise<void>;\n retryIntentAnalysis: () => Promise<void>;\n}\n\n/**\n * React Context for AdMesh SDK\n * \n * Provides SDK instance and tracking state to all child components\n */\nexport const AdMeshContext = createContext<AdMeshContextValue | undefined>(\n undefined\n);\n\n/**\n * Hook to access AdMesh context\n * \n * @throws Error if used outside of AdMeshProvider\n * @returns AdMeshContextValue\n */\nexport function useAdMeshContext(): AdMeshContextValue {\n const context = useContext(AdMeshContext);\n \n if (!context) {\n throw new Error(\n 'useAdMeshContext must be used within an <AdMeshProvider>. ' +\n 'Make sure your component is wrapped with <AdMeshProvider>.'\n );\n }\n \n return context;\n}\n","/**\n * Extract headings directly from web pages without external scripts\n * This utility function can be used by anyone who integrates the AdMesh UI SDK\n */\n\nexport interface HeadingsExtractionResult {\n title: string;\n headings: string[];\n article_text?: string;\n url: string;\n domain: string;\n extracted_at: string;\n}\n\nfunction titleFromPath(pathname: string): string {\n const segments = pathname.split('/').filter(Boolean);\n const raw = segments[segments.length - 1] || segments[segments.length - 2] || '';\n const withoutExtension = raw.replace(/\\.[a-z0-9]+$/i, '');\n const cleaned = withoutExtension.replace(/[-_]+/g, ' ').replace(/\\s+/g, ' ').trim();\n return cleaned\n ? cleaned.replace(/\\b\\w/g, (char) => char.toUpperCase())\n : 'This page';\n}\n\n/**\n * Extract headings directly from the current web page\n * Bypasses CSP restrictions by using direct DOM access\n * \n * @returns {HeadingsExtractionResult | null} Object containing title, headings, and metadata\n */\nexport function extractHeadingsDirectly(): HeadingsExtractionResult | null {\n try {\n console.log('[AdMesh] Starting direct headings extraction...');\n \n // Clean and normalize text content\n const cleanText = (text: string) => text.replace(/\\s+/g, \" \").trim();\n\n const getArticleText = () => {\n const selectors = [\n 'article',\n 'main article',\n 'main',\n '[role=\"main\"]',\n '[data-admesh-article]',\n '.article-content',\n '.post-content',\n '.entry-content',\n '.content',\n ];\n\n const ignoredSelector = [\n 'script',\n 'style',\n 'noscript',\n 'svg',\n 'canvas',\n 'iframe',\n 'nav',\n 'header',\n 'footer',\n 'aside',\n '[aria-hidden=\"true\"]',\n '[data-admesh-ignore]',\n '.admesh-publisher-assistant-root',\n '.admesh-publisher-assistant-reactMount',\n '.admesh-publisher-assistant-floating',\n '.admesh-publisher-assistant-inline',\n ].join(',');\n\n const candidates = selectors\n .map((selector) => document.querySelector(selector))\n .filter((element): element is Element => Boolean(element));\n\n const sourceElement = candidates\n .map((element) => {\n const clone = element.cloneNode(true) as Element;\n clone.querySelectorAll(ignoredSelector).forEach((node) => node.remove());\n const text = cleanText(clone.textContent || '');\n return { element, text };\n })\n .filter((candidate) => candidate.text.length >= 200)\n .sort((a, b) => b.text.length - a.text.length)[0]?.element || document.body;\n\n const clone = sourceElement.cloneNode(true) as Element;\n clone.querySelectorAll(ignoredSelector).forEach((node) => node.remove());\n\n const paragraphs = Array.from(clone.querySelectorAll('h1, h2, h3, p, li, blockquote'))\n .map((element) => cleanText(element.textContent || ''))\n .filter((text) => text.length >= 24);\n\n const articleText = paragraphs.length > 0\n ? paragraphs.join('\\n')\n : cleanText(clone.textContent || '');\n\n return articleText.slice(0, 6000);\n };\n \n const fallbackTitle = titleFromPath(window.location.pathname || '/');\n \n // Extract title\n const title = cleanText(document.title || '') || fallbackTitle;\n \n // Extract all headings by selector and combine into single array\n const getAllHeadings = () => {\n const allHeadings: string[] = [];\n \n // Get all heading elements (h1 through h6)\n const headingElements = document.querySelectorAll('h1, h2, h3, h4, h5, h6');\n \n // Convert NodeList to array and extract text\n Array.from(headingElements).forEach(element => {\n const text = cleanText(element.textContent || '');\n if (text.length > 0) {\n allHeadings.push(text);\n }\n });\n \n return allHeadings;\n };\n \n // Extract all headings in desired format\n const headings = getAllHeadings();\n const resolvedHeadings = headings.length > 0 ? headings : [title || fallbackTitle];\n \n // Create the simplified output format\n const result: HeadingsExtractionResult = {\n title: title,\n headings: resolvedHeadings,\n article_text: getArticleText(),\n url: window.location.href,\n domain: window.location.hostname,\n extracted_at: new Date().toISOString()\n };\n \n console.log('[AdMesh] Extracted headings:', {\n title: result.title,\n headingsCount: result.headings.length,\n articleTextLength: result.article_text?.length || 0,\n domain: result.domain\n });\n \n return result;\n } catch (error) {\n console.error('[AdMesh] Error in direct headings extraction:', error);\n return null;\n }\n}\n","/**\n * ACIE (AdMesh Commercial Intent Engine) API integration\n * Provides intent analysis functionality for the AdMesh UI SDK\n */\n\nimport type { AdMeshSDKConfig } from '../sdk/AdMeshSDK';\nimport type { Suggestion } from '../components/AdMeshIntentAssistant';\nimport type { PlatformResponse } from '../types/index';\n\nexport interface CommercialIntentRequest {\n url: string;\n title?: string;\n headings?: string[];\n article_text?: string;\n domain: string;\n article_slug?: string;\n agent_id?: string;\n cpx_floor?: number;\n source: string;\n api_key: string;\n user_id?: string;\n}\n\nexport interface CommercialIntentResult {\n url: string;\n domain: string;\n suggestions: Suggestion[];\n}\n\ntype AcieRecommendationProduct = {\n product_id?: string;\n product_link?: string;\n product_click_url?: string;\n product_name?: string;\n product_description?: string;\n product_price?: string | number | null;\n product_discount?: string | number | null;\n product_currency?: string;\n product_discount_type?: string;\n product_cta_label?: string;\n product_image_url?: string;\n product_features?: string[];\n};\n\ntype AcieRecommendationPayload = {\n recommendation_id?: string;\n title?: string;\n url?: string;\n click_url?: string;\n exposure_url?: string;\n follow_up_suggestion?: string;\n followup_engagement_url?: string;\n followup_exposure_url?: string;\n preferred_format?: string;\n products?: AcieRecommendationProduct[];\n creative_input?: {\n brand_name?: string;\n product_name?: string;\n short_description?: string;\n long_description?: string;\n cta_label?: string;\n cta_url?: string;\n assets?: {\n image_urls?: string[];\n logo_url?: string;\n };\n };\n};\n\nfunction isPlatformResponse(value: unknown): value is PlatformResponse {\n return Boolean(\n value &&\n typeof value === 'object' &&\n 'recommendation_id' in value &&\n 'status' in value\n );\n}\n\nfunction normalizeAcieRecommendation(value: unknown): PlatformResponse | undefined {\n if (!value || typeof value !== 'object') {\n return undefined;\n }\n\n if (isPlatformResponse(value)) {\n return value;\n }\n\n const recommendation = value as AcieRecommendationPayload;\n if (!recommendation.recommendation_id) {\n return undefined;\n }\n\n const products = (recommendation.products || []).map((product) => ({\n product_id: product.product_id || '',\n product_link: product.product_link || product.product_click_url || recommendation.click_url || recommendation.url || '',\n product_name: product.product_name || recommendation.title || recommendation.creative_input?.product_name || '',\n product_description: product.product_description || '',\n product_price: product.product_price ?? undefined,\n product_discount: product.product_discount ?? undefined,\n product_currency: product.product_currency,\n product_discount_type: product.product_discount_type,\n product_cta_label: product.product_cta_label || recommendation.creative_input?.cta_label,\n product_image_url: product.product_image_url,\n product_features: product.product_features,\n }));\n\n return {\n spec_version: '1.0',\n recommendation_id: recommendation.recommendation_id,\n timestamp: new Date().toISOString(),\n status: 'generated',\n ttl_ms: 300000,\n recommendation: {\n format: (recommendation.preferred_format as NonNullable<PlatformResponse['recommendation']>['format']) || 'tail',\n disclosure: 'Sponsored',\n creative: {\n brand_name: recommendation.creative_input?.brand_name || '',\n headline: recommendation.title || recommendation.creative_input?.product_name || '',\n description:\n recommendation.creative_input?.short_description ||\n recommendation.creative_input?.long_description ||\n '',\n cta_text: recommendation.creative_input?.cta_label || products[0]?.product_cta_label || 'Learn more',\n follow_up_suggestion: recommendation.follow_up_suggestion,\n logo_url: recommendation.creative_input?.assets?.logo_url,\n image_urls: recommendation.creative_input?.assets?.image_urls || [],\n landing_page_url: recommendation.url || recommendation.click_url || recommendation.creative_input?.cta_url || '',\n products,\n },\n },\n tracking: {\n exposure_url: recommendation.exposure_url,\n click_url: recommendation.click_url,\n followup_exposure_url: recommendation.followup_exposure_url,\n followup_engagement_url: recommendation.followup_engagement_url,\n },\n };\n}\n\nfunction normalizeCommercialIntentResult(result: CommercialIntentResult): CommercialIntentResult {\n return {\n ...result,\n suggestions: (result.suggestions || []).map((suggestion) => ({\n ...suggestion,\n recommendation: normalizeAcieRecommendation(suggestion.recommendation),\n })),\n };\n}\n\n/**\n * Extract article slug from URL for publisher API keys\n */\nfunction extractArticleSlug(url: string): string | undefined {\n try {\n const urlObj = new URL(url);\n const pathSegments = urlObj.pathname.split('/').filter(segment => segment.length > 0);\n const articleSlug = pathSegments[pathSegments.length - 1];\n return articleSlug || undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Call ACIE analyze-intent endpoint to analyze commercial intent of a page\n * \n * @param headingsData - Page data including title, headings, URL, and domain\n * @param config - AdMesh SDK configuration containing API base URL and API key\n * @returns Promise<CommercialIntentResult | null> - Intent analysis results or null on error\n */\nexport async function callAnalyzeIntentEndpoint(\n headingsData: {\n url: string;\n title?: string;\n headings?: string[];\n article_text?: string;\n domain: string;\n },\n config: AdMeshSDKConfig\n): Promise<CommercialIntentResult | null> {\n try {\n console.log('[AdMesh SDK] Starting ACIE analyze-intent call...', { url: headingsData.url });\n \n // Combine all headings into content for analysis\n const allHeadings = Array.isArray(headingsData.headings) ? headingsData.headings : [];\n const pathTopic = extractArticleSlug(headingsData.url)\n ?.replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n const fallbackHeading = pathTopic\n ? pathTopic.replace(/\\b\\w/g, (char) => char.toUpperCase())\n : undefined;\n \n // Extract article slug for publisher API keys\n const articleSlug = config.apiKey.toLowerCase().startsWith('pub_') \n ? extractArticleSlug(headingsData.url)\n : undefined;\n\n const normalizedSource = config.extension ? 'extension' : 'admesh_ui_sdk';\n const normalizedDomain = (\n headingsData.domain ||\n (typeof window !== 'undefined' ? window.location.hostname : '')\n ).trim().toLowerCase();\n \n // Prepare request payload matching CommercialIntentRequest model\n const payload: CommercialIntentRequest = {\n url: headingsData.url,\n title: headingsData.title || undefined,\n headings: allHeadings.length > 0 ? allHeadings : fallbackHeading ? [fallbackHeading] : undefined,\n article_text: headingsData.article_text?.trim() || undefined,\n domain: normalizedDomain,\n article_slug: articleSlug,\n agent_id: undefined, // Optional - can be added later if needed\n cpx_floor: undefined, // Optional - can be added later if needed\n source: normalizedSource,\n api_key: config.apiKey, // Add API key from config\n user_id: config.userId || undefined\n };\n \n console.log('[AdMesh SDK] Payload prepared:', {\n url: payload.url,\n titleLength: payload.title?.length || 0,\n headingsCount: payload.headings?.length || 0,\n articleTextLength: payload.article_text?.length || 0,\n domain: payload.domain,\n article_slug: payload.article_slug,\n source: payload.source,\n has_user_id: !!payload.user_id\n });\n \n const apiUrl = `${config.apiBaseUrl}/acie/analyze-intent`;\n console.log('[AdMesh SDK] Calling ACIE API:', apiUrl);\n \n // Make API call to ACIE endpoint\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`\n },\n body: JSON.stringify(payload)\n });\n \n console.log('[AdMesh SDK] ACIE API response received:', {\n status: response.status,\n statusText: response.statusText,\n ok: response.ok\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n console.error('[AdMesh SDK] ACIE API error:', {\n status: response.status,\n statusText: response.statusText,\n errorText: errorText\n });\n throw new Error(`ACIE API error: ${response.status} - ${errorText}`);\n }\n \n const rawAnalysisResult = await response.json();\n const analysisResult = normalizeCommercialIntentResult(rawAnalysisResult as CommercialIntentResult);\n \n console.log('[AdMesh SDK] ACIE analysis completed:', {\n url: headingsData.url,\n suggestionsCount: analysisResult.suggestions.length\n });\n \n // Return the analysis result\n return analysisResult;\n \n } catch (err) {\n console.error('[AdMesh SDK] Error calling ACIE analyze-intent endpoint:', err);\n return null;\n }\n}\n","/**\n * Fetch virtual page context for GAM/Xandr ad-slot creatives.\n */\n\nimport type { HeadingsExtractionResult } from './extractHeadings';\n\nexport type PageContextSource = 'cache' | 'index' | 'httpx' | 'firecrawl' | 'degraded';\n\nexport interface PageContextApiConfig {\n apiKey: string;\n apiBaseUrl: string;\n agentDisplayId?: string;\n publisherId?: string;\n}\n\nexport interface PageContextResponse {\n context: HeadingsExtractionResult & { degraded?: boolean };\n source: PageContextSource;\n cache_hit: boolean;\n}\n\nexport async function fetchPageContext(\n url: string,\n config: PageContextApiConfig,\n): Promise<PageContextResponse> {\n const base = (config.apiBaseUrl || 'https://api.useadmesh.com').replace(/\\/$/, '');\n const params = new URLSearchParams({ url: url.trim() });\n if (config.agentDisplayId?.trim()) {\n params.set('agent_display_id', config.agentDisplayId.trim());\n }\n if (config.publisherId?.trim()) {\n params.set('publisher_id', config.publisherId.trim());\n }\n\n const response = await fetch(`${base}/publisher-assistant/page-context?${params.toString()}`, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new Error(`Page context request failed (${response.status}): ${body || response.statusText}`);\n }\n\n return (await response.json()) as PageContextResponse;\n}\n","'use client';\n\nimport { useEffect, useState, useCallback, useRef, type ReactNode, type FC } from 'react';\nimport { logger } from '../utils/logger';\nimport { AdMeshSDK } from '../sdk/AdMeshSDK';\nimport { AdMeshContext, type AdMeshContextValue } from './AdMeshContext';\nimport type { AdMeshTheme, PlatformResponse, ActiveDelegationSession } from '../types/index';\nimport { extractHeadingsDirectly, type HeadingsExtractionResult } from '../utils/extractHeadings';\nimport { callAnalyzeIntentEndpoint } from '../utils/acieApi';\nimport { fetchPageContext } from '../utils/pageContextApi';\nimport type { Suggestion } from '../components/AdMeshIntentAssistant';\n\nexport type PageContextMode = 'page' | 'ad-slot' | 'auto';\n\nfunction isInIframe(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n try {\n return window.self !== window.top;\n } catch {\n return true;\n }\n}\n\nfunction getUsableWindowHref(): string | null {\n if (typeof window === 'undefined') {\n return null;\n }\n try {\n const href = window.location.href?.trim();\n if (isResolvedArticleUrl(href)) {\n return href;\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction isResolvedArticleUrl(value?: string): boolean {\n const trimmed = value?.trim();\n if (!trimmed || /%%[^%]+%%/.test(trimmed)) {\n return false;\n }\n try {\n const parsed = new URL(trimmed);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nfunction titleFromUrlPath(url: string): string {\n try {\n const parsed = new URL(url);\n const segments = parsed.pathname.split('/').filter(Boolean);\n const raw = segments[segments.length - 1] || segments[segments.length - 2] || parsed.hostname;\n const cleaned = raw\n .replace(/\\.[a-z0-9]+$/i, '')\n .replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n return cleaned ? cleaned.replace(/\\b\\w/g, (char) => char.toUpperCase()) : parsed.hostname;\n } catch {\n return 'This page';\n }\n}\n\nfunction buildUrlFallbackContext(url: string): HeadingsExtractionResult {\n const parsed = new URL(url);\n const title = titleFromUrlPath(url);\n return {\n title,\n headings: [title],\n article_text: `Article URL: ${url}\\nArticle topic inferred from URL path: ${title}`,\n url,\n domain: parsed.hostname,\n extracted_at: new Date().toISOString(),\n };\n}\n\nfunction resolveArticleUrlForContext(articleUrl?: string): string | null {\n const currentHref = getUsableWindowHref();\n if (currentHref) {\n return currentHref;\n }\n const trimmed = articleUrl?.trim();\n if (isResolvedArticleUrl(trimmed)) {\n return trimmed;\n }\n return null;\n}\n\nexport interface AdMeshProviderProps {\n /** AdMesh API key (required) */\n apiKey: string;\n\n /** Session ID (required) */\n sessionId: string;\n\n /** Optional: Whether this provider is being used by the extension (optional) */\n extension?: boolean;\n\n /** Optional theme configuration */\n theme?: AdMeshTheme;\n\n /** Optional API base URL (defaults to production) */\n apiBaseUrl?: string;\n\n /** Optional user language in BCP 47 format (e.g., \"en-US\") */\n language?: string;\n\n /** Optional detailed user location */\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n\n /** Optional anonymous hashed user ID */\n userId?: string;\n\n /** Optional AI model identifier (e.g., \"gpt-4o\") - forwarded as platform software version metadata */\n model?: string;\n\n /** Optional conversation history - forwarded in classification_input.interaction.input.messages */\n messages?: Array<{ role: string; content: string; id?: string }>;\n\n /** Pre-resolved page context (skips client/server extract) */\n pageContext?: HeadingsExtractionResult | null;\n\n /** Article URL for ad-slot / GAM (e.g. %%PAGE_URL%% macro) */\n articleUrl?: string;\n\n /** How to obtain page context: page DOM, ad-slot API, or auto-detect iframe */\n contextMode?: PageContextMode;\n\n /** Agent display id for optional content-index lookup */\n agentDisplayId?: string;\n\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * AdMeshProvider - Simplified SDK integration for React applications\n *\n * Handles:\n * - SDK initialization and lifecycle management\n * - Message deduplication tracking\n * - Session and message ID management\n * - Error handling and logging\n *\n * @example\n * ```tsx\n * <AdMeshProvider\n * apiKey={process.env.NEXT_PUBLIC_ADMESH_API_KEY}\n * sessionId=\"custom-session-id\"\n * >\n * <Chat messages={messages} />\n * </AdMeshProvider>\n * \n * // Extension usage (skips intent analysis)\n * <AdMeshProvider \n * apiKey=\"pub_extension_key\"\n * sessionId=\"extension-session-id\"\n * extension={true}\n * >\n * <AdMeshIntentAssistant autoOpen={true} />\n * </AdMeshProvider>\n * ```\n */\nexport const AdMeshProvider: FC<AdMeshProviderProps> = ({\n apiKey,\n sessionId,\n extension,\n theme,\n apiBaseUrl,\n language,\n location,\n userId,\n model,\n messages,\n pageContext,\n articleUrl,\n contextMode = 'auto',\n agentDisplayId,\n children,\n}) => {\n const [sdk, setSdk] = useState<AdMeshSDK | null>(null);\n const [processedMessageIds, setProcessedMessageIds] = useState<Set<string>>(\n new Set()\n );\n const [recommendationResults, setRecommendationResults] = useState<\n Map<string, PlatformResponse | null>\n >(new Map());\n const [activeDelegationSession, setActiveDelegationSessionState] = useState<ActiveDelegationSession | null>(null);\n\n // Suggestion state\n const [suggestions, setSuggestions] = useState<Suggestion[]>([]);\n const [isAnalyzingIntent, setIsAnalyzingIntent] = useState(false);\n const [intentError, setIntentError] = useState<string | null>(null);\n const [isResolvingPageContext, setIsResolvingPageContext] = useState(false);\n const hasAttemptedInitialAnalysisRef = useRef(false);\n\n const usesAdSlotContext =\n Boolean(pageContext) ||\n contextMode === 'ad-slot' ||\n (contextMode === 'auto' && (Boolean(articleUrl?.trim()) || isInIframe()));\n\n const resolveHeadingsForAnalysis = useCallback(async (): Promise<HeadingsExtractionResult | null> => {\n if (pageContext) {\n return pageContext;\n }\n\n if (!usesAdSlotContext) {\n return extractHeadingsDirectly();\n }\n\n const targetUrl = resolveArticleUrlForContext(articleUrl);\n if (!targetUrl) {\n logger.warn('[AdMeshProvider] Ad-slot context mode requires a real article URL');\n setIntentError('Article URL is required for ad-slot context');\n return null;\n }\n\n if (!apiKey || !apiBaseUrl) {\n logger.warn('[AdMeshProvider] Cannot fetch page context: missing API key or base URL');\n return buildUrlFallbackContext(targetUrl);\n }\n\n try {\n setIsResolvingPageContext(true);\n const response = await fetchPageContext(targetUrl, {\n apiKey,\n apiBaseUrl: apiBaseUrl || 'https://api.useadmesh.com',\n agentDisplayId,\n });\n logger.log('[AdMeshProvider] Page context resolved', {\n source: response.source,\n cache_hit: response.cache_hit,\n domain: response.context.domain,\n });\n return response.context;\n } catch (error) {\n logger.error('[AdMeshProvider] Failed to fetch page context:', error);\n logger.warn('[AdMeshProvider] Falling back to URL-path context for suggestions');\n return buildUrlFallbackContext(targetUrl);\n } finally {\n setIsResolvingPageContext(false);\n }\n }, [\n agentDisplayId,\n apiBaseUrl,\n apiKey,\n articleUrl,\n pageContext,\n usesAdSlotContext,\n ]);\n\n const prependSponsoredSuggestion = useCallback(\n (currentSuggestions: Suggestion[], sponsoredSuggestion: Suggestion): Suggestion[] => {\n const organicSuggestions = currentSuggestions.filter((suggestion) => !suggestion.is_sponsored).slice(0, 3);\n return [sponsoredSuggestion, ...organicSuggestions];\n },\n [],\n );\n\n const mergeOrganicSuggestions = useCallback((currentSuggestions: Suggestion[], organicSuggestions: Suggestion[]) => {\n const sponsoredSuggestion = currentSuggestions.find((suggestion) => suggestion.is_sponsored);\n const nextOrganicSuggestions = organicSuggestions.filter((suggestion) => !suggestion.is_sponsored).slice(0, 3);\n return sponsoredSuggestion ? [sponsoredSuggestion, ...nextOrganicSuggestions] : nextOrganicSuggestions;\n }, []);\n\n // Validate that sessionId is provided by platform\n useEffect(() => {\n if (!sessionId || sessionId.trim() === '') {\n logger.error('[AdMeshProvider] ❌ sessionId is required and must be provided by the platform. Use AdMeshSDK.generateSessionIdFromUrl() for URL-based detection.');\n return;\n }\n \n logger.log('[AdMeshProvider] ✅ Session ID available:', sessionId);\n }, [sessionId]);\n\n // Initialize SDK once on mount\n useEffect(() => {\n if (!apiKey) {\n logger.warn('[AdMeshProvider] ⚠️ AdMesh API key not configured');\n return;\n }\n\n if (!sessionId || sessionId.trim() === '') {\n logger.error('[AdMeshProvider] ❌ Cannot initialize SDK: sessionId is required. Use AdMeshSDK.generateSessionIdFromUrl() for URL-based detection.');\n return;\n }\n\n try {\n const sdkInstance = new AdMeshSDK({\n apiKey,\n theme,\n apiBaseUrl,\n extension,\n });\n setSdk(sdkInstance);\n logger.log('[AdMeshProvider] ✅ AdMesh SDK initialized with session:', sessionId);\n if (apiBaseUrl) {\n logger.log('[AdMeshProvider] 📍 Using custom API base URL');\n }\n } catch (error) {\n logger.error('[AdMeshProvider] ❌ Failed to initialize AdMesh SDK:', error);\n }\n\n // Cleanup on unmount\n return () => {\n logger.log('[AdMeshProvider] 🧹 Provider unmounted');\n };\n }, [apiKey, theme, apiBaseUrl, sessionId, extension]);\n\n // Intent analysis function\n const performIntentAnalysis = useCallback(async (prefetchedHeadingsData?: HeadingsExtractionResult | null) => {\n if (!apiKey || !apiBaseUrl) {\n logger.warn('[AdMeshProvider] ⚠️ Cannot perform intent analysis: missing API key or base URL');\n return;\n }\n\n // Skip intent analysis if called from extension\n if (extension) {\n logger.log('[AdMeshProvider] ℹ️ Extension mode: allowing intent analysis for any API key');\n // Don't return - continue to intent analysis for extension\n } else {\n // For non-extension usage, only allow pub_ API keys\n if (!apiKey.toLowerCase().startsWith('pub_')) {\n logger.log('[AdMeshProvider] ℹ️ Skipping auto intent analysis: API key does not start with \"pub_\"');\n return;\n }\n }\n\n try {\n setIsAnalyzingIntent(true);\n setIntentError(null);\n \n logger.log('[AdMeshProvider] 🔄 Starting automatic intent analysis...');\n \n const headingsData = prefetchedHeadingsData ?? (await resolveHeadingsForAnalysis());\n if (!headingsData) {\n logger.warn('[AdMeshProvider] ⚠️ Failed to extract headings for intent analysis');\n setIntentError('Failed to extract page content');\n return;\n }\n \n logger.log('[AdMeshProvider] 📄 Extracted headings:', {\n title: headingsData.title,\n headingsCount: headingsData.headings.length,\n articleTextLength: headingsData.article_text?.length || 0,\n domain: headingsData.domain\n });\n \n // Call ACIE API for intent analysis\n const config = {\n apiKey,\n apiBaseUrl: apiBaseUrl || 'https://api.useadmesh.com',\n extension,\n userId\n };\n \n const analysisResult = await callAnalyzeIntentEndpoint(headingsData, config);\n \n if (analysisResult) {\n logger.log('[AdMeshProvider] ✅ Intent analysis completed:', {\n suggestionsCount: analysisResult.suggestions.length,\n suggestions: (analysisResult.suggestions || []).map((suggestion) => ({\n id: suggestion.id,\n text: suggestion.text,\n is_sponsored: suggestion.is_sponsored,\n recommendationId: suggestion.recommendation?.recommendation_id || null,\n })),\n });\n \n setSuggestions((currentSuggestions) =>\n mergeOrganicSuggestions(currentSuggestions, analysisResult.suggestions || [])\n );\n } else {\n logger.warn('[AdMeshProvider] ⚠️ Intent analysis returned null');\n setIntentError('Intent analysis failed');\n setSuggestions((current) => {\n if (current.length > 0) {\n logger.log('[AdMeshProvider] ℹ️ Preserving existing suggestions after null intent analysis result');\n return current;\n }\n return [\n {\n id: \"fallback-1\",\n text: \"What are your questions about this content?\",\n type: \"information\" as const,\n is_sponsored: false,\n recommendation: undefined,\n }\n ];\n });\n }\n } catch (error) {\n logger.error('[AdMeshProvider] ❌ Error in intent analysis:', error);\n setIntentError('Intent analysis error');\n setSuggestions((current) => {\n if (current.length > 0) {\n logger.log('[AdMeshProvider] ℹ️ Preserving existing suggestions after intent analysis error');\n return current;\n }\n return [\n {\n id: \"error-fallback-1\",\n text: \"Ask me questions about this page\",\n type: \"information\" as const,\n is_sponsored: false,\n recommendation: undefined,\n }\n ];\n });\n } finally {\n setIsAnalyzingIntent(false);\n }\n }, [apiKey, apiBaseUrl, extension, userId, mergeOrganicSuggestions, resolveHeadingsForAnalysis]);\n\n const prefetchSponsoredSuggestion = useCallback(\n async (prefetchedHeadingsData?: HeadingsExtractionResult | null) => {\n if (!sdk || !apiKey) {\n return;\n }\n\n if (!apiKey.toLowerCase().startsWith('pub_')) {\n return;\n }\n\n const headingsData = prefetchedHeadingsData ?? (await resolveHeadingsForAnalysis());\n if (!headingsData) {\n logger.warn('[AdMeshProvider] ⚠️ Failed to extract page content for sponsored suggestion prefetch');\n return;\n }\n\n const query = headingsData.headings?.[0]?.trim() || headingsData.title?.trim();\n if (!query) {\n logger.warn('[AdMeshProvider] ⚠️ Skipping sponsored suggestion prefetch: no usable page query');\n return;\n }\n\n try {\n logger.log('[AdMeshProvider] 🔄 Prefetching sponsored suggestion from /aip/context...');\n const platformResult = await sdk.fetchPlatformResponse({\n query,\n sessionId,\n messageId: AdMeshSDK.createMessageId(sessionId),\n platformSurface: 'embedded_assistant',\n model,\n messages: [],\n language,\n location,\n userId,\n });\n\n const suggestionText = platformResult.recommendation?.creative?.follow_up_suggestion?.trim();\n const recommendationId = platformResult.recommendation_id;\n if (!suggestionText || !recommendationId) {\n logger.log('[AdMeshProvider] ℹ️ No sponsored follow-up suggestion returned from /aip/context');\n return;\n }\n\n const sponsoredSuggestion: Suggestion = {\n id: recommendationId,\n text: suggestionText,\n type: 'action',\n is_sponsored: true,\n recommendation: platformResult,\n metadata: {\n source: 'aip_context_prefetch',\n recommendation_id: recommendationId,\n },\n };\n\n setSuggestions((currentSuggestions) =>\n prependSponsoredSuggestion(currentSuggestions, sponsoredSuggestion)\n );\n\n logger.log('[AdMeshProvider] ✅ Sponsored suggestion prefetched from /aip/context', {\n recommendationId,\n suggestionText,\n });\n } catch (error) {\n logger.warn('[AdMeshProvider] ⚠️ Sponsored suggestion prefetch failed (non-blocking):', error);\n }\n },\n [apiKey, language, location, model, sdk, sessionId, userId, prependSponsoredSuggestion, resolveHeadingsForAnalysis],\n );\n\n // Retry intent analysis function\n const retryIntentAnalysis = useCallback(async () => {\n logger.log('[AdMeshProvider] 🔄 Manual retry of intent analysis');\n await performIntentAnalysis();\n }, [performIntentAnalysis]);\n\n // Auto-analyze intent once on mount for public API keys.\n // Empty ACIE/no_match responses are still valid outcomes and must not retrigger forever.\n useEffect(() => {\n if (!sdk || hasAttemptedInitialAnalysisRef.current) {\n return;\n }\n\n hasAttemptedInitialAnalysisRef.current = true;\n void (async () => {\n const headingsData = await resolveHeadingsForAnalysis();\n await Promise.allSettled([\n prefetchSponsoredSuggestion(headingsData),\n performIntentAnalysis(headingsData),\n ]);\n })();\n }, [sdk, performIntentAnalysis, prefetchSponsoredSuggestion, resolveHeadingsForAnalysis]);\n\n const isDelegationSessionActive = useCallback((session: ActiveDelegationSession | null) => {\n if (!session || session.status !== 'active') {\n return false;\n }\n\n const expiresAtMs = Date.parse(session.expires_at);\n if (Number.isNaN(expiresAtMs)) {\n return false;\n }\n\n return expiresAtMs > Date.now();\n }, []);\n\n const postDelegationEvent = useCallback(\n async (\n endpoint: string,\n eventType: string,\n metadata?: Record<string, unknown>,\n sessionOverride?: ActiveDelegationSession | null,\n ) => {\n const session = sessionOverride ?? activeDelegationSession;\n if (!session || !sdk) {\n logger.warn('[AdMeshProvider] ⚠️ Skipping delegation event because session or SDK is missing', {\n endpoint,\n eventType,\n hasSession: !!session,\n hasSdk: !!sdk,\n });\n return;\n }\n\n const timestamp = new Date().toISOString();\n logger.log('[AdMeshProvider] 📡 Sending delegation event', {\n endpoint,\n eventType,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n sessionId: session.session_id,\n });\n const response = await fetch(`${sdk.getApiBaseUrl()}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n delegation_session_id: session.delegation_session_id,\n recommendation_id: session.recommendation_id,\n session_id: session.session_id,\n event_type: eventType,\n timestamp,\n metadata: metadata || {},\n }),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n logger.error('[AdMeshProvider] ❌ Delegation event failed', {\n endpoint,\n eventType,\n status: response.status,\n errorBody,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n });\n throw new Error(`Delegation event failed (${response.status}): ${errorBody}`);\n }\n\n const result = await response.json();\n const updatedSession = result?.session as ActiveDelegationSession | undefined;\n logger.log('[AdMeshProvider] ✅ Delegation event acknowledged', {\n endpoint,\n eventType,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n returnedStatus: updatedSession?.status || result?.status,\n });\n if (updatedSession) {\n setActiveDelegationSessionState(updatedSession);\n }\n },\n [activeDelegationSession, apiKey, sdk],\n );\n\n useEffect(() => {\n if (!activeDelegationSession || !sdk) {\n return;\n }\n\n if (!isDelegationSessionActive(activeDelegationSession)) {\n setActiveDelegationSessionState((prev) =>\n prev\n ? {\n ...prev,\n status: 'expired',\n }\n : null,\n );\n return;\n }\n\n const interval = window.setInterval(() => {\n void postDelegationEvent('/aip/delegation/heartbeat', 'heartbeat').catch((error) => {\n logger.warn('[AdMeshProvider] ⚠️ Failed to send delegation heartbeat:', error);\n });\n }, 60_000);\n\n return () => {\n window.clearInterval(interval);\n };\n }, [activeDelegationSession, isDelegationSessionActive, postDelegationEvent, sdk]);\n\n // Create context value\n const contextValue: AdMeshContextValue = {\n sdk,\n apiKey,\n sessionId,\n theme,\n language,\n location,\n userId,\n model,\n messages,\n processedMessageIds,\n recommendationResults,\n activeDelegationSession,\n \n // Suggestion state\n suggestions,\n isAnalyzingIntent: isAnalyzingIntent || isResolvingPageContext,\n intentError,\n \n // Methods\n markMessageAsProcessed: (messageId: string) => {\n setProcessedMessageIds((prev) => {\n const updated = new Set(prev);\n updated.add(messageId);\n return updated;\n });\n },\n \n isMessageProcessed: (messageId: string) => {\n return processedMessageIds.has(messageId);\n },\n\n setRecommendationResult: (messageId: string, result: PlatformResponse | null) => {\n setRecommendationResults((prev) => {\n const next = new Map(prev);\n next.set(messageId, result);\n return next;\n });\n setProcessedMessageIds((prev) => {\n const updated = new Set(prev);\n updated.add(messageId);\n return updated;\n });\n },\n\n getRecommendationResult: (messageId: string) => {\n return recommendationResults.get(messageId);\n },\n\n hasRecommendationResult: (messageId: string) => {\n return recommendationResults.has(messageId);\n },\n\n setActiveDelegationSession: (session: ActiveDelegationSession | null) => {\n setActiveDelegationSessionState(session);\n },\n\n getActiveDelegationSession: () => {\n if (!isDelegationSessionActive(activeDelegationSession)) {\n return null;\n }\n return activeDelegationSession;\n },\n\n hasActiveDelegationSession: () => {\n return isDelegationSessionActive(activeDelegationSession);\n },\n\n refreshDelegationActivity: async (\n eventType: string = 'turn_completed',\n metadata?: Record<string, unknown>,\n ) => {\n await postDelegationEvent('/aip/delegation/activity', eventType, metadata);\n },\n\n stopDelegationSession: async (\n reason: string = 'user_stopped',\n metadata?: Record<string, unknown>,\n ) => {\n const session = activeDelegationSession;\n if (!session) {\n logger.warn('[AdMeshProvider] ⚠️ stopDelegationSession called without an active SDK delegation session');\n return;\n }\n\n logger.log('[AdMeshProvider] 🛑 Stopping delegation session', {\n reason,\n recommendationId: session.recommendation_id,\n delegationSessionId: session.delegation_session_id,\n });\n await postDelegationEvent(\n '/aip/delegation/stop',\n 'session_stopped',\n { reason, ...(metadata || {}) },\n session,\n );\n await sdk?.trackPublisherAssistantEvent({\n event_name: 'delegation_stopped',\n timestamp: new Date().toISOString(),\n session_id: session.session_id,\n recommendation_id: session.recommendation_id,\n delegation_session_id: session.delegation_session_id,\n brand_name: session.brand_name,\n status: 'stopped',\n metadata: {\n reason,\n ...(metadata || {}),\n },\n }).catch((analyticsError) => {\n logger.warn('[AdMeshProvider] ⚠️ Failed to track delegation_stopped event:', analyticsError);\n });\n setActiveDelegationSessionState(null);\n logger.log('[AdMeshProvider] ✅ Delegation session cleared locally after stop');\n },\n \n retryIntentAnalysis,\n };\n\n return (\n <AdMeshContext.Provider value={contextValue}>\n {children}\n </AdMeshContext.Provider>\n );\n};\n\nexport default AdMeshProvider;\n","/**\n * AdMesh Renderer\n * \n * Handles rendering of recommendations in the specified container\n */\n\nimport ReactDOM from 'react-dom/client';\nimport type { AdMeshRecommendationResponse, AdMeshTheme, DelegationActivationPayload } from '../types/index';\nimport { AdMeshLayout } from '../components/AdMeshLayout';\nimport { AdMeshTracker } from './AdMeshTracker';\nimport { AdMeshProvider } from '../context/AdMeshProvider';\nimport { logger } from '../utils/logger';\n\nexport interface RenderOptions {\n containerId: string;\n followups_container_id?: string;\n response: AdMeshRecommendationResponse;\n theme?: AdMeshTheme;\n tracker: AdMeshTracker;\n sessionId: string;\n apiKey: string;\n apiBaseUrl?: string;\n language?: string;\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string;\n model?: string;\n messages?: Array<{ role: string; content: string; id?: string }>;\n onPasteToInput?: (content: string) => void;\n onDelegationConsent?: (recommendation: import('../types/index').PlatformResponse) => boolean | Promise<boolean>;\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n onStartDelegation?: (recommendation: import('../types/index').PlatformResponse) => void | Promise<void>;\n onExecuteQuery?: (query: string) => void | Promise<void>;\n}\n\nexport class AdMeshRenderer {\n private roots: Map<string, ReactDOM.Root> = new Map();\n\n constructor() {\n // No configuration needed\n }\n\n /**\n * Render recommendations in the specified container\n */\n async render(options: RenderOptions): Promise<void> {\n try {\n logger.log('[AdMeshRenderer] 🎨 Attempting to render recommendations');\n\n // Check if we have any recommendations to render\n const recommendations = options.response.recommendations || [];\n if (recommendations.length === 0) {\n logger.log('[AdMeshRenderer] ⚠️ No recommendations to render - skipping render to avoid occupying space');\n return;\n }\n\n const container = document.getElementById(options.containerId);\n\n if (!container) {\n logger.error('[AdMeshRenderer] ❌ Container not found');\n throw new Error(`Container with ID \"${options.containerId}\" not found`);\n }\n\n logger.log('[AdMeshRenderer] ✅ Container ready');\n\n // Clean up existing root if any\n const existingRoot = this.roots.get(options.containerId);\n if (existingRoot) {\n logger.log('[AdMeshRenderer] 🧹 Cleaning up existing root');\n existingRoot.unmount();\n this.roots.delete(options.containerId);\n }\n\n // Clear the container's innerHTML to ensure React can create a fresh root\n container.innerHTML = '';\n\n // Create a new root\n const root = ReactDOM.createRoot(container);\n\n logger.log('[AdMeshRenderer] 📊 Rendering recommendations');\n\n // Get onPasteToInput from options or window object (for backward compatibility)\n // Wrap components in AdMeshProvider to provide context for hooks like useAdMesh()\n root.render(\n <AdMeshProvider\n apiKey={options.apiKey}\n sessionId={options.sessionId}\n theme={options.theme}\n apiBaseUrl={options.apiBaseUrl}\n language={options.language}\n location={options.location}\n userId={options.userId}\n model={options.model}\n messages={options.messages}\n >\n <AdMeshLayout\n recommendations={recommendations}\n theme={options.theme}\n sessionId={options.sessionId}\n onDelegationConsent={options.onDelegationConsent}\n onDelegationActivated={options.onDelegationActivated}\n onStartDelegation={options.onStartDelegation}\n />\n </AdMeshProvider>\n );\n\n // Show the container now that content is rendered (prevents empty space when no ads)\n container.style.display = 'block';\n\n logger.log('[AdMeshRenderer] ✅ Recommendations rendered successfully');\n\n // Store root for cleanup\n this.roots.set(options.containerId, root);\n\n } catch (error) {\n logger.error('[AdMeshRenderer] ❌ Error rendering recommendations');\n throw error;\n }\n }\n\n /**\n * Unmount a rendered component\n */\n unmount(containerId: string): void {\n const root = this.roots.get(containerId);\n if (root) {\n root.unmount();\n this.roots.delete(containerId);\n \n // Hide the container again to prevent empty space\n const container = document.getElementById(containerId);\n if (container) {\n container.style.display = 'none';\n }\n }\n }\n\n /**\n * Unmount all rendered components\n */\n unmountAll(): void {\n for (const [, root] of this.roots.entries()) {\n root.unmount();\n }\n this.roots.clear();\n }\n}\n","/**\n * AdMesh UI SDK - Zero-Code Integration\n * \n * Provides a simple, zero-code integration experience for platforms.\n * Handles all recommendation fetching, rendering, and tracking automatically.\n */\n\nimport type {\n AdMeshTheme,\n AdMeshRecommendationResponse,\n PlatformRequest,\n PlatformResponse,\n DelegationActivationPayload,\n ActiveDelegationSession,\n} from '../types/index';\nimport { AdMeshRenderer } from './AdMeshRenderer';\nimport { AdMeshTracker } from './AdMeshTracker';\nimport { logger } from '../utils/logger';\n\nconst normalizeCountryCode = (value?: string): string | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim().toUpperCase();\n return /^[A-Z]{2}$/.test(trimmed) ? trimmed : undefined;\n};\n\nexport interface AdMeshSDKConfig {\n apiKey: string;\n theme?: AdMeshTheme;\n apiBaseUrl?: string;\n /** Set true when requests originate from the browser extension */\n extension?: boolean;\n /** Optional override for extension source domain header */\n extensionSourceDomain?: string;\n /** Optional user identifier forwarded to ACIE/aip context flows */\n userId?: string;\n}\n\nexport interface ShowRecommendationsOptions {\n query: string;\n containerId: string;\n theme?: AdMeshTheme;\n\n // Optional follow-ups container (SDK will render follow-ups here if provided and followup_suggestion is present)\n followups_container_id?: string;\n\n // Session tracking (required)\n sessionId: string;\n\n // Message tracking (required)\n // messageId MUST be provided by the platform - SDK never generates it\n messageId: string;\n\n // Platform information\n // platformId is now extracted from API key by the backend\n platformSurface?: string;\n model?: string;\n messages?: Array<{ role: string; content: string }>;\n locale?: string;\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string;\n // latency_budget_ms removed - now fetched from agent profile by backend\n // allowed_formats removed - backend fetches from platform config (configured during onboarding)\n \n /** Legacy bridge CTA callback; prefer onStartDelegation */\n onPasteToInput?: (content: string) => void;\n\n /** Called when the SDK needs host approval before starting a delegated brand flow */\n onDelegationConsent?: (recommendation: PlatformResponse) => boolean | Promise<boolean>;\n\n /** Called with normalized delegation metadata the host can use directly */\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n\n /** Called after consent is granted so the host can create/open the delegation session */\n onStartDelegation?: (recommendation: PlatformResponse) => void | Promise<void>;\n \n /** Callback to execute query when follow-up is selected (required for follow-up functionality) */\n onExecuteQuery?: (query: string) => void | Promise<void>;\n}\n\nexport type PublisherAssistantEventName =\n | 'assistant_loaded'\n | 'assistant_opened'\n | 'suggestion_exposure'\n | 'suggestion_clicked'\n | 'query_submitted'\n | 'answer_completed'\n | 'answer_failed'\n | 'source_link_clicked'\n | 'recommendation_shown'\n | 'delegation_started'\n | 'delegation_stopped'\n | 'answer_feedback';\n\nexport interface PublisherAssistantAnalyticsEvent {\n event_name: PublisherAssistantEventName;\n timestamp: string;\n session_id: string;\n message_id?: string;\n page_url?: string;\n page_path?: string;\n article_slug?: string;\n page_title?: string;\n referrer?: string;\n device_type?: 'mobile' | 'tablet' | 'desktop' | 'unknown';\n query?: string;\n suggestion_id?: string;\n suggestion_text?: string;\n suggestion_type?: string;\n suggestion_position?: number;\n is_sponsored?: boolean;\n recommendation_id?: string;\n brand_name?: string;\n delegation_session_id?: string;\n used_capability?: string;\n status?: string;\n latency_ms?: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Main AdMesh SDK class for zero-code integration\n *\n * The SDK is stateless regarding session management. Developers must provide\n * sessionId when calling showRecommendations().\n *\n * @example\n * ```typescript\n * import { AdMeshSDK } from '@admesh/ui-sdk';\n *\n * const admesh = new AdMeshSDK({ apiKey: 'your-api-key' });\n *\n * // Generate session ID on your platform\n * const sessionId = AdMeshSDK.createSession();\n *\n * await admesh.showRecommendations({\n * query: 'best CRM for small business',\n * containerId: 'admesh-recommendations',\n * sessionId: sessionId\n * });\n * ```\n */\nexport class AdMeshSDK {\n private config: AdMeshSDKConfig;\n private apiBaseUrl: string;\n private static inFlightPlatformResponses = new Map<string, Promise<PlatformResponse>>();\n\n // OPTIMIZATION: Lazy-initialized managers (only created when needed)\n private renderer: AdMeshRenderer | null = null;\n private tracker: AdMeshTracker | null = null;\n\n constructor(config: AdMeshSDKConfig) {\n if (!config.apiKey) {\n throw new Error('AdMeshSDK: apiKey is required');\n }\n\n this.config = {\n apiKey: config.apiKey,\n theme: config.theme,\n apiBaseUrl: config.apiBaseUrl,\n extension: config.extension,\n extensionSourceDomain: config.extensionSourceDomain,\n userId: config.userId,\n };\n\n // Set API base URL with priority: config > environment variable > production default\n this.apiBaseUrl = config.apiBaseUrl ||\n (typeof window !== 'undefined' && (window as unknown as { __ADMESH_API_BASE_URL__: string }).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n }\n\n /**\n * Get the API base URL\n * @returns The API base URL being used by the SDK\n */\n getApiBaseUrl(): string {\n return this.apiBaseUrl;\n }\n\n private static buildPlatformResponseCacheKey(sessionId: string, messageId: string): string {\n return `${sessionId}::${messageId}`;\n }\n\n /**\n * Resolve source domain for extension-originated requests.\n */\n private getExtensionSourceDomain(): string | undefined {\n const configuredDomain = this.config.extensionSourceDomain?.trim();\n if (configuredDomain) {\n return configuredDomain.toLowerCase();\n }\n\n if (typeof window !== 'undefined' && window.location?.hostname) {\n const hostname = window.location.hostname.trim().toLowerCase();\n return hostname || undefined;\n }\n\n return undefined;\n }\n\n /**\n * PLATFORM UTILITY: Generate a unique session ID for tracking recommendations\n * \n * IMPORTANT: This is a utility method for PLATFORMS to use. The SDK itself\n * NEVER calls this method automatically. Platforms must:\n * 1. Call this method (or generate their own sessionId)\n * 2. Store the sessionId in their own storage\n * 3. Pass sessionId to AdMeshProvider and SDK methods\n * \n * The SDK will throw an error if sessionId is not provided - it will never\n * auto-generate one.\n *\n * @returns A unique session ID (platform must store and manage this)\n */\n static createSession(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 15);\n return `session_${timestamp}_${random}`;\n }\n\n /**\n * PLATFORM UTILITY: Generate session ID from URL for digital publishers\n * \n * This utility function helps platforms generate session IDs based on URL structure.\n * Platforms can call this function on page load to get a consistent session ID.\n * \n * @param url - The URL to extract session information from (defaults to current page URL)\n * @returns A session ID in format: session_{timestamp}_{article-slug}\n * \n * @example\n * ```typescript\n * // In your React component\n * const sessionId = AdMeshSDK.generateSessionIdFromUrl();\n * \n * // Or with a specific URL\n * const sessionId = AdMeshSDK.generateSessionIdFromUrl('https://techcrunch.com/2025/12/30/ai-apps/');\n * // Returns: \"session_1739534760000_ai-apps\"\n * ```\n */\n static generateSessionIdFromUrl(url?: string): string {\n const targetUrl = url || (typeof window !== 'undefined' ? window.location.href : '');\n \n if (!targetUrl) {\n // Fallback to regular session generation\n return AdMeshSDK.createSession();\n }\n\n try {\n const urlObj = new URL(targetUrl);\n const pathSegments = urlObj.pathname.split('/').filter(segment => segment.length > 0);\n const articleSlug = pathSegments[pathSegments.length - 1];\n \n if (articleSlug) {\n const timestamp = Date.now();\n return `session_${timestamp}_${articleSlug}`;\n }\n \n // Fallback if no slug found\n return AdMeshSDK.createSession();\n } catch {\n // Fallback if URL parsing fails\n return AdMeshSDK.createSession();\n }\n }\n\n /**\n * PLATFORM UTILITY: Generate a unique message ID for tracking recommendations per message\n * @returns A unique message ID (platform must provide this to SDK methods)\n */\n static createMessageId(sessionId?: string): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 9);\n if (sessionId) {\n return `msg_${sessionId}_${timestamp}_${random}`;\n }\n return `msg_${timestamp}_${random}`;\n }\n\n\n /**\n * OPTIMIZATION: Lazy initialize renderer on first use\n */\n private getRenderer(): AdMeshRenderer {\n if (!this.renderer) {\n this.renderer = new AdMeshRenderer();\n }\n return this.renderer;\n }\n\n /**\n * OPTIMIZATION: Lazy initialize tracker on first use\n */\n private getTracker(): AdMeshTracker {\n if (!this.tracker) {\n this.tracker = new AdMeshTracker({\n apiKey: this.config.apiKey\n });\n }\n return this.tracker;\n }\n\n private async postDelegationEvent(\n endpoint: string,\n session: ActiveDelegationSession,\n eventType: string,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n const response = await fetch(`${this.apiBaseUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n delegation_session_id: session.delegation_session_id,\n recommendation_id: session.recommendation_id,\n session_id: session.session_id,\n event_type: eventType,\n timestamp: new Date().toISOString(),\n metadata: metadata || {},\n }),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new Error(`Delegation event failed (${response.status}): ${errorBody}`);\n }\n\n const result = await response.json();\n return (result?.session as ActiveDelegationSession | undefined) || null;\n }\n\n async reportDelegationTurnStarted(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'turn_started', metadata);\n }\n\n async reportDelegationSessionStarted(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'session_started', metadata);\n }\n\n async reportDelegationTurnCompleted(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'turn_completed', metadata);\n }\n\n async reportDelegationToolInvocation(\n session: ActiveDelegationSession,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/activity', session, 'tool_invoked', metadata);\n }\n\n async reportDelegationOutcome(\n session: ActiveDelegationSession,\n outcomeType: string,\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/complete', session, outcomeType, metadata);\n }\n\n async stopDelegationSession(\n session: ActiveDelegationSession,\n reason: string = 'user_stopped',\n metadata?: Record<string, unknown>,\n ): Promise<ActiveDelegationSession | null> {\n return this.postDelegationEvent('/aip/delegation/stop', session, 'session_stopped', {\n reason,\n ...(metadata || {}),\n });\n }\n\n getActiveDelegationSession(session: ActiveDelegationSession | null): ActiveDelegationSession | null {\n if (!session || session.status !== 'active') {\n return null;\n }\n\n const expiresAtMs = Date.parse(session.expires_at);\n if (Number.isNaN(expiresAtMs) || expiresAtMs <= Date.now()) {\n return null;\n }\n\n return session;\n }\n\n hasActiveDelegationSession(session: ActiveDelegationSession | null): boolean {\n return !!this.getActiveDelegationSession(session);\n }\n\n\n\n\n /**\n * Fetch and render recommendations automatically using /aip/context endpoint\n *\n * IMPORTANT: Both sessionId and messageId MUST be provided by the platform.\n * The SDK NEVER generates these automatically. Use AdMeshSDK.createSession()\n * and AdMeshSDK.createMessageId() on your platform, or generate your own IDs.\n */\n async showRecommendations(options: ShowRecommendationsOptions): Promise<void> {\n try {\n // CRITICAL: sessionId MUST be provided by platform - SDK never generates it\n if (!options.sessionId || options.sessionId.trim() === '') {\n throw new Error('sessionId is required and must be provided by the platform. The SDK never generates sessionId automatically.');\n }\n \n // CRITICAL: messageId MUST be provided by the platform - SDK never generates it\n if (!options.messageId || options.messageId.trim() === '') {\n throw new Error('messageId is required and must be provided by the platform. The SDK never generates messageId automatically.');\n }\n \n // Fetch canonical platform result from /aip/context endpoint\n // platformId is extracted from API key by the backend\n const platformResult = await this.fetchPlatformResponse({\n query: options.query,\n sessionId: options.sessionId,\n messageId: options.messageId, // Pass messageId from platform\n platformSurface: options.platformSurface,\n model: options.model,\n messages: options.messages,\n language: options.locale, // locale maps to language\n location: options.location,\n userId: options.userId ?? this.config.userId,\n // latency_budget_ms removed - now fetched from agent profile by backend\n // allowed_formats removed - backend fetches from platform config automatically\n });\n\n const response: AdMeshRecommendationResponse = {\n sessionId: options.sessionId,\n messageId: options.messageId,\n recommendations: [platformResult]\n };\n\n // Standard rendering\n const renderer = this.getRenderer();\n const tracker = this.getTracker();\n\n await renderer.render({\n containerId: options.containerId,\n followups_container_id: options.followups_container_id,\n response,\n theme: options.theme || this.config.theme,\n tracker: tracker,\n sessionId: options.sessionId,\n apiKey: this.config.apiKey,\n apiBaseUrl: this.apiBaseUrl,\n language: options.locale,\n location: options.location,\n userId: options.userId,\n model: options.model,\n messages: options.messages,\n onPasteToInput: options.onPasteToInput,\n onDelegationConsent: options.onDelegationConsent,\n onDelegationActivated: options.onDelegationActivated,\n onStartDelegation: options.onStartDelegation,\n onExecuteQuery: options.onExecuteQuery\n });\n\n // NOTE: Exposure pixels are now fired by AdMeshViewabilityTracker component\n // when ads meet MRC viewability standards (50% visible for 1 second).\n // This ensures MRC-compliant exposure tracking and proper CPX billing.\n } catch (error) {\n logger.error('[AdMeshSDK] Error showing recommendations');\n throw error;\n }\n }\n\n /**\n * Fetch the canonical PlatformResponse from `/aip/context`.\n *\n * Use this when you want the full platform response returned by the operator,\n * including `status`, `recommendation`, `tracking`, and `delegation`.\n */\n async fetchPlatformResponse(params: {\n query: string;\n sessionId: string;\n messageId?: string;\n // platformId is now extracted from API key by the backend\n platformSurface?: string;\n model?: string;\n messages?: Array<{ role: string; content: string; id?: string }>;\n language?: string;\n location?: {\n city?: string;\n state?: string;\n stateCode?: string;\n country?: string;\n countryCode?: string;\n zipcode?: string;\n latitude?: number;\n longitude?: number;\n };\n userId?: string;\n // latency_budget_ms removed - now fetched from agent profile by backend\n // allowed_formats removed - backend fetches from platform config (configured during onboarding)\n }): Promise<PlatformResponse> {\n const url = `${this.apiBaseUrl}/aip/context`;\n\n logger.log('[AdMeshSDK] 📥 fetchPlatformResponse called');\n\n // CRITICAL: sessionId MUST be provided by platform - SDK never generates it\n if (!params.sessionId || params.sessionId.trim() === '') {\n const error = new Error('sessionId is required and must be provided by the platform. The SDK never generates sessionId automatically.');\n logger.error('[AdMeshSDK] ❌ sessionId not provided by platform - cannot process request');\n throw error;\n }\n\n // CRITICAL: messageId MUST be provided by the platform - SDK never generates it\n // NEVER derive from messages array - platform must pass it explicitly\n const messageId = params.messageId;\n if (!messageId || messageId.trim() === '') {\n const error = new Error('messageId is required and must be provided by the platform. The SDK never generates messageId automatically.');\n logger.error('[AdMeshSDK] ❌ messageId not provided by platform - cannot process request');\n throw error;\n }\n\n const cacheKey = AdMeshSDK.buildPlatformResponseCacheKey(params.sessionId, messageId);\n const inFlightResponse = AdMeshSDK.inFlightPlatformResponses.get(cacheKey);\n if (inFlightResponse) {\n logger.log('[AdMeshSDK] ⏳ Reusing in-flight PlatformResponse request', {\n sessionId: params.sessionId,\n messageId,\n });\n return inFlightResponse;\n }\n \n // Calculate turn_index from messages length\n const turnIndex = params.messages ? params.messages.length : 0;\n \n // Detect device platform (web by default, could be enhanced with user agent detection)\n const devicePlatform = typeof window !== 'undefined' && window.navigator ? 'web' : 'web';\n \n // Detect form factor (could be enhanced with screen size detection)\n const formFactor = typeof window !== 'undefined' && window.innerWidth \n ? (window.innerWidth < 768 ? 'mobile' : window.innerWidth < 1024 ? 'tablet' : 'desktop')\n : 'desktop';\n const countryCode = normalizeCountryCode(params.location?.countryCode) || 'US';\n const pageContext = typeof window !== 'undefined' && window.location\n ? {\n url: window.location.href,\n origin: window.location.origin,\n referrer: document.referrer || undefined,\n host: window.location.hostname,\n }\n : undefined;\n\n // Build the canonical AIP PlatformRequest payload.\n // platform.platform_id will be normalized from the API key by the backend.\n const resolvedUserId = params.userId ?? this.config.userId;\n\n const payload: PlatformRequest = {\n spec_version: '1.0',\n message_id: messageId,\n timestamp: new Date().toISOString(),\n platform: {\n platform_id: 'placeholder',\n role: 'platform',\n software: {\n name: 'admesh_ui_sdk',\n version: params.model || '1.0.0'\n }\n },\n identity: {\n namespace: 'platform_user',\n value_hash: resolvedUserId || '',\n confidence: resolvedUserId ? 1.0 : 0.0\n },\n consent: {\n status: 'granted',\n source: 'admesh_ui_sdk',\n scope: {\n intent_based_monetization: true,\n agent_participation: true,\n measurement: true\n },\n constraints: {\n allow_identity_downstream: false\n }\n },\n classification_input: {\n type: 'interaction',\n interaction: {\n session: {\n id: params.sessionId,\n turn_index: turnIndex\n },\n surface: {\n channel: params.platformSurface || 'conversation',\n interaction_mode: 'text',\n platform: devicePlatform,\n form_factor: formFactor,\n locale: params.language || 'en-US',\n country: countryCode,\n publisher: 'placeholder'\n },\n input: {\n query_text: params.query,\n messages: params.messages || []\n },\n context: {\n location: {\n city: params.location?.city || undefined,\n state: params.location?.state || undefined,\n state_code: params.location?.stateCode || undefined,\n country: params.location?.country || undefined,\n country_code: countryCode,\n zipcode: params.location?.zipcode || undefined,\n latitude: params.location?.latitude,\n longitude: params.location?.longitude,\n },\n page: pageContext,\n },\n }\n },\n monetization: {\n enabled: true,\n pricing_model: 'CPX',\n auction: {\n enabled: true,\n floor: {\n amount: 0,\n currency: 'USD'\n }\n }\n }\n };\n\n // Validate query before sending\n if (!payload.classification_input.interaction?.input.query_text?.trim()) {\n logger.warn('[AdMeshSDK] ⚠️ Warning: Sending request with empty query_text');\n }\n\n const jsonBody = JSON.stringify(payload);\n logger.log('[AdMeshSDK] 📤 Sending canonical request to /aip/context', {\n messageId: payload.message_id,\n specVersion: payload.spec_version,\n classificationType: payload.classification_input.type,\n platformId: payload.platform.platform_id,\n surfaceChannel: payload.classification_input.interaction?.surface.channel,\n sessionId: payload.classification_input.interaction?.session?.id\n });\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`\n };\n\n if (this.config.extension) {\n headers['X-AdMesh-Source'] = 'extension';\n\n const sourceDomain = this.getExtensionSourceDomain();\n if (sourceDomain) {\n headers['X-AdMesh-Source-Domain'] = sourceDomain;\n }\n }\n\n const requestPromise = (async () => {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: jsonBody\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n const errorMessage = errorData.detail || `HTTP ${response.status}`;\n throw new Error(`Failed to fetch recommendation from /aip/context: ${errorMessage}`);\n }\n\n const data: PlatformResponse = await response.json();\n\n logger.log('[AdMeshSDK] 📥 Raw response from /aip/context:', {\n status: data.status,\n recommendationId: data.recommendation_id,\n hasRecommendation: !!data.recommendation,\n hasTracking: !!data.tracking,\n hasDelegation: !!data.delegation,\n topLevelKeys: Object.keys(data)\n });\n logger.log('[AdMeshSDK] 📦 Full PlatformResponse received from /aip/context', data);\n return data as PlatformResponse;\n })();\n\n AdMeshSDK.inFlightPlatformResponses.set(cacheKey, requestPromise);\n\n try {\n return await requestPromise;\n } finally {\n AdMeshSDK.inFlightPlatformResponses.delete(cacheKey);\n }\n }\n\n async trackPublisherAssistantEvent(\n event: PublisherAssistantAnalyticsEvent | PublisherAssistantAnalyticsEvent[],\n ): Promise<void> {\n const payload = Array.isArray(event) ? { events: event } : event;\n const response = await fetch(`${this.apiBaseUrl}/analytics/publisher-assistant/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n });\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '');\n throw new Error(`Failed to track publisher assistant analytics (${response.status}): ${errorBody}`);\n }\n }\n\n /**\n * Fire exposure for sponsored followup\n * \n * @param exposureUrl - The exposure URL to fire (can use regular exposure_url)\n * @param recommendationId - The recommendation ID\n * @param sessionId - The session ID\n */\n fireFollowupExposure(exposureUrl: string, recommendationId: string, sessionId: string): void {\n const tracker = this.getTracker();\n tracker.fireFollowupExposure(exposureUrl, recommendationId, sessionId);\n }\n\n /**\n * Fire engagement for sponsored followup\n * \n * @param engagementUrl - The engagement URL to fire\n * @param recommendationId - The recommendation ID\n * @param sessionId - The session ID\n * @returns Promise that resolves when engagement is fired\n */\n async fireFollowupEngagement(engagementUrl: string, recommendationId: string, sessionId: string): Promise<void> {\n const tracker = this.getTracker();\n return tracker.fireFollowupEngagement(engagementUrl, recommendationId, sessionId);\n }\n}\n\nexport default AdMeshSDK;\n","/**\n * WeaveResponseProcessor\n * \n * Automatically detects and enhances AdMesh recommendation links in organic LLM responses.\n * Handles:\n * - Automatic link detection (AdMesh tracking URLs)\n * - Label enhancement (<sub>Ad</sub> subscript labels)\n * - Exposure pixel triggering\n * - Streaming response support (MutationObserver)\n */\n\nimport { logger } from '../utils/logger';\n\nexport interface DetectedLink {\n element: HTMLAnchorElement;\n href: string;\n text: string;\n hasAdLabel: boolean;\n matchedRecommendation?: {\n recommendation_id: string;\n click_url: string;\n exposure_url?: string;\n };\n}\n\nexport interface ProcessorConfig {\n autoAddLabels?: boolean;\n fireExposurePixels?: boolean;\n labelStyle?: {\n fontSize?: string;\n fontWeight?: string;\n color?: string;\n marginLeft?: string;\n };\n}\n\nexport interface ExposurePixelTarget {\n exposureUrl?: string;\n recommendationId?: string;\n linkElement: HTMLAnchorElement;\n}\n\nexport class WeaveResponseProcessor {\n private autoAddLabels: boolean;\n private fireExposurePixels: boolean;\n private labelStyle: Record<string, string>;\n private processedLinks: Set<string> = new Set();\n private mutationObserver: MutationObserver | null = null;\n\n constructor(config: ProcessorConfig = {}) {\n this.autoAddLabels = config.autoAddLabels !== false; // Default: true\n this.fireExposurePixels = config.fireExposurePixels !== false; // Default: true\n this.labelStyle = {\n fontSize: config.labelStyle?.fontSize || '0.75em',\n fontWeight: config.labelStyle?.fontWeight || 'bold',\n color: config.labelStyle?.color || '#666',\n marginLeft: config.labelStyle?.marginLeft || '2px'\n };\n }\n\n /**\n * Get links to process with CSS selector optimization\n *\n * Optimized approach:\n * 1. Use CSS selector to find AdMesh links (97% faster)\n * - Matches: api.useadmesh.com/click/*, *.useadmesh.com/click/*\n * 2. Fallback to scanning all links if selector finds nothing\n * 3. Recommendation validation ensures accuracy\n */\n private getLinksToProcess(container: HTMLElement): HTMLAnchorElement[] {\n // Try optimized selector first for AdMesh links\n // Matches both api.useadmesh.com and *.useadmesh.com domains\n const optimizedSelector = 'a[href*=\"/click/\"][href*=\"admesh.com\"], a[href*=\"/click/\"][href*=\"useadmesh.com\"]';\n const optimizedLinks = container.querySelectorAll(optimizedSelector);\n\n if (optimizedLinks.length > 0) {\n return Array.from(optimizedLinks) as HTMLAnchorElement[];\n }\n\n // Fallback: scan all links\n return Array.from(container.querySelectorAll('a')) as HTMLAnchorElement[];\n }\n\n /**\n * Scan container for ALL links and process only AdMesh recommendation links\n *\n * This method:\n * 1. Scans container for all <a> tags (or uses optimized selector)\n * 2. If recommendations provided: Filters to only process links matching recommendation click_url values\n * 3. If NO recommendations: Detects links by URL pattern (api.useadmesh.com/click/*)\n * 4. Ignores non-AdMesh links (external links, documentation, etc.)\n * 5. Adds Ad labels to matching links\n * 6. Fires exposure pixels for each match\n *\n * NOTE: When recommendations array is empty, this method detects AdMesh links by URL pattern.\n * This is important for Weave Ad Format where the backend embeds links in the LLM response\n * and the frontend hook doesn't have access to the recommendations data.\n */\n scanAndProcessLinks(\n container: HTMLElement,\n recommendations: any[],\n onExposurePixel?: (target: ExposurePixelTarget) => void\n ): DetectedLink[] {\n if (!container) {\n return [];\n }\n\n const detectedLinks: DetectedLink[] = [];\n\n // If recommendations provided, use them for matching\n if (recommendations.length > 0) {\n // Get links to process (with optional optimization)\n const links = this.getLinksToProcess(container);\n\n // Build map of AdMesh click URLs for fast lookup\n const clickUrlMap = new Map(\n recommendations\n .map((r) => [r?.tracking?.click_url || r?.recommendation?.creative?.landing_page_url || '', r] as const)\n .filter(([clickUrl]) => !!clickUrl)\n );\n\n // Build map of brand URLs (redirect_url, url) for matching direct brand links\n const brandUrlMap = new Map<string, any>();\n recommendations.forEach((r: any) => {\n const redirectUrl = r?.recommendation?.creative?.landing_page_url;\n if (redirectUrl && typeof redirectUrl === 'string') {\n // Normalize URL (remove trailing slashes, query params for matching)\n const normalizedUrl = redirectUrl.trim().replace(/\\/$/, '');\n brandUrlMap.set(normalizedUrl, r);\n // Also match with trailing slash\n brandUrlMap.set(`${normalizedUrl}/`, r);\n }\n });\n\n links.forEach((link: HTMLAnchorElement) => {\n const href = link.getAttribute('href') || '';\n const linkKey = `${href}`;\n\n // Skip if already processed\n if (this.processedLinks.has(linkKey)) {\n return;\n }\n\n // First, check if link matches AdMesh click URL\n let recommendation = clickUrlMap.get(href);\n let actualHref = href;\n \n // If not found, check if link matches brand URL (redirect_url or url)\n if (!recommendation) {\n const normalizedHref = href.trim().replace(/\\/$/, '');\n recommendation = brandUrlMap.get(normalizedHref) || brandUrlMap.get(`${normalizedHref}/`);\n \n // If brand URL matched, replace it with click_url\n const recommendationClickUrl =\n recommendation?.tracking?.click_url ||\n recommendation?.recommendation?.creative?.landing_page_url;\n if (recommendation && recommendationClickUrl) {\n logger.log('[WeaveResponseProcessor] 🔄 Found brand URL match, replacing with click_url:', href);\n link.setAttribute('href', recommendationClickUrl);\n actualHref = recommendationClickUrl;\n }\n }\n \n // Process link if it matches a recommendation (either by click_url or brand URL)\n if (recommendation) {\n this.processedLinks.add(linkKey);\n\n // ALWAYS set target=\"_blank\" and rel=\"noopener noreferrer\" for AdMesh tracking links\n // This ensures all click_url links open in a new tab\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n\n const detectedLink: DetectedLink = {\n element: link,\n href: actualHref, // Use actual href (may be updated click_url)\n text: link.textContent || '',\n hasAdLabel: this.hasAdLabel(link),\n matchedRecommendation: {\n recommendation_id: recommendation?.recommendation_id || '',\n click_url:\n recommendation?.tracking?.click_url ||\n recommendation?.recommendation?.creative?.landing_page_url ||\n '',\n exposure_url: recommendation?.tracking?.exposure_url\n }\n };\n\n // Add label if not present\n if (this.autoAddLabels && !detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] 🏷️ Adding Ad label to matched recommendation link:', actualHref);\n this.addAdLabel(link);\n detectedLink.hasAdLabel = true;\n } else if (!this.autoAddLabels) {\n logger.log('[WeaveResponseProcessor] ℹ️ autoAddLabels is disabled, skipping label');\n } else if (detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link already has label, skipping');\n }\n\n // Fire exposure pixel\n const exposureUrl = recommendation?.tracking?.exposure_url;\n if (this.fireExposurePixels && exposureUrl && onExposurePixel && detectedLink.matchedRecommendation) {\n onExposurePixel({\n exposureUrl,\n recommendationId: detectedLink.matchedRecommendation.recommendation_id,\n linkElement: link\n });\n }\n\n detectedLinks.push(detectedLink);\n }\n });\n } else {\n // No recommendations provided - detect AdMesh links by URL pattern\n // This is used for Weave Ad Format where backend embeds links in LLM response\n // Links can be in formats like:\n // - https://api.useadmesh.com/click/...\n // - https://api.useadmesh.com/click/...\n // - https://useadmesh.com/click/...\n // - https://admesh.com/click/...\n // Get ALL links in container and filter programmatically\n const allLinks = Array.from(container.querySelectorAll('a')) as HTMLAnchorElement[];\n\n \n\n allLinks.forEach((link: HTMLAnchorElement) => {\n const href = link.getAttribute('href') || '';\n const linkKey = `${href}`;\n\n // Skip if already processed\n if (this.processedLinks.has(linkKey)) {\n return;\n }\n\n // Check if this is an AdMesh link by examining the URL\n const isAdMeshLink = this.isAdMeshLink(href);\n\n if (isAdMeshLink) {\n\n this.processedLinks.add(linkKey);\n\n const detectedLink: DetectedLink = {\n element: link,\n href,\n text: link.textContent || '',\n hasAdLabel: this.hasAdLabel(link),\n matchedRecommendation: undefined\n };\n\n // Set target=\"_blank\" and rel=\"noopener noreferrer\" for security\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n\n // Add label if not present\n if (this.autoAddLabels && !detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] 🏷️ Adding Ad label to pattern-matched AdMesh link:', href);\n this.addAdLabel(link);\n detectedLink.hasAdLabel = true;\n } else if (!this.autoAddLabels) {\n logger.log('[WeaveResponseProcessor] ℹ️ autoAddLabels is disabled, skipping label');\n } else if (detectedLink.hasAdLabel) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link already has label, skipping');\n }\n\n // Fire exposure tracking with converted exposure URL\n // For Weave Ad Format: LLM embeds click URLs in response text, so we convert to exposure URL\n if (this.fireExposurePixels && onExposurePixel) {\n const exposureUrl = this.convertClickUrlToExposureUrl(href);\n onExposurePixel({\n exposureUrl,\n recommendationId: this.extractRecommendationIdFromUrl(href),\n linkElement: link\n });\n }\n\n detectedLinks.push(detectedLink);\n }\n });\n\n \n }\n\n return detectedLinks;\n }\n\n /**\n * Check if link already has Ad label\n *\n * This method checks for Ad labels on BOTH sides of the link:\n * - Previous sibling (left side): Ad link text\n * - Next sibling (right side): link text Ad\n * - Inside the link itself (as a child element)\n *\n * This prevents duplicate label rendering when the LLM response\n * already contains Ad labels in any position.\n */\n private hasAdLabel(link: HTMLAnchorElement): boolean {\n // First, check if link itself contains Ad in its text content or as a child\n const linkText = link.textContent || '';\n if (linkText.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link text contains Ad label');\n return true;\n }\n\n // Check for Ad label as a direct child element (e.g., <a>text<sub>Ad</sub></a>)\n const childElements = link.querySelectorAll('sub, span');\n for (const child of Array.from(childElements)) {\n if (child.textContent?.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link has Ad label as child element');\n return true;\n }\n }\n\n // Check PREVIOUS sibling (left side) for Ad label\n let prevNode = link.previousSibling;\n\n // Skip text nodes that are just whitespace\n while (prevNode && prevNode.nodeType === Node.TEXT_NODE) {\n const text = prevNode.textContent || '';\n if (text.trim() === '') {\n prevNode = prevNode.previousSibling;\n continue;\n }\n // If we find non-whitespace text, check if it contains Ad\n if (text.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in previous text sibling');\n return true;\n }\n break;\n }\n\n // Check if previous element node is a <sub> or <span> with Ad label\n if (prevNode && prevNode.nodeType === Node.ELEMENT_NODE) {\n const element = prevNode as HTMLElement;\n const tagName = element.tagName.toUpperCase();\n if ((tagName === 'SUB' || tagName === 'SPAN') &&\n element.textContent?.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in previous element sibling:', tagName);\n return true;\n }\n }\n\n // Check NEXT sibling (right side) for Ad label\n let nextNode = link.nextSibling;\n\n // Skip text nodes that are just whitespace\n while (nextNode && nextNode.nodeType === Node.TEXT_NODE) {\n const text = nextNode.textContent || '';\n if (text.trim() === '') {\n nextNode = nextNode.nextSibling;\n continue;\n }\n // If we find non-whitespace text, check if it contains Ad\n if (text.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in next text sibling');\n return true;\n }\n break;\n }\n\n // Check if next element node is a <sub> or <span> with Ad label\n if (nextNode && nextNode.nodeType === Node.ELEMENT_NODE) {\n const element = nextNode as HTMLElement;\n const tagName = element.tagName.toUpperCase();\n if ((tagName === 'SUB' || tagName === 'SPAN') &&\n element.textContent?.includes('Ad')) {\n logger.log('[WeaveResponseProcessor] ℹ️ Found Ad label in next element sibling:', tagName);\n return true;\n }\n }\n\n logger.log('[WeaveResponseProcessor] ℹ️ No existing Ad label found');\n return false;\n }\n\n /**\n * Add Ad label as subscript after link with \"Why this ad?\" tooltip\n *\n * This method:\n * 1. Removes any Ad label on the LEFT side (previous sibling)\n * 2. Creates a <sub> element with Ad text\n * 3. Positions it immediately after the link (to the RIGHT)\n * 4. Adds tooltip styling with default cursor (not help cursor)\n * 5. Adds click handler for tooltip interaction\n * 6. Ensures only ONE label per link, always on the RIGHT side\n */\n private addAdLabel(link: HTMLAnchorElement): void {\n logger.log('[WeaveResponseProcessor] 🏷️ Attempting to add Ad label to link:', link.href);\n \n // Verify link is still in the DOM\n if (!link.isConnected) {\n logger.warn('[WeaveResponseProcessor] ⚠️ Link is not in DOM, cannot add label');\n return;\n }\n\n // Double-check that Ad label doesn't already exist to prevent duplicates\n if (this.hasAdLabel(link)) {\n logger.log('[WeaveResponseProcessor] ℹ️ Link already has Ad label, skipping');\n return;\n }\n\n // Verify parent node exists before proceeding\n const parentNode = link.parentNode;\n if (!parentNode) {\n logger.error('[WeaveResponseProcessor] ❌ Link has no parent node, cannot add label');\n return;\n }\n\n // Remove any Ad label on the LEFT side (previous sibling)\n this.removeLeftAdLabel(link);\n\n // Create the Ad label as a <sub> element\n const subLabel = document.createElement('sub');\n subLabel.textContent = 'Ad';\n subLabel.style.fontSize = this.labelStyle.fontSize;\n subLabel.style.fontWeight = this.labelStyle.fontWeight;\n subLabel.style.color = this.labelStyle.color;\n subLabel.style.marginLeft = this.labelStyle.marginLeft;\n\n // Add tooltip styling with default cursor (not help cursor)\n subLabel.style.cursor = 'pointer';\n subLabel.style.borderBottom = `1px dotted ${this.labelStyle.color}`;\n subLabel.style.whiteSpace = 'nowrap';\n subLabel.title = 'Why this ad? This is a sponsored recommendation based on your search query.';\n\n // Track tooltip state for click interactions\n let isTooltipVisible = false;\n\n // Add hover effect for visual feedback\n subLabel.addEventListener('mouseenter', () => {\n subLabel.style.opacity = '0.7';\n });\n\n subLabel.addEventListener('mouseleave', () => {\n subLabel.style.opacity = '1';\n // Hide tooltip on mouse leave if it was shown by click\n if (isTooltipVisible) {\n isTooltipVisible = false;\n }\n });\n\n // Add click handler to toggle tooltip visibility\n subLabel.addEventListener('click', (event: Event) => {\n event.stopPropagation();\n isTooltipVisible = !isTooltipVisible;\n\n if (isTooltipVisible) {\n // Show tooltip by adding visual indicator\n subLabel.style.textDecoration = 'underline';\n subLabel.style.opacity = '0.7';\n } else {\n // Hide tooltip visual indicator\n subLabel.style.textDecoration = 'none';\n subLabel.style.opacity = '1';\n }\n });\n\n // Close tooltip when clicking elsewhere on the page\n const closeTooltipOnClickOutside = (event: Event) => {\n if (isTooltipVisible && event.target !== subLabel) {\n isTooltipVisible = false;\n subLabel.style.textDecoration = 'none';\n subLabel.style.opacity = '1';\n }\n };\n\n document.addEventListener('click', closeTooltipOnClickOutside);\n\n // Insert the label immediately after the link (to the right)\n // Handle edge cases: if nextSibling is null, appendChild will insert at the end\n try {\n const nextSibling = link.nextSibling;\n if (nextSibling) {\n parentNode.insertBefore(subLabel, nextSibling);\n logger.log('[WeaveResponseProcessor] ✅ Ad label inserted before next sibling');\n } else {\n // If no next sibling, append to parent (inserts after link)\n parentNode.appendChild(subLabel);\n logger.log('[WeaveResponseProcessor] ✅ Ad label appended to parent (no next sibling)');\n }\n \n // Verify label was successfully inserted\n if (subLabel.isConnected && subLabel.parentNode === parentNode) {\n logger.log('[WeaveResponseProcessor] ✅ Ad label successfully added to link:', link.href);\n } else {\n logger.error('[WeaveResponseProcessor] ❌ Ad label insertion failed - label not in DOM');\n }\n } catch (error) {\n logger.error('[WeaveResponseProcessor] ❌ Error inserting Ad label:', error);\n }\n }\n\n /**\n * Remove Ad label from the LEFT side (previous sibling) of a link\n *\n * This ensures that only ONE Ad label appears on the RIGHT side,\n * removing any duplicate labels that might be on the left.\n */\n private removeLeftAdLabel(link: HTMLAnchorElement): void {\n let prevNode = link.previousSibling;\n\n // Skip text nodes that are just whitespace\n while (prevNode && prevNode.nodeType === Node.TEXT_NODE) {\n const text = prevNode.textContent || '';\n if (text.trim() === '') {\n prevNode = prevNode.previousSibling;\n continue;\n }\n // If we find non-whitespace text containing Ad, remove it\n if (text.includes('Ad')) {\n prevNode.parentNode?.removeChild(prevNode);\n return;\n }\n break;\n }\n\n // Check if previous element node is a <sub> or <span> with Ad label\n if (prevNode && prevNode.nodeType === Node.ELEMENT_NODE) {\n const element = prevNode as HTMLElement;\n if ((element.tagName === 'SUB' || element.tagName === 'SPAN') &&\n element.textContent?.includes('Ad')) {\n element.parentNode?.removeChild(element);\n }\n }\n }\n\n /**\n * Check if a URL is an AdMesh link\n *\n * Detects AdMesh links by checking if the URL contains /click/ and matches AdMesh patterns:\n * - https://api.useadmesh.com/click/...\n * - https://api.useadmesh.com/click/...\n * - http://localhost:8000/click/... (local development)\n * - Any URL with /click/ that looks like an AdMesh tracking URL\n */\n private isAdMeshLink(href: string): boolean {\n if (!href) {\n return false;\n }\n\n // Check if URL contains /click/ (AdMesh tracking pattern)\n if (!href.includes('/click/')) {\n return false;\n }\n\n // Check for known AdMesh domains\n const admeshDomains = [\n 'useadmesh.com',\n 'admesh.com',\n 'api.useadmesh.com',\n 'api.admesh.com',\n 'localhost:8000', // Local development\n 'localhost:3000', // Local development (if proxied)\n ];\n\n const isKnownDomain = admeshDomains.some(domain => href.includes(domain));\n if (isKnownDomain) {\n return true;\n }\n\n // Fallback: if URL has /click/ and looks like a tracking URL, treat it as AdMesh\n // This handles cases where the domain might be different but the pattern matches\n try {\n const url = new URL(href);\n const pathname = url.pathname;\n\n // Check if pathname starts with /click/ (AdMesh pattern)\n if (pathname.startsWith('/click/')) {\n return true;\n }\n } catch {\n // If URL parsing fails, check string pattern\n if (href.match(/\\/click\\/[a-zA-Z0-9\\-_]+/)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Extract recommendation ID from AdMesh click URL\n *\n * URL format: https://api.useadmesh.com/click/{recommendation_id}?...\n * Returns the recommendation_id portion or empty string if extraction fails\n */\n private extractRecommendationIdFromUrl(url: string): string {\n try {\n // Try to extract from /click/{id} pattern\n const match = url.match(/\\/click\\/([^/?]+)/);\n if (match && match[1]) {\n return match[1];\n }\n // Fallback to empty string (recommendation_id should be in URL)\n return '';\n } catch {\n return url;\n }\n }\n\n /**\n * Convert AdMesh click URL to exposure URL (Weave Ad Format only)\n *\n * This is ONLY used for Weave Ad Format where the LLM embeds click URLs in the response text\n * and we need to derive the exposure URL for tracking.\n *\n * Click URL format: https://api.useadmesh.com/click/r/{aid}?aid={aid}&rid={rid}&nonce={nonce}&exp={exp}&sig={sig}\n * Exposure URL format: https://api.useadmesh.com/exposure?aid={aid}&rid={rid}&nonce={nonce}&exp={exp}&sig={sig}&cpx={cpx}\n *\n * This method:\n * 1. Parses the click URL to extract the base domain and query parameters\n * 2. Replaces the /click/r/{aid} path with /exposure\n * 3. Preserves all tracking parameters (aid, rid, nonce, exp, sig)\n * 4. Adds cpx=0 as default (actual CPX value is set server-side)\n *\n * @param clickUrl - The AdMesh click tracking URL\n * @returns The corresponding exposure tracking URL, or the original URL if conversion fails\n */\n private convertClickUrlToExposureUrl(clickUrl: string): string {\n try {\n const url = new URL(clickUrl);\n\n // Extract the base URL (protocol + host)\n const baseUrl = `${url.protocol}//${url.host}`;\n\n // Build exposure endpoint URL\n const exposureUrl = `${baseUrl}/exposure`;\n\n // Preserve all existing query parameters from click URL\n // These include: aid, rid, nonce, exp, sig\n const params = new URLSearchParams(url.search);\n\n // Add cpx parameter if not present (default to 0, actual value is set server-side)\n if (!params.has('cpx')) {\n params.set('cpx', '0');\n }\n\n // Construct final exposure URL with all parameters\n return `${exposureUrl}?${params.toString()}`;\n } catch (error) {\n // If URL parsing fails, log warning and return original URL\n logger.warn('[WeaveResponseProcessor] Failed to convert click URL to exposure URL');\n return clickUrl;\n }\n }\n\n /**\n * Watch container for new links (streaming support)\n */\n watchForNewLinks(\n container: HTMLElement,\n recommendations: any[],\n onExposurePixel?: (target: ExposurePixelTarget) => void\n ): void {\n if (!container) {\n return;\n }\n\n // Stop existing observer\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n }\n\n // Create observer for new nodes\n this.mutationObserver = new MutationObserver(() => {\n this.scanAndProcessLinks(container, recommendations, onExposurePixel);\n });\n\n this.mutationObserver.observe(container, {\n childList: true,\n subtree: true,\n characterData: false\n });\n }\n\n /**\n * Stop watching for new links\n */\n stopWatching(): void {\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n }\n\n /**\n * Clear processed links cache\n */\n clearCache(): void {\n this.processedLinks.clear();\n }\n}\n\nexport default WeaveResponseProcessor;\n","import { useAdMeshContext } from '../context/AdMeshContext';\n\n/**\n * Hook to access AdMesh SDK and tracking state\n *\n * Must be used within an <AdMeshProvider>\n *\n * @returns Object with SDK instance and tracking methods\n *\n * @example\n * ```tsx\n * const { sdk, sessionId, markMessageAsProcessed } = useAdMesh();\n *\n * // Use SDK to show recommendations\n * await sdk?.showRecommendations({\n * query: 'user query',\n * containerId: 'recommendations-container',\n * sessionId,\n * messageId\n * });\n *\n * // Mark message as processed to avoid duplicates\n * markMessageAsProcessed(messageId);\n * ```\n */\nexport function useAdMesh() {\n const context = useAdMeshContext();\n\n return {\n /** AdMesh SDK instance */\n sdk: context.sdk,\n\n /** API key */\n apiKey: context.apiKey,\n\n /** Session ID */\n sessionId: context.sessionId,\n\n /** Theme configuration */\n theme: context.theme,\n\n /** User language in BCP 47 format (e.g., \"en-US\") - from AdMeshProvider */\n language: context.language,\n\n /** Detailed user location from AdMeshProvider */\n location: context.location,\n\n /** Anonymous hashed user ID - from AdMeshProvider */\n userId: context.userId,\n\n /** AI model identifier (e.g., \"gpt-4o\") - from AdMeshProvider */\n model: context.model,\n\n /** Conversation history - from AdMeshProvider */\n messages: context.messages,\n\n /** Set of processed message IDs (for deduplication) */\n processedMessageIds: context.processedMessageIds,\n\n /** Ephemeral per-session recommendation results keyed by messageId */\n recommendationResults: context.recommendationResults,\n activeDelegationSession: context.activeDelegationSession,\n\n /** Mark a message as processed to prevent duplicate recommendations */\n markMessageAsProcessed: context.markMessageAsProcessed,\n\n /** Check if a message has already been processed */\n isMessageProcessed: context.isMessageProcessed,\n\n /** Store the recommendation result for a message within the current provider session */\n setRecommendationResult: context.setRecommendationResult,\n\n /** Read a stored recommendation result for a message within the current provider session */\n getRecommendationResult: context.getRecommendationResult,\n\n /** Check whether a recommendation result exists for a message within the current provider session */\n hasRecommendationResult: context.hasRecommendationResult,\n setActiveDelegationSession: context.setActiveDelegationSession,\n getActiveDelegationSession: context.getActiveDelegationSession,\n hasActiveDelegationSession: context.hasActiveDelegationSession,\n refreshDelegationActivity: context.refreshDelegationActivity,\n stopDelegationSession: context.stopDelegationSession,\n };\n}\n\nexport default useAdMesh;\n","'use client';\n\nimport type { FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { PlatformResponse, AdMeshTheme } from '../types/index';\nimport { AdMeshSDK } from '../sdk/AdMeshSDK';\nimport { AdMeshViewabilityTracker } from './AdMeshViewabilityTracker';\n\nexport interface AdMeshFollowupProps {\n recommendation: PlatformResponse;\n theme?: AdMeshTheme;\n sdk: AdMeshSDK;\n sessionId: string;\n onExecuteQuery?: (query: string) => void | Promise<void>;\n}\n\nconst PlusIcon = ({ className, size = 20 }: { className?: string; size?: number }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n);\n\n/**\n * AdMeshFollowup - Sponsored Follow-up Component\n * \n * Displays sponsored follow-up suggestions as optional fields on any recommendation.\n * Follow-ups use the same recommendation_id as the primary ad and are rendered separately\n * in a followups_container_id. This component handles all exposure and engagement tracking\n * internally - platforms only need to provide an onExecuteQuery hook for query execution.\n * \n * @example\n * ```tsx\n * <AdMeshFollowup\n * recommendation={recommendation}\n * sdk={sdk}\n * sessionId={sessionId}\n * theme={theme}\n * onExecuteQuery={(query) => {\n * // Platform's query execution logic\n * executeQuery(query);\n * }}\n * />\n * ```\n */\nexport const AdMeshFollowup: FC<AdMeshFollowupProps> = ({\n recommendation,\n theme: _theme,\n sdk,\n sessionId,\n onExecuteQuery,\n}) => {\n const followupSuggestion =\n recommendation.recommendation?.creative?.follow_up_suggestion &&\n recommendation.tracking?.followup_engagement_url &&\n recommendation.tracking?.followup_exposure_url\n ? {\n query: recommendation.recommendation.creative.follow_up_suggestion,\n engagement_url: recommendation.tracking.followup_engagement_url,\n exposure_url: recommendation.tracking.followup_exposure_url,\n }\n : null;\n const followupQuery = followupSuggestion?.query;\n const followupEngagementUrl = followupSuggestion?.engagement_url;\n const followupExposureUrl = followupSuggestion?.exposure_url;\n const recommendationId = recommendation.recommendation_id;\n const productId = recommendation.recommendation?.offerId || recommendationId;\n\n // Validate required fields\n if (!followupQuery || !followupEngagementUrl || !followupExposureUrl) {\n logger.log('[AdMeshFollowup] Missing followup_suggestion.query, engagement_url, or exposure_url - not rendering');\n return null;\n }\n\n // Handle follow-up click/selection\n const handleFollowupClick = async () => {\n try {\n // Fire engagement tracking (SDK handles this automatically)\n if (followupEngagementUrl && recommendationId) {\n logger.log('[AdMeshFollowup] 🎯 Firing follow-up engagement tracking');\n await sdk.fireFollowupEngagement(followupEngagementUrl, recommendationId, sessionId);\n }\n\n // Execute query via platform hook\n if (onExecuteQuery && followupQuery) {\n logger.log(`[AdMeshFollowup] 🔍 Executing query: ${followupQuery}`);\n await onExecuteQuery(followupQuery);\n } else {\n logger.warn('[AdMeshFollowup] ⚠️ onExecuteQuery not provided - cannot execute query');\n }\n } catch (error) {\n logger.error('[AdMeshFollowup] ❌ Error handling follow-up click:', error);\n }\n };\n\n // Platform-native styling (matching Perplexica's \"Related\" section)\n // We use inline styles that can be overridden, but default to blending in\n\n return (\n <AdMeshViewabilityTracker\n productId={productId}\n recommendationId={recommendationId || ''}\n exposureUrl={followupExposureUrl}\n sessionId={sessionId}\n className=\"admesh-followup-container\"\n style={{\n width: '100%',\n }}\n >\n <div className=\"flex flex-col space-y-3 text-sm admesh-followup-wrapper\">\n {/* Divider matching platform style */}\n <div className=\"h-px w-full bg-[#E5E5E5] dark:bg-[#262626] admesh-divider\" />\n\n <div\n onClick={handleFollowupClick}\n className=\"cursor-pointer flex flex-row justify-between font-medium space-x-2 items-center group\"\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n handleFollowupClick();\n }\n }}\n aria-label={`Sponsored follow-up: ${followupQuery}`}\n >\n <p className=\"transition duration-200 text-[#000] dark:text-[#FFF] hover:text-[#24A0ED] admesh-followup-text\">\n {followupQuery}\n </p>\n <div className=\"flex flex-row items-center space-x-2\">\n <span className=\"text-xs text-gray-500 dark:text-gray-400 italic admesh-ad-label\">\n Ad\n </span>\n <PlusIcon\n size={20}\n className=\"text-[#24A0ED] flex-shrink-0 admesh-plus-icon\"\n />\n </div>\n </div>\n </div>\n </AdMeshViewabilityTracker>\n );\n};\n","'use client';\n\nimport { useCallback, useEffect, useState, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useAdMesh } from '../hooks/useAdMesh';\nimport { logger } from '../utils/logger';\nimport { AdMeshCompactCard } from './AdMeshCompactCard';\nimport { AdMeshFollowup } from './AdMeshFollowup';\nimport type {\n PlatformResponse,\n DelegationActivationPayload,\n ActiveDelegationSession,\n} from '../types/index';\n\nexport interface AdMeshRecommendationsProps {\n /** Optional callback when recommendations are shown */\n onRecommendationsShown?: (messageId: string, recommendation: PlatformResponse | null) => void;\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /**\n * Message ID for per-message recommendations.\n *\n * This is the primary identifier for fetching recommendations for a specific message.\n */\n messageId?: string;\n\n /**\n * User query text for generating recommendations.\n *\n * This is the query that will be used to fetch recommendations from the backend.\n * Typically the user's question or search query.\n *\n * IMPORTANT: This should be a non-empty string. If not provided or empty,\n * the component will skip rendering to prevent 400 Bad Request errors.\n * The backend requires a valid query parameter.\n */\n query?: string;\n\n /** Legacy bridge CTA callback; prefer onStartDelegation. */\n onPasteToInput?: (content: string) => void;\n\n /** Called when the SDK needs host approval before starting a delegated brand flow. */\n onDelegationConsent?: (recommendation: PlatformResponse) => boolean | Promise<boolean>;\n\n /** Called with normalized delegation metadata after consent/engagement. */\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n\n /** Called after consent is granted so the host can create/open the delegation session. */\n onStartDelegation?: (recommendation: PlatformResponse) => void | Promise<void>;\n\n /**\n * Optional container ID for follow-up suggestions.\n * When provided and the recommendation includes a followup_suggestion,\n * the SDK will automatically render the follow-up in this container.\n */\n followups_container_id?: string;\n\n /**\n * Callback to execute query when follow-up is selected (required for follow-up functionality).\n * When a user clicks on a follow-up suggestion, this callback is invoked with the followup_suggestion.query.\n * This allows the platform to continue the conversation with the sponsored follow-up query.\n */\n onExecuteQuery?: (query: string) => void | Promise<void>;\n\n /**\n * Callback when a sponsored followup is detected.\n * This allows third-party applications to integrate the sponsored followup query into their own\n * followup suggestions UI (e.g., adding to a suggestions list, related questions section, etc.).\n * \n * When a user clicks the followup suggestion, the application should:\n * 1. Fire engagement tracking by calling the followupEngagementUrl\n * 2. Execute the followupQuery (e.g., submit it as a new user query)\n * \n * @param followupQuery - The sponsored followup query text to display to the user\n * @param followupEngagementUrl - The engagement tracking URL to call when user clicks the followup\n * @param recommendationId - The recommendation ID for tracking and correlation\n * \n * @example\n * ```tsx\n * <AdMeshRecommendations\n * onFollowupDetected={(query, engagementUrl, recId) => {\n * // Add to your suggestions list\n * setSuggestions(prev => [...prev, {\n * text: query,\n * sponsored: true,\n * engagementUrl,\n * recommendationId: recId\n * }]);\n * }}\n * />\n * ```\n */\n\n onFollowupDetected?: (\n followupSuggestion: any, // Will be updated to proper type later\n recommendationId: string,\n ) => void;\n\n /**\n * Signal indicating if the followup container is ready in the DOM.\n * \n * Useful for scenarios where the container is rendered conditionally or after a delay (e.g. streaming).\n * If provided, the component will wait until this is true before attempting to attach the portal.\n */\n isContainerReady?: boolean;\n\n /**\n * Optional user ID to override the context-provided user ID.\n * Useful for per-message or specific user tracking scenarios.\n */\n userId?: string;\n\n /**\n * Optional pre-fetched canonical platform result from an upstream backend flow.\n * When provided, the component reuses this payload and skips calling /aip/context.\n */\n initialRecommendation?: PlatformResponse;\n\n /**\n * Whether the rendered recommendation card should fire its primary exposure URL.\n * Defaults to true. Set false when the recommendation came from a sponsored follow-up click\n * and the click should only count as follow-up engagement.\n */\n triggerExposureUrl?: boolean;\n}\n\n/**\n * AdMeshRecommendations - Citation/Product Format Recommendation Display\n *\n * Displays recommendations as a separate UI component. Handles all the complexity:\n * - Uses provided messageId directly\n * - Generates container IDs for recommendations\n * - Calls SDK's showRecommendations()\n *\n * For Weave Ad Format (where AdMesh links are embedded in LLM response),\n * use WeaveAdFormatContainer component instead.\n *\n * @example\n * ```tsx\n * // Per-message recommendations with messageId\n * <AdMeshProvider apiKey={apiKey} sessionId={sessionId}>\n * {messages.map((msg) => (\n * <div key={msg.messageId}>\n * {msg.content}\n * {msg.role === 'assistant' && (\n * <AdMeshRecommendations\n * messageId={msg.messageId}\n * query={msg.userQuery}\n * />\n * )}\n * </div>\n * ))}\n * </AdMeshProvider>\n * ```\n *\n * @example\n * ```tsx\n * // Format is auto-detected from brand agent's preferred_format\n * <AdMeshProvider apiKey={apiKey} sessionId={sessionId}>\n * <Chat messages={messages} />\n * <AdMeshRecommendations\n * messageId={lastMessageId}\n * query=\"best CRM for small business\"\n * />\n * </AdMeshProvider>\n * ```\n */\nexport const AdMeshRecommendations = ({\n onRecommendationsShown,\n onError,\n messageId,\n query,\n userId: propUserId,\n initialRecommendation,\n triggerExposureUrl = true,\n followups_container_id,\n onPasteToInput,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n onExecuteQuery,\n onFollowupDetected,\n isContainerReady,\n}: AdMeshRecommendationsProps) => {\n const {\n sdk,\n sessionId,\n apiKey,\n language,\n location,\n userId: contextUserId,\n model,\n messages,\n theme,\n getRecommendationResult,\n hasRecommendationResult,\n setRecommendationResult,\n activeDelegationSession,\n setActiveDelegationSession,\n hasActiveDelegationSession,\n } = useAdMesh();\n const isFilledAuctionResponse = (\n response: PlatformResponse | null | undefined,\n ): response is PlatformResponse => {\n return !!response && response.status === 'generated' && !!response.recommendation;\n };\n \n // Use prop userId if provided, otherwise context userId\n const userId = propUserId || contextUserId;\n\n const [platformResult, setPlatformResult] = useState<PlatformResponse | null>(null);\n const [detectedFormat, setDetectedFormat] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // Track fetched messageId to prevent duplicate fetches\n const fetchedMessageIdRef = useRef<string | null>(null);\n const isFetchingRef = useRef<boolean>(false);\n const reusedInitialRecommendationRef = useRef<boolean>(false);\n\n // Use refs for callbacks to avoid dependency issues\n const onRecommendationsShownRef = useRef(onRecommendationsShown);\n const onErrorRef = useRef(onError);\n\n // Update refs when callbacks change\n useEffect(() => {\n onRecommendationsShownRef.current = onRecommendationsShown;\n onErrorRef.current = onError;\n }, [onRecommendationsShown, onError]);\n\n // Reset fetched ref when messageId changes\n useEffect(() => {\n if (fetchedMessageIdRef.current !== messageId) {\n fetchedMessageIdRef.current = null;\n reusedInitialRecommendationRef.current = false;\n setPlatformResult(null);\n setDetectedFormat(null);\n }\n }, [messageId]);\n\n const hasActiveDelegatedSessionForConversation =\n hasActiveDelegationSession() &&\n activeDelegationSession?.session_id === sessionId;\n\n useEffect(() => {\n if (!messageId || !hasRecommendationResult(messageId)) {\n return;\n }\n\n if (hasActiveDelegatedSessionForConversation) {\n return;\n }\n\n const storedResult = getRecommendationResult(messageId);\n if (!storedResult) {\n logger.log('[AdMeshRecommendations] ♻️ Reusing stored no_match result from provider state');\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n return;\n }\n\n let selectedFormat: string = storedResult.recommendation?.format || 'tail';\n if (selectedFormat === 'weave' || selectedFormat === 'product_card') {\n selectedFormat = 'tail';\n }\n\n logger.log('[AdMeshRecommendations] ♻️ Reusing stored recommendation result from provider state', {\n messageId,\n recommendationId: storedResult.recommendation_id,\n format: storedResult.recommendation?.format,\n });\n setPlatformResult(storedResult);\n setDetectedFormat(selectedFormat);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n onRecommendationsShownRef.current?.(messageId, storedResult);\n }, [getRecommendationResult, hasRecommendationResult, hasActiveDelegatedSessionForConversation, messageId]);\n\n // Reuse upstream recommendation payload when available to avoid a second /aip/context call.\n useEffect(() => {\n if (!initialRecommendation || !messageId) {\n return;\n }\n\n if (hasActiveDelegatedSessionForConversation) {\n return;\n }\n\n try {\n const canonicalResponse = initialRecommendation;\n const initialStatus = initialRecommendation.status || 'unknown';\n if (!isFilledAuctionResponse(canonicalResponse)) {\n if (initialStatus === 'no_match') {\n logger.log('[AdMeshRecommendations] ℹ️ Initial recommendation returned no_match - rendering nothing');\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n setRecommendationResult(messageId, null);\n return;\n }\n throw new Error(`Initial recommendation is not a filled auction response (status=${initialStatus})`);\n }\n\n let selectedFormat: string = canonicalResponse.recommendation?.format || 'tail';\n if (selectedFormat === 'weave' || selectedFormat === 'product_card') {\n selectedFormat = 'tail';\n }\n\n setPlatformResult(canonicalResponse);\n setDetectedFormat(selectedFormat);\n setError(null);\n setIsLoading(false);\n fetchedMessageIdRef.current = messageId;\n isFetchingRef.current = false;\n reusedInitialRecommendationRef.current = true;\n setRecommendationResult(messageId, canonicalResponse);\n onRecommendationsShownRef.current?.(messageId, canonicalResponse);\n\n logger.log('[AdMeshRecommendations] ♻️ Using initial recommendation payload, skipping /aip/context fetch');\n logger.log('[AdMeshRecommendations] ✅ Accepted initial generated recommendation payload', {\n messageId,\n recommendationId: canonicalResponse.recommendation_id,\n format: canonicalResponse.recommendation?.format,\n brandName: canonicalResponse.recommendation?.creative?.brand_name,\n headline: canonicalResponse.recommendation?.creative?.headline,\n hasTracking: !!canonicalResponse.tracking,\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n reusedInitialRecommendationRef.current = false;\n logger.warn(`[AdMeshRecommendations] ⚠️ Failed to reuse initial recommendation, will fall back to fetch: ${error.message}`);\n }\n }, [hasActiveDelegatedSessionForConversation, initialRecommendation, messageId, setRecommendationResult]);\n\n // Single fetch effect - fetch recommendation once and detect format\n useEffect(() => {\n // Validate required parameters\n if (!messageId || !query || query.trim() === '') {\n logger.log('[AdMeshRecommendations] ❌ Validation failed - missing required parameters');\n setIsLoading(false);\n return;\n }\n\n if (hasActiveDelegatedSessionForConversation) {\n logger.log('[AdMeshRecommendations] ⏸️ Delegated session active, skipping /aip/context fetch', {\n messageId,\n conversationSessionId: sessionId,\n delegationSessionId: activeDelegationSession?.delegation_session_id,\n });\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n isFetchingRef.current = false;\n return;\n }\n\n if (!sdk?.fetchPlatformResponse) {\n logger.log('[AdMeshRecommendations] SDK fetchPlatformResponse not available');\n setIsLoading(false);\n return;\n }\n\n if (reusedInitialRecommendationRef.current) {\n logger.log('[AdMeshRecommendations] ⏭️ Initial recommendation provided, skipping duplicate fetch');\n return;\n }\n\n // Prevent duplicate fetches for the same messageId\n if (fetchedMessageIdRef.current === messageId) {\n logger.log('[AdMeshRecommendations] ⏭️ Already fetched for this messageId, skipping duplicate fetch');\n return;\n }\n\n // Prevent concurrent fetches\n if (isFetchingRef.current) {\n logger.log('[AdMeshRecommendations] ⏭️ Fetch already in progress, skipping duplicate fetch');\n return;\n }\n\n logger.log('[AdMeshRecommendations] 📤 Fetching recommendation from /aip/context (single fetch)');\n\n const fetchRecommendations = async () => {\n try {\n isFetchingRef.current = true;\n setIsLoading(true);\n setError(null);\n\n // Single fetch call\n // Note: messages is optional - only pass if available\n const result = await sdk.fetchPlatformResponse({\n query: query.trim(),\n sessionId: sessionId,\n messageId: messageId, // REQUIRED: messageId is mandatory\n language: language,\n location: location,\n userId: userId,\n model: model,\n ...(messages && messages.length > 0 && { messages }), // Optional: only pass if messages exist\n });\n const resultStatus = (result as any)?.status || 'unknown';\n if (!isFilledAuctionResponse(result)) {\n if (resultStatus === 'no_match') {\n logger.log('[AdMeshRecommendations] ℹ️ No recommendation returned from /aip/context');\n setPlatformResult(null);\n setDetectedFormat(null);\n setError(null);\n setIsLoading(false);\n isFetchingRef.current = false;\n fetchedMessageIdRef.current = messageId;\n setRecommendationResult(messageId, null);\n return;\n }\n throw new Error(`No filled recommendation returned from /aip/context (status=${resultStatus})`);\n }\n\n setPlatformResult(result);\n logger.log('[AdMeshRecommendations] ✅ Accepted fetched generated recommendation payload', {\n messageId,\n recommendationId: result.recommendation_id,\n format: result.recommendation?.format,\n brandName: result.recommendation?.creative?.brand_name,\n headline: result.recommendation?.creative?.headline,\n hasTracking: !!result.tracking,\n });\n\n let selectedFormat: string = result.recommendation?.format || 'tail';\n if (selectedFormat === 'weave' || selectedFormat === 'product_card') {\n selectedFormat = 'tail';\n }\n\n setDetectedFormat(selectedFormat);\n fetchedMessageIdRef.current = messageId; // Mark as fetched\n setRecommendationResult(messageId, result);\n logger.log('[AdMeshRecommendations] 📊 Format detection:', {\n preferred_format: result.recommendation?.format,\n selected_format: selectedFormat\n });\n\n setIsLoading(false);\n isFetchingRef.current = false;\n onRecommendationsShownRef.current?.(messageId, result);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n // Log error but don't break the UI - network errors are expected in some scenarios\n if (error.message.includes('Failed to fetch') || error.message.includes('NetworkError')) {\n logger.warn(`[AdMeshRecommendations] ⚠️ Network error fetching recommendations(non - critical): ${error.message} `);\n } else {\n logger.error(`[AdMeshRecommendations] ❌ Error fetching recommendations: ${error.message} `);\n }\n setError(error);\n setIsLoading(false);\n isFetchingRef.current = false;\n onErrorRef.current?.(error);\n }\n };\n\n fetchRecommendations();\n }, [\n activeDelegationSession?.delegation_session_id,\n hasActiveDelegatedSessionForConversation,\n sdk,\n sessionId,\n messageId,\n query,\n language,\n location,\n userId,\n model,\n initialRecommendation,\n setRecommendationResult,\n ]); // Removed messages, onRecommendationsShown, onError from dependencies\n\n useEffect(() => {\n if (!platformResult || !onFollowupDetected) {\n return;\n }\n\n const followupSuggestion =\n platformResult.recommendation?.creative?.follow_up_suggestion &&\n platformResult.tracking?.followup_engagement_url &&\n platformResult.tracking?.followup_exposure_url\n ? {\n label: platformResult.recommendation.creative.follow_up_suggestion,\n query: platformResult.recommendation.creative.follow_up_suggestion,\n engagement_url: platformResult.tracking.followup_engagement_url,\n exposure_url: platformResult.tracking.followup_exposure_url,\n }\n : null;\n if (!followupSuggestion) {\n return;\n }\n\n onFollowupDetected(followupSuggestion, platformResult.recommendation_id);\n }, [platformResult, onFollowupDetected]);\n\n const handleSdkDelegationActivated = useCallback(\n async (payload: DelegationActivationPayload) => {\n if (!sdk || !sessionId) {\n throw new Error('AdMesh SDK activation requires an initialized session');\n }\n\n const response = await fetch(`${sdk.getApiBaseUrl()}/aip/delegation/activate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n session_id: sessionId,\n recommendation_id: payload.recommendation_id,\n metadata: payload.metadata,\n }),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new Error(`Failed to activate delegation session: ${response.status} ${errorBody}`);\n }\n\n const activation = await response.json();\n const resolvedPayload: DelegationActivationPayload = {\n ...payload,\n delegation_session_id: activation.delegation_session_id || payload.delegation_session_id,\n session_id: activation.session_id || sessionId,\n brand_id: activation.brand_id || payload.brand_id,\n brand_name: activation.brand_name || payload.brand_name,\n mcp_endpoint: activation.mcp_endpoint,\n eligibility_reason: activation.eligibility_reason || payload.eligibility_reason,\n delegate_reason: activation.delegate_reason || payload.delegate_reason,\n session_goal: activation.session_goal || payload.session_goal,\n desired_outcome_type: activation.desired_outcome_type || payload.desired_outcome_type,\n required_user_inputs: activation.required_user_inputs || payload.required_user_inputs || [],\n required_consent_types: activation.required_consent_types || payload.required_consent_types || [],\n success_outcome: activation.success_outcome || payload.success_outcome,\n fallback_message: activation.fallback_message || payload.fallback_message,\n session_mode: 'inline',\n status: activation.status || 'active',\n capabilities: activation.capabilities || payload.capabilities || [],\n allowed_data_types: activation.allowed_data_types || payload.allowed_data_types || [],\n auth_model: activation.auth_model || payload.auth_model,\n handoff_protocol: activation.handoff_protocol || payload.handoff_protocol,\n supported_actions: activation.supported_actions || payload.supported_actions || [],\n metadata: activation.metadata || payload.metadata,\n };\n\n const activeSession: ActiveDelegationSession = {\n delegation_session_id: activation.delegation_session_id,\n recommendation_id: payload.recommendation_id,\n session_id: activation.session_id || sessionId,\n brand_agent_id: activation.brand_agent_id,\n brand_id: activation.brand_id || payload.brand_id,\n brand_name: activation.brand_name || payload.brand_name || 'Brand',\n mcp_endpoint: activation.mcp_endpoint,\n status: activation.status || 'active',\n activated_at: activation.created_at,\n last_activity_at: activation.updated_at,\n expires_at: activation.expires_at || activation.updated_at,\n eligibility_reason: activation.eligibility_reason || payload.eligibility_reason,\n delegate_reason: activation.delegate_reason || payload.delegate_reason,\n session_goal: activation.session_goal || payload.session_goal,\n desired_outcome_type: activation.desired_outcome_type || payload.desired_outcome_type,\n required_user_inputs: activation.required_user_inputs || payload.required_user_inputs || [],\n required_consent_types: activation.required_consent_types || payload.required_consent_types || [],\n success_outcome: activation.success_outcome || payload.success_outcome,\n fallback_message: activation.fallback_message || payload.fallback_message,\n capabilities: activation.capabilities || payload.capabilities || [],\n allowed_data_types: activation.allowed_data_types || payload.allowed_data_types || [],\n consent_requirements: activation.consent_requirements || payload.consent_requirements || [],\n auth_model: activation.auth_model || payload.auth_model,\n handoff_protocol: activation.handoff_protocol || payload.handoff_protocol,\n supported_actions: activation.supported_actions || payload.supported_actions || [],\n metadata: activation.metadata || payload.metadata,\n };\n\n setActiveDelegationSession(activeSession);\n await sdk\n .trackPublisherAssistantEvent({\n event_name: 'delegation_started',\n timestamp: new Date().toISOString(),\n session_id: sessionId,\n recommendation_id: payload.recommendation_id,\n delegation_session_id: activation.delegation_session_id,\n brand_name: activeSession.brand_name,\n status: activation.status || 'active',\n metadata: {\n brand_agent_id: activation.brand_agent_id,\n source: 'recommendation_card',\n },\n })\n .catch((analyticsError) => {\n logger.warn('[AdMeshRecommendations] ⚠️ Failed to track delegation_started event:', analyticsError);\n });\n await sdk\n .reportDelegationSessionStarted(activeSession, {\n brand_agent_id: activation.brand_agent_id,\n brand_name: activeSession.brand_name,\n })\n .then((updatedSession) => {\n if (updatedSession) {\n setActiveDelegationSession(updatedSession);\n }\n })\n .catch((eventError) => {\n logger.warn('[AdMeshRecommendations] ⚠️ Failed to report delegation session_started event:', eventError);\n });\n\n if (onDelegationActivated) {\n try {\n await onDelegationActivated(resolvedPayload);\n } catch (callbackError) {\n logger.warn(\n '[AdMeshRecommendations] ⚠️ Host onDelegationActivated callback failed after successful delegation activation:',\n callbackError,\n );\n }\n return;\n }\n\n if (onStartDelegation) {\n try {\n await onStartDelegation({\n ...payload.platform_response,\n delegation: {\n ...payload.platform_response.delegation,\n ...resolvedPayload,\n delegation_session_id: activation.delegation_session_id,\n available: true,\n status: activation.status || 'active',\n },\n });\n } catch (callbackError) {\n logger.warn(\n '[AdMeshRecommendations] ⚠️ Host onStartDelegation callback failed after successful delegation activation:',\n callbackError,\n );\n }\n }\n },\n [\n apiKey,\n onDelegationActivated,\n onStartDelegation,\n sdk,\n sessionId,\n setActiveDelegationSession,\n ],\n );\n\n // Don't render anything if validation fails\n if (!messageId || !query || query.trim() === '') {\n return null;\n }\n\n // Show loading state (optional - can be removed if not needed)\n if (isLoading) {\n return null; // Or return a loading spinner if desired\n }\n\n // Show error state (optional - can be removed if not needed)\n if (error) {\n return null; // Error is already handled by onError callback\n }\n\n // Don't render if no recommendation\n if (!platformResult || !detectedFormat) {\n logger.log('[AdMeshRecommendations] 🚫 Nothing to render', {\n messageId,\n hasPlatformResult: !!platformResult,\n detectedFormat,\n isLoading,\n hasError: !!error,\n });\n return null;\n }\n\n logger.log('[AdMeshRecommendations] 🎨 Rendering recommendation component', {\n messageId,\n recommendationId: platformResult.recommendation_id,\n detectedFormat,\n brandName: platformResult.recommendation?.creative?.brand_name,\n headline: platformResult.recommendation?.creative?.headline,\n });\n\n const followupContainer =\n typeof document !== 'undefined' &&\n followups_container_id &&\n (isContainerReady ?? true)\n ? document.getElementById(followups_container_id)\n : null;\n\n return (\n <>\n <div className=\"admesh-recommendations-container\" style={{ marginTop: '1rem' }}>\n <AdMeshCompactCard\n recommendations={[platformResult]}\n theme={theme}\n sessionId={sessionId}\n triggerExposureUrl={triggerExposureUrl}\n onPasteToInput={onPasteToInput}\n onDelegationConsent={onDelegationConsent}\n onDelegationActivated={handleSdkDelegationActivated}\n onStartDelegation={onStartDelegation}\n />\n </div>\n {followupContainer && sdk && sessionId\n ? createPortal(\n <AdMeshFollowup\n recommendation={platformResult}\n theme={theme}\n sdk={sdk}\n sessionId={sessionId}\n onExecuteQuery={onExecuteQuery}\n />,\n followupContainer,\n )\n : null}\n </>\n );\n};\n\nexport default AdMeshRecommendations;\n","'use client';\n\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useAdMesh } from '../hooks/useAdMesh';\nimport { logger } from '../utils/logger';\n\nexport interface WeaveFallbackRecommendationsProps {\n /** Recommendation format for fallback display\n *\n * - 'product': Display as product cards\n * - 'tail': Display as tail format (default)\n */\n format?: 'product' | 'tail';\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /**\n * Message ID for per-message recommendations.\n *\n * This is the primary identifier for fetching recommendations for a specific message.\n */\n messageId: string;\n\n /**\n * User query text for generating recommendations.\n *\n * This is the query that will be used to fetch recommendations from the backend.\n * Typically the user's question or search query.\n *\n * IMPORTANT: This should be a non-empty string. If not provided or empty,\n * the component will skip rendering to prevent 400 Bad Request errors.\n * The backend requires a valid query parameter.\n */\n query?: string;\n\n /**\n * Fallback state - controls whether to show recommendations\n * When true, recommendations will be fetched and displayed\n * When false or undefined, component will not render\n */\n fallback?: boolean;\n\n /**\n * Previously fetched recommendations from WeaveAdFormatContainer.\n * If provided and not empty, these will be rendered directly without making a new API call.\n * Only makes a new API call if this is empty/null/undefined.\n */\n previousRecommendations?: any[]; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\n/**\n * WeaveFallbackRecommendations - Weave Format Fallback Component\n *\n * Displays recommendations as a fallback UI when no AdMesh links are detected\n * in the LLM response. Works independently without requiring WeaveAdFormatContext.\n *\n * This component will:\n * - Accept messageId, query, and fallback state as props\n * - Only render when fallback prop is true\n * - If previousRecommendations are provided and not empty: renders them directly (no API call)\n * - If previousRecommendations are empty/null: calls SDK's showRecommendations() to fetch recommendations\n * - Display recommendations in the specified format (tail or product)\n *\n * IMPORTANT: Pass previousRecommendations from WeaveAdFormatContainer to avoid duplicate API calls.\n *\n * @example\n * ```tsx\n * const [fallback, setFallback] = useState(false);\n *\n * <AdMeshProvider apiKey={apiKey} sessionId={sessionId}>\n * <WeaveAdFormatContainer\n * messageId={message.id}\n * query={userQuery}\n * onFallbackChange={setFallback}\n * >\n * {llmResponseContent}\n * </WeaveAdFormatContainer>\n * <WeaveFallbackRecommendations\n * messageId={message.id}\n * query={userQuery}\n * format=\"tail\"\n * fallback={fallback}\n * previousRecommendations={recommendations} // Pass from WeaveAdFormatContainer\n * />\n * </AdMeshProvider>\n * ```\n */\nexport const WeaveFallbackRecommendations: React.FC<WeaveFallbackRecommendationsProps> = ({\n format = 'tail',\n onError,\n messageId,\n query,\n fallback,\n previousRecommendations,\n}) => {\n const { sdk, sessionId, theme, apiKey, language, location, userId, model, messages } = useAdMesh();\n const containerRef = useRef<HTMLDivElement>(null);\n const [containerId, setContainerId] = useState<string>('');\n\n // Generate container ID based on message ID\n useEffect(() => {\n if (messageId) {\n setContainerId(`admesh-weave-fallback-${messageId}`);\n }\n }, [messageId]);\n\n // Log component render\n logger.log('[WeaveFallbackRecommendations] 🎨 Component render');\n\n useEffect(() => {\n // Log what we're receiving\n logger.log('[WeaveFallbackRecommendations] 🔄 useEffect triggered', {\n fallback,\n hasPreviousRecommendations: previousRecommendations && previousRecommendations.length > 0,\n previousRecommendationsCount: previousRecommendations?.length || 0\n });\n\n // Skip if fallback is not true\n if (!fallback) {\n logger.log('[WeaveFallbackRecommendations] ⏭️ Skipping - fallback is FALSE, not rendering recommendations');\n return;\n }\n\n logger.log('[WeaveFallbackRecommendations] ✅ fallback is TRUE, proceeding with recommendations');\n\n // Validate required parameters\n if (!messageId || !query || query.trim() === '') {\n logger.log('[WeaveFallbackRecommendations] ❌ Validation failed - returning early');\n return;\n }\n\n logger.log('[WeaveFallbackRecommendations] ✅ Validation passed');\n\n if (!sdk || !containerId) {\n logger.log('[WeaveFallbackRecommendations] SDK or containerId not ready');\n return;\n }\n\n // Check if we have previous recommendations to reuse\n const hasPreviousRecs = previousRecommendations && previousRecommendations.length > 0;\n \n logger.log('[WeaveFallbackRecommendations] 📊 Checking previous recommendations:', {\n hasPreviousRecs,\n count: previousRecommendations?.length || 0,\n fallback,\n messageId\n });\n \n if (hasPreviousRecs) {\n // Use previous recommendations - render directly without API call\n logger.log(`[WeaveFallbackRecommendations] ♻️ Reusing ${previousRecommendations.length} previous recommendation(s), skipping API call`);\n \n const renderRecommendations = async () => {\n try {\n const aipResponse = previousRecommendations[0];\n \n logger.log('[WeaveFallbackRecommendations] 📦 Processing AIP response:', {\n hasAipResponse: !!aipResponse,\n recommendationId: aipResponse?.recommendation_id || '',\n format: aipResponse?.recommendation?.format || 'unknown'\n });\n \n // Development logging: Log full recommendation details\n if (aipResponse && process.env.NODE_ENV === 'development') {\n logger.log('[WeaveFallbackRecommendations] 📋 Recommendation received (DEV):', {\n recommendation_id: aipResponse?.recommendation_id,\n click_url:\n aipResponse?.tracking?.click_url ||\n aipResponse?.recommendation?.creative?.landing_page_url,\n format: aipResponse?.recommendation?.format,\n full_response: aipResponse\n });\n }\n \n if (!aipResponse) {\n logger.warn('[WeaveFallbackRecommendations] ⚠️ Previous recommendation is empty, falling back to API call');\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId,\n });\n return;\n }\n\n const sdkAny = sdk as any;\n const getRendererMethod = sdkAny.getRenderer;\n const getTrackerMethod = sdkAny.getTracker;\n const sdkTheme = sdkAny.config?.theme;\n\n if (getRendererMethod && getTrackerMethod) {\n const response = {\n sessionId,\n messageId,\n recommendations: [aipResponse]\n };\n\n // Get renderer and tracker\n const renderer = getRendererMethod.call(sdk);\n const tracker = getTrackerMethod.call(sdk);\n \n // Get apiBaseUrl from SDK instance\n const apiBaseUrl = (sdk as any)?.apiBaseUrl || \n (typeof window !== 'undefined' && (window as any).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n \n // Render directly - pass all required props for AdMeshProvider\n await renderer.render({\n containerId,\n response,\n theme: theme || sdkTheme,\n tracker: tracker,\n sessionId: sessionId,\n apiKey: apiKey || (sdk as any)?.config?.apiKey,\n apiBaseUrl: apiBaseUrl,\n language: language,\n location: location,\n userId: userId,\n model: model,\n messages: messages,\n });\n \n logger.log('[WeaveFallbackRecommendations] ✅ Recommendations rendered from previous response (no API call)');\n } else {\n // SDK methods not accessible - fall back to showRecommendations\n // This will use the cached result from auction coordination, so it's still fast\n logger.warn('[WeaveFallbackRecommendations] ⚠️ SDK internal methods not accessible, using showRecommendations (will use cached result)');\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId,\n });\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n logger.error(`[WeaveFallbackRecommendations] ❌ Error rendering previous recommendations: ${err.message}`);\n // Fallback to API call on error (will use cached result)\n try {\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId,\n });\n } catch (fallbackError) {\n onError?.(err);\n }\n }\n };\n\n renderRecommendations();\n } else {\n // No previous recommendations - make new API call\n logger.log('[WeaveFallbackRecommendations] 📤 No previous recommendations, calling sdk.showRecommendations');\n \n const fetchRecommendations = async () => {\n try {\n if (!sdk?.showRecommendations) {\n logger.log('[WeaveFallbackRecommendations] SDK showRecommendations not available');\n return;\n }\n\n await sdk.showRecommendations({\n query: query.trim(),\n containerId,\n sessionId,\n messageId: messageId, // REQUIRED: messageId must be provided by platform\n });\n\n logger.log('[WeaveFallbackRecommendations] ✅ Recommendations displayed successfully');\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n logger.log(`[WeaveFallbackRecommendations] ❌ Error: ${err.message}`);\n onError?.(err);\n }\n };\n\n fetchRecommendations();\n }\n }, [sdk, sessionId, containerId, format, messageId, query, fallback, onError, previousRecommendations, theme]);\n\n // Don't render anything if fallback is not active or validation fails\n if (!fallback || !messageId || !query || query.trim() === '') {\n return null;\n }\n\n // Render the container where fallback recommendations will be displayed\n // Use display: 'none' initially to prevent taking up space until recommendations are loaded\n // The SDK will set display: 'block' when it renders content\n return (\n <div\n ref={containerRef}\n id={containerId}\n className=\"admesh-weave-fallback-recommendations-container\"\n style={{\n marginTop: '1rem',\n display: 'none', // Hidden by default, SDK will show when recommendations are rendered\n }}\n />\n );\n};\n\nexport default WeaveFallbackRecommendations;\n","'use client';\n\nimport { createContext, useContext, type ReactNode, type FC } from 'react';\n\nexport interface WeaveAdFormatContextType {\n /** Whether the fallback UI should be rendered (no AdMesh links detected) */\n shouldRenderFallback: boolean;\n /** The message ID for this Weave Ad Format container (used for deduplication) */\n messageId: string;\n /** The session ID for this Weave Ad Format container (used for tracking) */\n sessionId?: string;\n /** The query for this message (used for fallback API calls) */\n query?: string;\n}\n\nconst WeaveAdFormatContext = createContext<WeaveAdFormatContextType | undefined>(undefined);\n\nexport const WeaveAdFormatProvider: FC<{\n children: ReactNode;\n shouldRenderFallback: boolean;\n messageId: string;\n sessionId?: string;\n query?: string;\n}> = ({ children, shouldRenderFallback, messageId, sessionId, query }) => {\n return (\n <WeaveAdFormatContext.Provider value={{ shouldRenderFallback, messageId, sessionId, query }}>\n {children}\n </WeaveAdFormatContext.Provider>\n );\n};\n\n/**\n * Hook to access WeaveAdFormatContext\n * \n * Returns the context value if inside a WeaveAdFormatContainer,\n * or undefined if not inside one.\n * \n * @example\n * ```tsx\n * const weaveContext = useWeaveAdFormatContext();\n * if (weaveContext) {\n * // Inside a WeaveAdFormatContainer\n * const { shouldRenderFallback, messageId } = weaveContext;\n * }\n * ```\n */\nexport const useWeaveAdFormatContext = (): WeaveAdFormatContextType | undefined => {\n return useContext(WeaveAdFormatContext);\n};\n\nexport default WeaveAdFormatContext;\n","import { useEffect, useRef, useState, type CSSProperties, type FC } from 'react';\nimport { logger } from '../utils/logger';\nimport type { PlatformResponse, AdMeshTheme, DelegationActivationPayload } from '../types/index';\nimport { AdMeshViewabilityTracker } from './AdMeshViewabilityTracker';\n\nexport interface AdMeshTailAdProps {\n recommendations: PlatformResponse[]; // Canonical platform responses\n theme?: AdMeshTheme;\n className?: string;\n style?: CSSProperties;\n sessionId?: string;\n triggerExposureUrl?: boolean;\n onDelegationConsent?: (recommendation: PlatformResponse) => boolean | Promise<boolean>;\n onDelegationActivated?: (payload: DelegationActivationPayload) => void | Promise<void>;\n onStartDelegation?: (recommendation: PlatformResponse) => void | Promise<void>;\n onPasteToInput?: (content: string) => void;\n}\n\n// Utility function to validate and normalize URLs\nconst isValidUrl = (url: string): boolean => {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n};\n\n// Helper function to get CTA label from backend\nconst getCTALabel = (ctaLabel?: string): string => {\n // Use provided CTA label from backend if available\n if (ctaLabel && ctaLabel.trim()) {\n return ctaLabel.trim();\n }\n\n // Return empty string if no CTA label provided (will hide CTA button)\n return '';\n};\n\nconst getDisplayText = (value: unknown): string => {\n if (typeof value === 'string') {\n return value.trim();\n }\n if (typeof value === 'number') {\n return String(value);\n }\n return '';\n};\n\nconst asOptionalString = (value: unknown): string | undefined => {\n const text = getDisplayText(value);\n return text || undefined;\n};\n\nconst truncateWords = (value: string, maxWords: number): string => {\n const words = value.split(/\\s+/).filter(Boolean);\n if (words.length <= maxWords) {\n return value;\n }\n return `${words.slice(0, maxWords).join(' ')}...`;\n};\n\nconst formatProductPrice = (price: unknown, currency?: string): string => {\n if (price === null || price === undefined || price === '') {\n return '';\n }\n\n if (typeof price === 'number') {\n try {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: 2,\n }).format(price);\n } catch {\n return String(price);\n }\n }\n\n return getDisplayText(price);\n};\n\nconst formatProductDiscount = (\n discount: unknown,\n discountType?: string,\n currency?: string,\n): string => {\n if (discount === null || discount === undefined || discount === '') {\n return '';\n }\n\n const normalizedType = (discountType || 'percentage').trim().toLowerCase();\n\n if (typeof discount === 'number') {\n if (normalizedType === 'amount' || normalizedType === 'fixed' || normalizedType === 'fixed_amount') {\n try {\n const formattedAmount = new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n maximumFractionDigits: 2,\n }).format(discount);\n return `${formattedAmount} off`;\n } catch {\n return `${discount} off`;\n }\n }\n\n return `${discount}% off`;\n }\n\n const text = getDisplayText(discount);\n if (!text) {\n return '';\n }\n if (/%|off/i.test(text)) {\n return text;\n }\n if (normalizedType === 'amount' || normalizedType === 'fixed' || normalizedType === 'fixed_amount') {\n return `${text} off`;\n }\n return `${text}% off`;\n};\n\nconst TAIL_AD_COLORS = {\n surface: '#ffffff',\n surfaceMuted: '#f9fafb',\n surfaceSubtle: '#f8fafc',\n border: 'rgba(17, 24, 39, 0.10)',\n text: '#111827',\n textSecondary: '#4b5563',\n textMuted: '#6b7280',\n link: '#2563eb',\n logoFallbackBg: '#f3f4f6',\n logoFallbackText: '#4b5563',\n productImageFallbackBg: '#e5e7eb',\n successText: '#065f46',\n successBg: '#d1fae5',\n};\n\nexport const AdMeshTailAd: FC<AdMeshTailAdProps> = ({\n recommendations,\n theme,\n className = '',\n style = {},\n sessionId,\n triggerExposureUrl = true,\n onDelegationConsent,\n onDelegationActivated,\n onStartDelegation,\n onPasteToInput,\n}) => {\n // Validate inputs - return null if empty\n if (!recommendations || recommendations.length === 0) {\n logger.log('[AdMesh Tail Ad] No recommendations provided - not rendering');\n return null;\n }\n\n // Get the first recommendation's data for CTA and tracking\n const firstRecommendation = recommendations[0];\n const productId = firstRecommendation?.recommendation?.offerId || '';\n const exposureUrl = firstRecommendation?.tracking?.exposure_url || '';\n const recommendationId = firstRecommendation?.recommendation_id || '';\n const shortDescription = firstRecommendation?.recommendation?.creative?.description || '';\n const disclosure = firstRecommendation?.recommendation?.disclosure || 'Sponsored';\n const brandName = firstRecommendation?.recommendation?.creative?.brand_name || '';\n const productName =\n firstRecommendation?.recommendation?.creative?.headline ||\n firstRecommendation?.recommendation?.creative?.brand_name ||\n '';\n const logoUrl = firstRecommendation?.recommendation?.creative?.logo_url || '';\n const clickUrl =\n firstRecommendation?.tracking?.click_url ||\n firstRecommendation?.recommendation?.creative?.landing_page_url ||\n '';\n const ctaLabel = getCTALabel(firstRecommendation?.recommendation?.creative?.cta_text);\n const relatedProducts = firstRecommendation?.recommendation?.creative?.products || [];\n const hasProductRail = relatedProducts.length > 1;\n const visibleProducts = hasProductRail ? relatedProducts.slice(0, 4) : [];\n const recommendationFormat = firstRecommendation?.recommendation?.format || 'tail';\n const isBridgeRecommendation = recommendationFormat === 'bridge';\n const delegationBrandName = firstRecommendation?.delegation?.brand_name || brandName;\n const hasDelegation = firstRecommendation?.delegation?.available === true;\n const shouldShowDelegationButton = isBridgeRecommendation && hasDelegation;\n const delegationCtaText = 'Talk to Agent';\n const shouldShowPrimaryCta = !hasProductRail && !!ctaLabel && !!clickUrl;\n\n // For tail format, we need at least brand name\n // But we still validate that we have at least one recommendation with data\n if (!brandName && !productName && !shortDescription) {\n logger.log('[AdMesh Tail Ad] No valid recommendation data provided - not rendering', {\n reason: 'brand, headline, and description are missing',\n brandName,\n hasFirstRecommendation: !!firstRecommendation,\n recommendationId,\n recommendationKeys: firstRecommendation ? Object.keys(firstRecommendation) : []\n });\n return null;\n }\n \n // Build headline parts with priority:\n // 1. If offer_summary exists: \"Brand — Offer Summary\"\n // 2. If product_name exists: \"Brand — Product Name\"\n // 3. Otherwise: just \"Brand\"\n let headlineText = brandName;\n let headlineSuffix = '';\n \n if (productName && productName !== brandName) {\n headlineSuffix = productName;\n }\n \n if (headlineSuffix) {\n headlineText = `${brandName} — ${headlineSuffix}`;\n }\n\n logger.debug('[AdMeshTailAd] 📊 Rendering with tracking data:', {\n recommendationId,\n productId,\n exposureUrl: exposureUrl ? 'present' : 'MISSING',\n sessionId: sessionId ? 'present' : 'MISSING',\n recommendationsCount: recommendations.length,\n clickUrl: clickUrl ? clickUrl : 'MISSING',\n clickUrlSource: firstRecommendation?.tracking?.click_url ? 'tracking.click_url' :\n firstRecommendation?.recommendation?.creative?.landing_page_url ? 'recommendation.creative.landing_page_url' :\n 'none',\n shortDescription: shortDescription ? 'present' : 'MISSING',\n brandName,\n productName,\n headlineText,\n triggerExposureUrl\n });\n logger.log('[AdMeshTailAd] ✅ Rendering tail ad', {\n recommendationId,\n brandName,\n productName,\n hasDescription: !!shortDescription,\n hasClickUrl: !!clickUrl,\n hasLogoUrl: !!logoUrl,\n recommendationFormat,\n });\n\n // Handler for tracking clicks on the entire tail ad\n const handleContainerClick = (source: string, e?: React.MouseEvent) => {\n if (e) {\n e.stopPropagation();\n }\n logger.log(`AdMesh tail ad ${source} clicked`);\n if (typeof window !== 'undefined' && (window as any).admeshTracker) {\n (window as any).admeshTracker.trackClick({\n recommendationId,\n productId,\n clickUrl: clickUrl,\n source: source\n }).catch(() => {\n logger.error(`[AdMesh] Failed to track ${source} click`);\n });\n }\n };\n\n // Handler for brand name link click\n const handleBrandNameClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n handleContainerClick('tail_ad_brand_name');\n };\n\n // Handler for CTA link click\n const handleCTAClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n handleContainerClick('tail_ad_cta');\n };\n\n // Handler for logo click\n const handleLogoClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n handleContainerClick('tail_ad_logo');\n };\n\n const handleCardClick = () => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n handleContainerClick('tail_ad_card');\n if (typeof window !== 'undefined') {\n window.open(clickUrl, '_blank', 'noopener,noreferrer');\n }\n };\n\n const handleCardKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (hasProductRail || !clickUrl) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleCardClick();\n }\n };\n\n const requestDefaultConsent = (): boolean => {\n return true;\n };\n\n const [showConsentPrompt, setShowConsentPrompt] = useState(false);\n const consentResolverRef = useRef<((value: boolean) => void) | null>(null);\n\n useEffect(() => {\n return () => {\n if (consentResolverRef.current) {\n consentResolverRef.current(false);\n consentResolverRef.current = null;\n }\n };\n }, []);\n\n const resolveConsentPrompt = (value: boolean) => {\n consentResolverRef.current?.(value);\n consentResolverRef.current = null;\n setShowConsentPrompt(false);\n };\n\n const requestConsent = async (): Promise<boolean> => {\n if (onDelegationConsent) {\n return await onDelegationConsent(firstRecommendation);\n }\n if (!requestDefaultConsent()) {\n return false;\n }\n return await new Promise<boolean>((resolve) => {\n consentResolverRef.current = resolve;\n setShowConsentPrompt(true);\n });\n };\n\n const trackDelegationEngagement = async () => {\n if (!(recommendationId && sessionId)) {\n return;\n }\n\n try {\n const apiBaseUrl =\n (typeof window !== 'undefined' && (window as any).__ADMESH_API_BASE_URL__) ||\n 'https://api.useadmesh.com';\n\n const response = await fetch(`${apiBaseUrl}/click/bridge-engagement`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n recommendation_id: recommendationId,\n session_id: sessionId,\n is_test: false,\n }),\n });\n\n if (!response.ok) {\n logger.warn('[AdMesh Tail Ad] Delegation engagement tracking failed:', response.statusText);\n }\n } catch (error) {\n logger.error('[AdMesh Tail Ad] Error tracking delegation engagement:', error);\n }\n };\n\n const handleDelegationClick = async (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (!firstRecommendation || !shouldShowDelegationButton) {\n return;\n }\n\n handleContainerClick('tail_ad_delegation_cta');\n await trackDelegationEngagement();\n\n const consentGranted = await requestConsent();\n if (!consentGranted) {\n logger.log('[AdMesh Tail Ad] Delegation consent declined');\n return;\n }\n\n const delegation = firstRecommendation.delegation;\n const delegationPayload: DelegationActivationPayload | null =\n delegation?.available\n ? {\n recommendation_id: firstRecommendation.recommendation_id,\n brand_id: asOptionalString(delegation.brand_id),\n brand_name: asOptionalString(\n delegation.brand_name || firstRecommendation.recommendation?.creative?.brand_name,\n ),\n eligibility_reason: asOptionalString(delegation.eligibility_reason),\n delegate_reason: asOptionalString(delegation.delegate_reason),\n session_goal: asOptionalString(delegation.session_goal),\n desired_outcome_type: delegation.desired_outcome_type,\n required_user_inputs: Array.isArray(delegation.required_user_inputs)\n ? delegation.required_user_inputs.filter((value): value is string => typeof value === 'string')\n : [],\n required_consent_types: Array.isArray(delegation.required_consent_types)\n ? delegation.required_consent_types.filter((value): value is string => typeof value === 'string')\n : [],\n success_outcome: asOptionalString(delegation.success_outcome),\n fallback_message: asOptionalString(delegation.fallback_message),\n session_mode: asOptionalString(delegation.session_mode),\n status: asOptionalString(delegation.status),\n capabilities: delegation.capabilities || [],\n allowed_data_types: delegation.allowed_data_types || [],\n consent_requirements: delegation.consent_requirements || [],\n auth_model: asOptionalString(delegation.auth_model),\n handoff_protocol:\n delegation.handoff_protocol && typeof delegation.handoff_protocol === 'object'\n ? delegation.handoff_protocol\n : undefined,\n supported_actions: delegation.supported_actions || [],\n metadata:\n delegation.metadata && typeof delegation.metadata === 'object'\n ? delegation.metadata\n : undefined,\n platform_response: firstRecommendation,\n }\n : null;\n\n if (onDelegationActivated && delegationPayload) {\n await onDelegationActivated(delegationPayload);\n return;\n }\n\n if (onStartDelegation) {\n await onStartDelegation(firstRecommendation);\n return;\n }\n\n const fallbackPrompt = firstRecommendation.recommendation?.creative?.follow_up_suggestion || '';\n if (fallbackPrompt && onPasteToInput) {\n onPasteToInput(fallbackPrompt);\n return;\n }\n\n if (fallbackPrompt && typeof window !== 'undefined' && (window as any).__admesh_setMessage) {\n (window as any).__admesh_setMessage(fallbackPrompt);\n return;\n }\n };\n\n // State for logo load error\n const [logoError, setLogoError] = useState(false);\n\n // Get first letter of brand name for fallback\n const brandInitial = brandName ? brandName.charAt(0).toUpperCase() : 'B';\n\n // Tail ads use their own neutral palette so host light/dark themes cannot\n // make sponsored content unreadable.\n const cardBackground = TAIL_AD_COLORS.surface;\n const cardBorder = TAIL_AD_COLORS.border;\n const cardBorderRadius = theme?.borderRadius || theme?.components?.card?.borderRadius || '8px';\n \n // Shadow styles - definitive shadow for floating feel\n const defaultShadow = '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)';\n const hoverShadow = '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)';\n \n const cardShadow = theme?.shadows?.medium || theme?.components?.card?.boxShadow || defaultShadow;\n const cardHoverShadow = theme?.shadows?.large || hoverShadow;\n\n return (\n <AdMeshViewabilityTracker\n productId={productId}\n recommendationId={recommendationId}\n exposureUrl={exposureUrl}\n sessionId={sessionId}\n triggerExposureUrl={triggerExposureUrl}\n className={`admesh-tail-ad ${className}`}\n style={{\n fontFamily: theme?.fontFamily || '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n lineHeight: 1.4,\n ...style\n }}\n >\n <style>{`\n .admesh-tail-product-scroll {\n -ms-overflow-style: none;\n scrollbar-width: none;\n }\n\n .admesh-tail-product-scroll::-webkit-scrollbar {\n display: none;\n width: 0;\n height: 0;\n }\n `}</style>\n <div \n className=\"tail-ad-container flex flex-col gap-3 sm:flex-row\"\n role={!hasProductRail && clickUrl ? 'link' : undefined}\n tabIndex={!hasProductRail && clickUrl ? 0 : undefined}\n style={{\n ...theme?.components?.card,\n backgroundColor: cardBackground,\n borderRadius: cardBorderRadius,\n padding: '16px',\n boxShadow: cardShadow,\n border: `1px solid ${cardBorder}`,\n color: TAIL_AD_COLORS.text,\n transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',\n transform: 'translateY(0)',\n cursor: !hasProductRail && clickUrl ? 'pointer' : undefined,\n }}\n onClick={handleCardClick}\n onKeyDown={handleCardKeyDown}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow = cardHoverShadow;\n e.currentTarget.style.transform = 'translateY(-2px)';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow = cardShadow;\n e.currentTarget.style.transform = 'translateY(0)';\n }}\n >\n {/* Left Section: Logo Area (10% width, stacks on mobile) */}\n {logoUrl && (\n <div \n className=\"flex-shrink-0 flex items-center justify-start pr-0 sm:justify-center sm:pr-2\"\n style={{\n width: 'auto',\n minWidth: '48px'\n }}\n >\n {!logoError && isValidUrl(logoUrl) ? (\n <a\n href={clickUrl || '#'}\n target={clickUrl ? \"_blank\" : undefined}\n rel={clickUrl ? \"noopener noreferrer\" : undefined}\n onClick={clickUrl ? handleLogoClick : undefined}\n className=\"block\"\n style={{ \n cursor: clickUrl ? 'pointer' : 'default',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '100%',\n maxWidth: '64px'\n }}\n >\n <img\n src={logoUrl}\n alt={`${brandName} logo`}\n className=\"object-cover\"\n style={{\n width: '100%',\n height: 'auto',\n maxWidth: '64px',\n maxHeight: '64px',\n objectFit: 'contain',\n borderRadius: '8px'\n }}\n onError={() => {\n setLogoError(true);\n logger.debug('[AdMesh Tail Ad] Logo failed to load, showing fallback');\n }}\n />\n </a>\n ) : (\n <div\n className=\"flex items-center justify-center text-lg font-semibold\"\n style={{\n width: '100%',\n maxWidth: '64px',\n aspectRatio: '1',\n borderRadius: '8px',\n minHeight: '48px',\n backgroundColor: TAIL_AD_COLORS.logoFallbackBg,\n color: TAIL_AD_COLORS.logoFallbackText,\n fontSize: '18px',\n }}\n >\n {brandInitial}\n </div>\n )}\n </div>\n )}\n\n {/* Right Section: Content Area (90% width) */}\n <div \n className=\"flex-1\"\n style={{\n width: '100%',\n minWidth: 0 // Allow flex item to shrink below content size\n }}\n >\n {/* Headline: Brand Name (clickable link) — Offer Summary / Product Name / Brand only */}\n {headlineText && !hasProductRail && (\n <div className=\"mb-2\">\n <h3 className=\"font-semibold text-base\" style={{ fontSize: '14px', lineHeight: 1.35, color: TAIL_AD_COLORS.text }}>\n {clickUrl && brandName ? (\n <>\n <a\n href={clickUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline transition-colors duration-200 font-semibold\"\n style={{\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textDecorationColor: TAIL_AD_COLORS.link,\n textUnderlineOffset: '2px'\n }}\n onClick={handleBrandNameClick}\n >\n {brandName}\n </a>\n {headlineSuffix && ` — ${headlineSuffix}`}\n </>\n ) : (\n headlineText\n )}\n </h3>\n </div>\n )}\n \n {/* Description: Full short_description */}\n {shortDescription && !hasProductRail && (\n <p className=\"text-sm mb-3 leading-relaxed\" style={{ fontSize: '13px', lineHeight: 1.45, color: TAIL_AD_COLORS.textSecondary }}>\n {shortDescription}\n </p>\n )}\n\n {hasProductRail && visibleProducts.length > 0 && (\n <div className=\"mb-3\">\n <div\n className=\"admesh-tail-product-scroll\"\n style={{\n marginBottom: '8px',\n overflowX: 'auto',\n overflowY: 'hidden',\n WebkitOverflowScrolling: 'touch',\n overscrollBehaviorX: 'contain',\n overscrollBehaviorY: 'none',\n scrollBehavior: 'smooth',\n paddingBottom: '2px',\n }}\n >\n <div\n style={{\n display: 'flex',\n gap: '10px',\n minWidth: 'max-content',\n scrollSnapType: 'x proximity',\n paddingRight: 0,\n }}\n >\n {visibleProducts.map((product) => {\n const productName = getDisplayText(product.product_name) || 'Product';\n const productLink =\n getDisplayText(product.product_link) ||\n getDisplayText(product.product_url) ||\n clickUrl ||\n '#';\n const productDescription = truncateWords(getDisplayText(product.product_description), 10);\n const productPrice = formatProductPrice(product.product_price, product.product_currency);\n const productDiscount = formatProductDiscount(\n product.product_discount,\n product.product_discount_type,\n product.product_currency,\n );\n const productImageUrl = getDisplayText(product.product_image_url);\n const fallbackLogoUrl = logoUrl && isValidUrl(logoUrl) ? logoUrl : '';\n const displayProductImageUrl =\n productImageUrl && isValidUrl(productImageUrl)\n ? productImageUrl\n : fallbackLogoUrl;\n const productCtaLabel = getCTALabel(product.product_cta_label);\n const hasProductLink = productLink !== '#';\n\n return (\n <a\n key={product.product_id || `${recommendationId}-${productName}`}\n href={productLink}\n target={hasProductLink ? '_blank' : undefined}\n rel={hasProductLink ? 'noopener noreferrer' : undefined}\n onClick={(e) => handleContainerClick(`tail_ad_product_${product.product_id || 'item'}`, e)}\n className=\"block\"\n style={{\n border: `1px solid ${cardBorder}`,\n borderRadius: '8px',\n padding: '10px',\n backgroundColor: TAIL_AD_COLORS.surfaceMuted,\n textDecoration: 'none',\n color: TAIL_AD_COLORS.text,\n minWidth: 'min(264px, 82vw)',\n width: 'clamp(220px, 72vw, 312px)',\n flex: '0 0 clamp(220px, 72vw, 312px)',\n scrollSnapAlign: 'start',\n }}\n >\n <div className=\"flex items-start gap-2\">\n {displayProductImageUrl ? (\n <img\n src={displayProductImageUrl}\n alt={productName}\n style={{\n width: '44px',\n height: '44px',\n objectFit: 'cover',\n borderRadius: '6px',\n flexShrink: 0,\n }}\n />\n ) : (\n <div\n className=\"flex items-center justify-center text-xs font-semibold\"\n style={{\n width: '44px',\n height: '44px',\n borderRadius: '6px',\n flexShrink: 0,\n backgroundColor: TAIL_AD_COLORS.productImageFallbackBg,\n color: TAIL_AD_COLORS.textSecondary,\n fontSize: '12px',\n }}\n >\n {productName.charAt(0).toUpperCase()}\n </div>\n )}\n\n <div style={{ minWidth: 0, flex: 1 }}>\n <p\n className=\"font-medium text-sm\"\n style={{\n fontSize: '13px',\n lineHeight: 1.3,\n color: TAIL_AD_COLORS.text,\n marginBottom: '4px',\n }}\n >\n {productName}\n </p>\n\n {productDescription && (\n <p\n className=\"text-xs\"\n style={{\n fontSize: '12px',\n lineHeight: 1.3,\n color: TAIL_AD_COLORS.textSecondary,\n marginBottom: '6px',\n }}\n >\n {productDescription}\n </p>\n )}\n\n {(productPrice || productDiscount) && (\n <div\n className=\"flex items-center gap-2 flex-wrap\"\n style={{\n marginBottom: productCtaLabel ? '6px' : 0,\n }}\n >\n {productPrice && (\n <div className=\"flex items-center gap-1\">\n <span\n style={{\n fontSize: '10px',\n color: TAIL_AD_COLORS.textMuted,\n textTransform: 'uppercase',\n letterSpacing: '0.04em',\n }}\n >\n Price\n </span>\n <span\n className=\"font-semibold\"\n style={{\n fontSize: '13px',\n color: TAIL_AD_COLORS.text,\n }}\n >\n {productPrice}\n </span>\n </div>\n )}\n {productDiscount && (\n <span\n className=\"text-xs\"\n style={{\n fontSize: '11px',\n color: TAIL_AD_COLORS.successText,\n backgroundColor: TAIL_AD_COLORS.successBg,\n borderRadius: '999px',\n padding: '2px 8px',\n fontWeight: 600,\n }}\n >\n {productDiscount}\n </span>\n )}\n </div>\n )}\n\n {productCtaLabel && (\n <span\n className=\"font-medium\"\n style={{\n fontSize: '12px',\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textUnderlineOffset: '2px',\n }}\n >\n {productCtaLabel}\n </span>\n )}\n </div>\n </div>\n </a>\n );\n })}\n </div>\n </div>\n </div>\n )}\n \n {/* CTA Link, Feedback Buttons, and Sponsored Label */}\n <div className=\"mt-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {hasProductRail && brandName && (\n <span\n className=\"text-sm\"\n style={{\n fontSize: '13px',\n color: TAIL_AD_COLORS.textSecondary,\n fontWeight: 400,\n }}\n >\n {brandName}\n </span>\n )}\n\n {shouldShowDelegationButton ? (\n <button\n type=\"button\"\n onClick={handleDelegationClick}\n className=\"underline transition-colors duration-200 font-medium text-sm\"\n style={{\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textDecorationColor: TAIL_AD_COLORS.link,\n textUnderlineOffset: '2px',\n fontSize: '13px',\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n }}\n >\n {delegationCtaText}\n </button>\n ) : null}\n\n {shouldShowPrimaryCta && (\n <a\n href={clickUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline transition-colors duration-200 font-medium text-sm\"\n style={{\n color: TAIL_AD_COLORS.link,\n textDecoration: 'underline',\n textDecorationColor: TAIL_AD_COLORS.link,\n textUnderlineOffset: '2px',\n fontSize: '13px',\n }}\n onClick={handleCTAClick}\n >\n {ctaLabel}\n </a>\n )}\n\n {hasProductRail && relatedProducts.length > visibleProducts.length && (\n <span\n className=\"text-xs\"\n style={{ fontSize: '11px', color: TAIL_AD_COLORS.textMuted }}\n >\n +{relatedProducts.length - visibleProducts.length} more\n </span>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n <p className=\"text-xs\" style={{ fontSize: '11px', color: TAIL_AD_COLORS.textMuted }}>\n {disclosure || 'Sponsored'}\n </p>\n </div>\n </div>\n\n {showConsentPrompt ? (\n <div\n style={{\n marginTop: '10px',\n border: `1px solid ${cardBorder}`,\n borderRadius: '12px',\n backgroundColor: TAIL_AD_COLORS.surfaceSubtle,\n padding: '12px',\n display: 'flex',\n flexDirection: 'column',\n gap: '10px',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <div\n style={{\n fontSize: '11px',\n fontWeight: 700,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n color: TAIL_AD_COLORS.link,\n }}\n >\n Confirm Agent Access\n </div>\n <div\n style={{\n fontSize: '14px',\n lineHeight: 1.4,\n color: TAIL_AD_COLORS.text,\n fontWeight: 600,\n }}\n >\n Allow {delegationBrandName || 'this brand'} to start a delegated session?\n </div>\n <div\n style={{\n fontSize: '12px',\n lineHeight: 1.45,\n color: TAIL_AD_COLORS.textSecondary,\n }}\n >\n The agent will only use the details you choose to share for this request.\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(false);\n }}\n style={{\n borderRadius: '10px',\n border: `1px solid ${cardBorder}`,\n background: cardBackground,\n color: TAIL_AD_COLORS.text,\n fontSize: '12px',\n fontWeight: 600,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Not now\n </button>\n <button\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n resolveConsentPrompt(true);\n }}\n style={{\n borderRadius: '10px',\n border: 'none',\n background: '#2563eb',\n color: '#ffffff',\n fontSize: '12px',\n fontWeight: 700,\n padding: '8px 12px',\n cursor: 'pointer',\n }}\n >\n Allow agent\n </button>\n </div>\n </div>\n ) : null}\n </div>\n </div>\n </AdMeshViewabilityTracker>\n );\n};\n\nexport default AdMeshTailAd;\n","import React, { useCallback, useEffect, useRef } from 'react';\nimport type { AdMeshLinkTrackerProps } from '../types/index';\nimport { logger } from '../utils/logger';\n\n/**\n * AdMeshLinkTracker Component\n * \n * Wraps content with click tracking via AdMesh click URLs.\n * \n * Note: View/exposure tracking is handled separately by AdMeshViewabilityTracker component.\n * This component only handles click navigation to the admeshLink (which contains click tracking).\n * \n * The admeshLink prop should be the click URL from the recommendation, which already includes\n * all necessary tracking parameters and will redirect to the merchant URL.\n */\nexport const AdMeshLinkTracker: React.FC<AdMeshLinkTrackerProps> = ({\n recommendationId: _recommendationId,\n admeshLink,\n productId: _productId,\n children,\n trackingData: _trackingData,\n className,\n style\n}) => {\n const elementRef = useRef<HTMLDivElement>(null);\n\n // Ensure all child links open in new tab\n useEffect(() => {\n if (!elementRef.current) return;\n\n // Find all <a> tags within this component and ensure they open in new tab\n const links = elementRef.current.querySelectorAll('a');\n links.forEach((link) => {\n // Only set if not already set or if it's not _blank\n if (!link.hasAttribute('target') || link.getAttribute('target') !== '_blank') {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n });\n }, [children]); // Re-run when children change\n\n const handleClick = useCallback((event: React.MouseEvent) => {\n // The admeshLink already contains the click tracking URL from the backend\n // Navigating to it will automatically fire the click tracking pixel and redirect to merchant\n \n // If the children contain a link, ensure it opens in new tab\n // Otherwise, navigate programmatically\n const target = event.target as HTMLElement;\n const link = target.closest('a');\n\n if (!link) {\n // No link found, navigate programmatically to the click URL\n // The click URL will handle tracking and redirect\n if (admeshLink) {\n window.open(admeshLink, '_blank', 'noopener,noreferrer');\n } else {\n logger.warn('[AdMeshLinkTracker] No admeshLink provided for click tracking');\n }\n } else {\n // Link found - ensure it opens in new tab\n // If the link href is not set or is different from admeshLink, update it\n if (!link.href || link.href === '#' || link.href === '') {\n if (admeshLink) {\n link.href = admeshLink;\n }\n }\n if (!link.hasAttribute('target') || link.getAttribute('target') !== '_blank') {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n // Let the browser handle navigation naturally (click URL will track and redirect)\n }\n }, [admeshLink]);\n\n return (\n <div\n ref={elementRef}\n className={className}\n onClick={handleClick}\n style={{\n cursor: 'pointer',\n ...style\n }}\n >\n {children}\n </div>\n );\n};\n\nAdMeshLinkTracker.displayName = 'AdMeshLinkTracker';\n","/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames () {\n\t\tvar classes = '';\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (arg) {\n\t\t\t\tclasses = appendClass(classes, parseValue(arg));\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction parseValue (arg) {\n\t\tif (typeof arg === 'string' || typeof arg === 'number') {\n\t\t\treturn arg;\n\t\t}\n\n\t\tif (typeof arg !== 'object') {\n\t\t\treturn '';\n\t\t}\n\n\t\tif (Array.isArray(arg)) {\n\t\t\treturn classNames.apply(null, arg);\n\t\t}\n\n\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\treturn arg.toString();\n\t\t}\n\n\t\tvar classes = '';\n\n\t\tfor (var key in arg) {\n\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\tclasses = appendClass(classes, key);\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction appendClass (value, newClass) {\n\t\tif (!newClass) {\n\t\t\treturn value;\n\t\t}\n\t\n\t\tif (value) {\n\t\t\treturn value + ' ' + newClass;\n\t\t}\n\t\n\t\treturn value + newClass;\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n","import type { FC } from 'react';\nimport classNames from 'classnames';\nimport type { AdMeshBadgeProps, BadgeType } from '../types/index';\n\n// Badge type to variant mapping\nconst badgeTypeVariants: Record<BadgeType, string> = {\n 'Top Match': 'primary',\n 'Free Tier': 'success',\n 'AI Powered': 'secondary',\n 'Popular': 'warning',\n 'New': 'primary',\n 'Trial Available': 'success'\n};\n\n// Badge type to icon mapping (using clean Unicode symbols)\nconst badgeTypeIcons: Partial<Record<BadgeType, string>> = {\n 'Top Match': '★',\n 'Free Tier': '◆',\n 'AI Powered': '◉',\n 'Popular': '▲',\n 'New': '●',\n 'Trial Available': '◈'\n};\n\nexport const AdMeshBadge: FC<AdMeshBadgeProps> = ({\n type,\n variant,\n size = 'md',\n className,\n style\n}) => {\n const effectiveVariant = variant || badgeTypeVariants[type] || 'secondary';\n const icon = badgeTypeIcons[type];\n\n const badgeClasses = classNames(\n 'admesh-component',\n 'admesh-badge',\n `admesh-badge--${effectiveVariant}`,\n `admesh-badge--${size}`,\n className\n );\n\n return (\n <span\n className={badgeClasses}\n style={style}\n >\n {icon && <span className=\"admesh-badge__icon\">{icon}</span>}\n <span className=\"admesh-badge__text\">{type}</span>\n </span>\n );\n};\n\nAdMeshBadge.displayName = 'AdMeshBadge';\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.js';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.js';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.js';\nimport { toKebabCase } from './shared/src/utils/toKebabCase.js';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 3h6v6\", key: \"1q9fwt\" }],\n [\"path\", { d: \"m21 3-7 7\", key: \"1l2asr\" }],\n [\"path\", { d: \"m3 21 7-7\", key: \"tjx5ai\" }],\n [\"path\", { d: \"M9 21H3v-6\", key: \"wtvkvv\" }]\n];\nconst Maximize2 = createLucideIcon(\"maximize-2\", __iconNode);\n\nexport { __iconNode, Maximize2 as default };\n//# sourceMappingURL=maximize-2.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m14 10 7-7\", key: \"oa77jy\" }],\n [\"path\", { d: \"M20 10h-6V4\", key: \"mjg0md\" }],\n [\"path\", { d: \"m3 21 7-7\", key: \"tjx5ai\" }],\n [\"path\", { d: \"M4 14h6v6\", key: \"rmj7iw\" }]\n];\nconst Minimize2 = createLucideIcon(\"minimize-2\", __iconNode);\n\nexport { __iconNode, Minimize2 as default };\n//# sourceMappingURL=minimize-2.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\",\n key: \"1ffxy3\"\n }\n ],\n [\"path\", { d: \"m21.854 2.147-10.94 10.939\", key: \"12cjpa\" }]\n];\nconst Send = createLucideIcon(\"send\", __iconNode);\n\nexport { __iconNode, Send as default };\n//# sourceMappingURL=send.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\",\n key: \"m61m77\"\n }\n ],\n [\"path\", { d: \"M17 14V2\", key: \"8ymqnk\" }]\n];\nconst ThumbsDown = createLucideIcon(\"thumbs-down\", __iconNode);\n\nexport { __iconNode, ThumbsDown as default };\n//# sourceMappingURL=thumbs-down.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\",\n key: \"emmmcr\"\n }\n ],\n [\"path\", { d: \"M7 10v12\", key: \"1qc93n\" }]\n];\nconst ThumbsUp = createLucideIcon(\"thumbs-up\", __iconNode);\n\nexport { __iconNode, ThumbsUp as default };\n//# sourceMappingURL=thumbs-up.js.map\n","/**\n * @license lucide-react v0.563.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n];\nconst X = createLucideIcon(\"x\", __iconNode);\n\nexport { __iconNode, X as default };\n//# sourceMappingURL=x.js.map\n","/**\n * AdMesh Style Injection System\n * \n * Provides platform-agnostic, isolated styling for AdMesh components\n * that prevents interference from host platform CSS frameworks\n */\n\nconst ADMESH_STYLE_ID = 'admesh-ui-sdk-styles';\nconst ADMESH_RESET_ID = 'admesh-ui-sdk-reset';\n\n/**\n * CSS Reset for AdMesh components\n * Normalizes styles to prevent host platform CSS from affecting AdMesh components\n */\nconst ADMESH_CSS_RESET = `\n/* AdMesh UI SDK - CSS Reset & Normalization */\n.admesh-component,\n.admesh-component * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0;\n font-size: 100%;\n font-weight: normal;\n font-style: normal;\n line-height: 1.5;\n text-decoration: none;\n background: transparent;\n color: inherit;\n}\n\n.admesh-component {\n all: revert;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n}\n\n.admesh-component button,\n.admesh-component a {\n cursor: pointer;\n border: none;\n background: none;\n padding: 0;\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n}\n\n.admesh-component a {\n text-decoration: none;\n color: inherit;\n}\n\n.admesh-component button:focus,\n.admesh-component a:focus {\n outline: none;\n}\n\n.admesh-component img {\n max-width: 100%;\n height: auto;\n display: block;\n}\n\n.admesh-component ul,\n.admesh-component ol {\n list-style: none;\n}\n\n.admesh-component table {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\n.admesh-component input,\n.admesh-component textarea,\n.admesh-component select {\n font-family: inherit;\n font-size: inherit;\n color: inherit;\n}\n\n/* Prevent Tailwind and other frameworks from affecting AdMesh */\n.admesh-component .prose,\n.admesh-component .container,\n.admesh-component .grid,\n.admesh-component .flex {\n all: revert;\n}\n\n/* Ensure AdMesh components are not affected by dark mode utilities */\n.admesh-component.dark,\n.admesh-component[data-admesh-theme=\"dark\"] {\n color-scheme: dark;\n}\n\n.admesh-component.light,\n.admesh-component[data-admesh-theme=\"light\"] {\n color-scheme: light;\n}\n`;\n\n/**\n * Core AdMesh Component Styles\n * Self-contained styles that work independently of host platform\n */\nconst ADMESH_CORE_STYLES = `\n/* AdMesh Core Component Styles */\n\n.admesh-component {\n position: relative;\n display: block;\n}\n\n/* Product Card Styles */\n.admesh-product-card {\n position: relative;\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n height: 100%;\n border-radius: 0.75rem;\n background: rgb(255, 255, 255);\n border: 1px solid rgb(229, 231, 235);\n box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n overflow: hidden;\n}\n\n.admesh-product-card[data-admesh-theme=\"dark\"] {\n background: rgb(17, 24, 39);\n border-color: rgb(31, 41, 55);\n}\n\n.admesh-product-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n border-color: rgba(99, 102, 241, 0.2);\n}\n\n.admesh-product-card__container {\n position: relative;\n padding: 1rem;\n height: 100%;\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n z-index: 2;\n}\n\n.admesh-product-card__header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 0.5rem;\n margin-bottom: 0.25rem;\n}\n\n.admesh-product-card__title {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1.2;\n color: rgb(17, 24, 39);\n letter-spacing: -0.025em;\n transition: all 0.3s ease;\n}\n\n.admesh-product-card[data-admesh-theme=\"dark\"] .admesh-product-card__title {\n color: rgb(243, 244, 246);\n}\n\n.admesh-product-card:hover .admesh-product-card__title {\n transform: translateX(4px);\n}\n\n.admesh-product-card__cta {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n white-space: nowrap;\n border-radius: 0.5rem;\n font-size: 1rem;\n font-weight: 600;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0.75rem 1.5rem;\n background: rgb(0, 0, 0);\n color: rgb(255, 255, 255);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n}\n\n.admesh-product-card[data-admesh-theme=\"dark\"] .admesh-product-card__cta {\n background: rgb(255, 255, 255);\n color: rgb(0, 0, 0);\n}\n\n.admesh-product-card__cta:hover {\n transform: translateY(-2px);\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);\n}\n\n.admesh-product-card__cta:active {\n transform: translateY(0);\n}\n\n/* Summary Unit Styles */\n.admesh-summary-unit {\n font-size: 1rem;\n line-height: 1.6;\n color: rgb(17, 24, 39);\n}\n\n.admesh-summary-unit[data-admesh-theme=\"dark\"] {\n color: rgb(243, 244, 246);\n}\n\n.admesh-summary-unit a {\n color: rgb(37, 99, 235);\n text-decoration: underline;\n text-decoration-color: rgb(37, 99, 235);\n text-underline-offset: 2px;\n transition: all 0.2s ease;\n font-weight: 500;\n}\n\n.admesh-summary-unit[data-admesh-theme=\"dark\"] a {\n color: rgb(96, 165, 250);\n text-decoration-color: rgb(96, 165, 250);\n}\n\n.admesh-summary-unit a:hover {\n color: rgb(29, 78, 216);\n text-decoration-color: rgb(29, 78, 216);\n}\n\n.admesh-summary-unit[data-admesh-theme=\"dark\"] a:hover {\n color: rgb(147, 197, 253);\n text-decoration-color: rgb(147, 197, 253);\n}\n\n/* Ecommerce Cards Styles */\n.admesh-ecommerce-container {\n position: relative;\n width: 100%;\n}\n\n.admesh-ecommerce-card {\n flex-shrink: 0;\n background: white;\n border: 1px solid rgb(229, 231, 235);\n border-radius: 0.5rem;\n overflow: hidden;\n transition: all 0.2s ease-in-out;\n cursor: pointer;\n position: relative;\n}\n\n.admesh-ecommerce-card[data-admesh-theme=\"dark\"] {\n background: rgb(31, 41, 55);\n border-color: rgb(55, 65, 81);\n color: white;\n}\n\n.admesh-ecommerce-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);\n}\n\n/* Badge Styles */\n.admesh-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n border-radius: 0.5rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.875rem;\n font-weight: 600;\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n}\n\n.admesh-badge--primary {\n background: linear-gradient(135deg, rgb(99, 102, 241), rgb(79, 70, 229));\n color: white;\n box-shadow: 0 4px 6px -1px rgba(99, 102, 241, 0.3);\n}\n\n.admesh-badge--secondary {\n background: rgb(243, 244, 246);\n color: rgb(55, 65, 81);\n}\n\n.admesh-badge[data-admesh-theme=\"dark\"].admesh-badge--secondary {\n background: rgb(31, 41, 55);\n color: rgb(209, 213, 219);\n}\n\n/* Responsive */\n@media (max-width: 640px) {\n .admesh-product-card__container {\n padding: 0.75rem;\n gap: 0.5rem;\n }\n\n .admesh-product-card__title {\n font-size: 1.25rem;\n }\n\n .admesh-product-card__cta {\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n }\n}\n`;\n\n/**\n * Inject AdMesh styles into the document\n * Ensures styles are loaded only once and don't conflict with host platform\n */\nexport const injectAdMeshStyles = (): void => {\n if (typeof document === 'undefined') return;\n\n // Check if styles already injected\n if (document.getElementById(ADMESH_RESET_ID) && document.getElementById(ADMESH_STYLE_ID)) {\n return;\n }\n\n // Inject CSS Reset\n if (!document.getElementById(ADMESH_RESET_ID)) {\n const resetStyle = document.createElement('style');\n resetStyle.id = ADMESH_RESET_ID;\n resetStyle.textContent = ADMESH_CSS_RESET;\n document.head.appendChild(resetStyle);\n }\n\n // Inject Core Styles\n if (!document.getElementById(ADMESH_STYLE_ID)) {\n const coreStyle = document.createElement('style');\n coreStyle.id = ADMESH_STYLE_ID;\n coreStyle.textContent = ADMESH_CORE_STYLES;\n document.head.appendChild(coreStyle);\n }\n};\n\n/**\n * Remove AdMesh styles from the document\n * Useful for cleanup or testing\n */\nexport const removeAdMeshStyles = (): void => {\n if (typeof document === 'undefined') return;\n\n const resetStyle = document.getElementById(ADMESH_RESET_ID);\n const coreStyle = document.getElementById(ADMESH_STYLE_ID);\n\n if (resetStyle) resetStyle.remove();\n if (coreStyle) coreStyle.remove();\n};\n\n/**\n * Check if AdMesh styles are already injected\n */\nexport const areAdMeshStylesInjected = (): boolean => {\n if (typeof document === 'undefined') return false;\n return !!(document.getElementById(ADMESH_RESET_ID) && document.getElementById(ADMESH_STYLE_ID));\n};\n\n","import { useEffect } from 'react';\nimport { logger } from '../utils/logger';\nimport { injectAdMeshStyles } from '../utils/styleInjection';\n\n// Complete CSS content as a string - this will be injected automatically\nconst ADMESH_STYLES = `\n/* AdMesh UI SDK - Complete Self-Contained Styles */\n\n/* CSS Reset for AdMesh components */\n.admesh-component, .admesh-component * {\n box-sizing: border-box;\n}\n\n/* CSS Variables - Black/White Color Scheme */\n.admesh-component {\n --admesh-primary: #000000;\n --admesh-primary-hover: #333333;\n --admesh-secondary: #666666;\n --admesh-accent: #000000;\n --admesh-background: #ffffff;\n --admesh-surface: #ffffff;\n --admesh-border: #e5e7eb;\n --admesh-text: #000000;\n --admesh-text-muted: #666666;\n --admesh-text-light: #999999;\n --admesh-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --admesh-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --admesh-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --admesh-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --admesh-radius: 0.5rem;\n --admesh-radius-sm: 0.25rem;\n --admesh-radius-lg: 0.75rem;\n --admesh-radius-xl: 1rem;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] {\n --admesh-primary: #ffffff;\n --admesh-primary-hover: #e5e7eb;\n --admesh-secondary: #9ca3af;\n --admesh-accent: #ffffff;\n --admesh-background: #000000;\n --admesh-surface: #111111;\n --admesh-border: #333333;\n --admesh-text: #ffffff;\n --admesh-text-muted: #9ca3af;\n --admesh-text-light: #666666;\n --admesh-shadow: 0 1px 3px 0 rgb(255 255 255 / 0.1), 0 1px 2px -1px rgb(255 255 255 / 0.1);\n --admesh-shadow-md: 0 4px 6px -1px rgb(255 255 255 / 0.1), 0 2px 4px -2px rgb(255 255 255 / 0.1);\n --admesh-shadow-lg: 0 10px 15px -3px rgb(255 255 255 / 0.1), 0 4px 6px -4px rgb(255 255 255 / 0.1);\n --admesh-shadow-xl: 0 20px 25px -5px rgb(255 255 255 / 0.1), 0 8px 10px -6px rgb(255 255 255 / 0.1);\n}\n\n/* Layout Styles */\n.admesh-layout {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n color: var(--admesh-text);\n background-color: var(--admesh-background);\n border-radius: var(--admesh-radius);\n padding: 1.5rem;\n box-shadow: var(--admesh-shadow);\n border: 1px solid var(--admesh-border);\n /* Consistent width: 100% for all layouts except ecommerce */\n width: 100%;\n}\n\n/* Ecommerce layout exception */\n.admesh-layout--ecommerce {\n width: auto;\n}\n\n/* Citation Unit Styles */\n.admesh-citation-unit {\n width: 100%;\n}\n\n/* Inline Recommendation Styles */\n.admesh-inline-recommendation {\n width: 100%;\n}\n\n/* Simple Ad Styles */\n.admesh-simple-ad {\n width: 100%;\n}\n\n.admesh-layout__header {\n margin-bottom: 1.5rem;\n text-align: center;\n}\n\n.admesh-layout__title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--admesh-text);\n margin-bottom: 0.5rem;\n}\n\n.admesh-layout__subtitle {\n font-size: 0.875rem;\n color: var(--admesh-text-muted);\n}\n\n.admesh-layout__cards-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 1rem;\n margin-bottom: 1.5rem;\n}\n\n.admesh-layout__more-indicator {\n text-align: center;\n padding: 1rem;\n color: var(--admesh-text-muted);\n font-size: 0.875rem;\n}\n\n.admesh-layout__empty {\n text-align: center;\n padding: 3rem 1rem;\n}\n\n.admesh-layout__empty-content h3 {\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--admesh-text-muted);\n margin-bottom: 0.5rem;\n}\n\n.admesh-layout__empty-content p {\n font-size: 0.875rem;\n color: var(--admesh-text-muted);\n}\n\n/* Product Card Styles */\n.admesh-product-card {\n background-color: var(--admesh-surface);\n border: 1px solid var(--admesh-border);\n border-radius: var(--admesh-radius);\n padding: 1.5rem;\n transition: all 0.2s ease-in-out;\n position: relative;\n overflow: hidden;\n /* Consistent width: 100% for product cards */\n width: 100%;\n}\n\n.admesh-product-card:hover {\n box-shadow: var(--admesh-shadow-lg);\n transform: translateY(-2px);\n border-color: var(--admesh-primary);\n}\n\n.admesh-product-card__header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__title {\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--admesh-text);\n margin-bottom: 0.5rem;\n line-height: 1.4;\n}\n\n.admesh-product-card__reason {\n font-size: 0.875rem;\n color: var(--admesh-text-muted);\n line-height: 1.5;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__match-score {\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__match-score-label {\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.75rem;\n color: var(--admesh-text-muted);\n margin-bottom: 0.25rem;\n}\n\n.admesh-product-card__match-score-bar {\n width: 100%;\n height: 0.375rem;\n background-color: var(--admesh-border);\n border-radius: var(--admesh-radius-sm);\n overflow: hidden;\n}\n\n.admesh-product-card__match-score-fill {\n height: 100%;\n background: var(--admesh-primary);\n border-radius: var(--admesh-radius-sm);\n transition: width 0.3s ease-in-out;\n}\n\n.admesh-product-card__badges {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__badge {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.25rem 0.5rem;\n background-color: var(--admesh-primary);\n color: white;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: var(--admesh-radius-sm);\n}\n\n.admesh-product-card__badge--secondary {\n background-color: var(--admesh-secondary);\n}\n\n.admesh-product-card__keywords {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n margin-bottom: 1rem;\n}\n\n.admesh-product-card__keyword {\n padding: 0.125rem 0.375rem;\n background-color: var(--admesh-border);\n color: var(--admesh-text-muted);\n font-size: 0.75rem;\n border-radius: var(--admesh-radius-sm);\n}\n\n/* Dark mode specific enhancements */\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-product-card__keyword {\n background-color: #4b5563;\n color: #d1d5db;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-product-card:hover {\n border-color: var(--admesh-primary);\n background-color: #374151;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-product-card__button:hover {\n background: var(--admesh-primary-hover);\n}\n\n.admesh-product-card__footer {\n display: flex;\n justify-content: flex-end;\n margin-top: 1.5rem;\n}\n\n/* Mobile-specific sidebar improvements */\n@media (max-width: 640px) {\n .admesh-sidebar {\n /* Ensure proper mobile viewport handling */\n height: 100vh !important;\n height: 100dvh !important; /* Dynamic viewport height for mobile browsers */\n max-height: 100vh !important;\n max-height: 100dvh !important;\n width: 100vw !important;\n max-width: 90vw !important;\n overflow: hidden !important;\n }\n\n .admesh-sidebar.relative {\n height: 100% !important;\n width: 100% !important;\n max-width: 100% !important;\n }\n\n /* Improve touch scrolling */\n .admesh-sidebar .overflow-y-auto {\n -webkit-overflow-scrolling: touch !important;\n overscroll-behavior: contain !important;\n scroll-behavior: smooth !important;\n }\n\n /* Prevent body scroll when sidebar is open */\n body:has(.admesh-sidebar[data-mobile-open=\"true\"]) {\n overflow: hidden !important;\n position: fixed !important;\n width: 100% !important;\n }\n}\n\n/* Tablet improvements */\n@media (min-width: 641px) and (max-width: 1024px) {\n .admesh-sidebar {\n max-width: 400px !important;\n }\n}\n\n/* Mobile responsiveness improvements for all components */\n@media (max-width: 640px) {\n /* Product cards mobile optimization */\n .admesh-card {\n padding: 0.75rem !important;\n margin-bottom: 0.75rem !important;\n }\n\n /* Inline recommendations mobile optimization */\n .admesh-inline-recommendation {\n padding: 0.5rem !important;\n margin-bottom: 0.5rem !important;\n }\n\n /* Conversation summary mobile optimization */\n .admesh-conversation-summary {\n padding: 1rem !important;\n }\n\n /* Percentage text mobile improvements */\n .admesh-component .text-xs {\n font-size: 0.75rem !important;\n line-height: 1rem !important;\n }\n\n .admesh-component .text-sm {\n font-size: 0.875rem !important;\n line-height: 1.25rem !important;\n }\n\n /* Button mobile improvements */\n .admesh-component button {\n padding: 0.375rem 0.75rem !important;\n font-size: 0.75rem !important;\n min-height: 2rem !important;\n touch-action: manipulation !important;\n }\n\n /* Badge mobile improvements */\n .admesh-component .rounded-full {\n padding: 0.25rem 0.5rem !important;\n font-size: 0.625rem !important;\n line-height: 1rem !important;\n }\n\n /* Progress bar mobile improvements */\n .admesh-component .bg-gray-200,\n .admesh-component .bg-slate-600 {\n height: 0.25rem !important;\n }\n\n /* Flex layout mobile improvements */\n .admesh-component .flex {\n flex-wrap: wrap !important;\n }\n\n .admesh-component .gap-2 {\n gap: 0.375rem !important;\n }\n\n .admesh-component .gap-3 {\n gap: 0.5rem !important;\n }\n}\n\n.admesh-product-card__button {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n background: var(--admesh-primary);\n color: var(--admesh-background);\n font-size: 0.875rem;\n font-weight: 500;\n border: none;\n border-radius: var(--admesh-radius);\n cursor: pointer;\n transition: all 0.2s ease-in-out;\n text-decoration: none;\n}\n\n.admesh-product-card__button:hover {\n transform: translateY(-1px);\n box-shadow: var(--admesh-shadow-lg);\n}\n\n/* Utility Classes */\n.admesh-text-xs { font-size: 0.75rem; }\n.admesh-text-sm { font-size: 0.875rem; }\n.admesh-text-base { font-size: 1rem; }\n.admesh-text-lg { font-size: 1.125rem; }\n.admesh-text-xl { font-size: 1.25rem; }\n\n.admesh-font-medium { font-weight: 500; }\n.admesh-font-semibold { font-weight: 600; }\n.admesh-font-bold { font-weight: 700; }\n\n.admesh-text-muted { color: var(--admesh-text-muted); }\n\n/* Comparison Table Styles */\n.admesh-compare-table {\n width: 100%;\n border-collapse: collapse;\n background-color: var(--admesh-surface);\n border: 1px solid var(--admesh-border);\n border-radius: var(--admesh-radius);\n overflow: hidden;\n}\n\n.admesh-compare-table th,\n.admesh-compare-table td {\n padding: 0.75rem;\n text-align: left;\n border-bottom: 1px solid var(--admesh-border);\n}\n\n.admesh-compare-table th {\n background-color: var(--admesh-background);\n font-weight: 600;\n color: var(--admesh-text);\n font-size: 0.875rem;\n}\n\n.admesh-compare-table td {\n color: var(--admesh-text);\n font-size: 0.875rem;\n}\n\n.admesh-compare-table tr:hover {\n background-color: var(--admesh-border);\n}\n\n/* Dark mode table enhancements */\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-compare-table th {\n background-color: #374151;\n}\n\n.admesh-component[data-admesh-theme=\"dark\"] .admesh-compare-table tr:hover {\n background-color: #4b5563;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .admesh-layout {\n padding: 1rem;\n }\n\n .admesh-layout__cards-grid {\n grid-template-columns: 1fr;\n gap: 0.75rem;\n }\n\n .admesh-product-card {\n padding: 1rem;\n }\n\n .admesh-compare-table {\n font-size: 0.75rem;\n }\n\n .admesh-compare-table th,\n .admesh-compare-table td {\n padding: 0.5rem;\n }\n}\n\n/* Essential Utility Classes for Self-Contained SDK - High Specificity */\n.admesh-component .relative { position: relative !important; }\n.admesh-component .absolute { position: absolute !important; }\n.admesh-component .flex { display: flex !important; }\n.admesh-component .inline-flex { display: inline-flex !important; }\n.admesh-component .grid { display: grid !important; }\n.admesh-component .hidden { display: none !important; }\n.admesh-component .block { display: block !important; }\n.admesh-component .inline-block { display: inline-block !important; }\n\n/* Flexbox utilities */\n.admesh-component .flex-col { flex-direction: column !important; }\n.admesh-component .flex-row { flex-direction: row !important; }\n.admesh-component .flex-wrap { flex-wrap: wrap !important; }\n.admesh-component .items-center { align-items: center !important; }\n.admesh-component .items-start { align-items: flex-start !important; }\n.admesh-component .items-end { align-items: flex-end !important; }\n.admesh-component .justify-center { justify-content: center !important; }\n.admesh-component .justify-between { justify-content: space-between !important; }\n.admesh-component .justify-end { justify-content: flex-end !important; }\n.admesh-component .flex-1 { flex: 1 1 0% !important; }\n.admesh-component .flex-shrink-0 { flex-shrink: 0 !important; }\n\n/* Grid utilities */\n.admesh-component .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }\n.admesh-component .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n.admesh-component .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n\n/* Spacing utilities */\n.admesh-component .gap-1 { gap: 0.25rem; }\n.admesh-component .gap-2 { gap: 0.5rem; }\n.admesh-component .gap-3 { gap: 0.75rem; }\n.admesh-component .gap-4 { gap: 1rem; }\n.admesh-component .gap-6 { gap: 1.5rem; }\n.admesh-component .gap-8 { gap: 2rem; }\n\n/* Padding utilities */\n.admesh-component .p-1 { padding: 0.25rem; }\n.admesh-component .p-2 { padding: 0.5rem; }\n.admesh-component .p-3 { padding: 0.75rem; }\n.admesh-component .p-4 { padding: 1rem; }\n.admesh-component .p-5 { padding: 1.25rem; }\n.admesh-component .p-6 { padding: 1.5rem; }\n.admesh-component .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }\n.admesh-component .px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }\n.admesh-component .px-4 { padding-left: 1rem; padding-right: 1rem; }\n.admesh-component .py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }\n.admesh-component .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }\n.admesh-component .py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }\n.admesh-component .pt-2 { padding-top: 0.5rem; }\n.admesh-component .pt-3 { padding-top: 0.75rem; }\n.admesh-component .pb-2 { padding-bottom: 0.5rem; }\n.admesh-component .pb-3 { padding-bottom: 0.75rem; }\n\n/* Margin utilities */\n.admesh-component .m-0 { margin: 0; }\n.admesh-component .mb-1 { margin-bottom: 0.25rem; }\n.admesh-component .mb-2 { margin-bottom: 0.5rem; }\n.admesh-component .mb-3 { margin-bottom: 0.75rem; }\n.admesh-component .mb-4 { margin-bottom: 1rem; }\n.admesh-component .mb-6 { margin-bottom: 1.5rem; }\n.admesh-component .mt-1 { margin-top: 0.25rem; }\n.admesh-component .mt-2 { margin-top: 0.5rem; }\n.admesh-component .mt-4 { margin-top: 1rem; }\n.admesh-component .mt-6 { margin-top: 1.5rem; }\n.admesh-component .mt-auto { margin-top: auto; }\n.admesh-component .ml-1 { margin-left: 0.25rem; }\n.admesh-component .mr-1 { margin-right: 0.25rem; }\n.admesh-component .mr-2 { margin-right: 0.5rem; }\n\n/* Width and height utilities */\n.admesh-component .w-2 { width: 0.5rem; }\n.admesh-component .w-3 { width: 0.75rem; }\n.admesh-component .w-4 { width: 1rem; }\n.admesh-component .w-5 { width: 1.25rem; }\n.admesh-component .w-6 { width: 1.5rem; }\n.admesh-component .w-full { width: 100%; }\n.admesh-component .w-fit { width: fit-content; }\n.admesh-component .h-2 { height: 0.5rem; }\n.admesh-component .h-3 { height: 0.75rem; }\n.admesh-component .h-4 { height: 1rem; }\n.admesh-component .h-5 { height: 1.25rem; }\n.admesh-component .h-6 { height: 1.5rem; }\n.admesh-component .h-full { height: 100%; }\n.admesh-component .min-w-0 { min-width: 0px; }\n\n/* Border utilities */\n.admesh-component .border { border-width: 1px; }\n.admesh-component .border-t { border-top-width: 1px; }\n.admesh-component .border-gray-100 { border-color: #f3f4f6; }\n.admesh-component .border-gray-200 { border-color: #e5e7eb; }\n.admesh-component .border-gray-300 { border-color: #d1d5db; }\n.admesh-component .border-blue-200 { border-color: #bfdbfe; }\n.admesh-component .border-green-200 { border-color: #bbf7d0; }\n\n/* Border radius utilities */\n.admesh-component .rounded { border-radius: 0.25rem !important; }\n.admesh-component .rounded-md { border-radius: 0.375rem !important; }\n.admesh-component .rounded-lg { border-radius: 0.5rem !important; }\n.admesh-component .rounded-xl { border-radius: 0.75rem !important; }\n.admesh-component .rounded-full { border-radius: 9999px !important; }\n\n/* Background utilities */\n.admesh-component .bg-white { background-color: #ffffff; }\n.admesh-component .bg-gray-50 { background-color: #f9fafb; }\n.admesh-component .bg-gray-100 { background-color: #f3f4f6; }\n.admesh-component .bg-blue-50 { background-color: #eff6ff; }\n.admesh-component .bg-blue-100 { background-color: #dbeafe; }\n.admesh-component .bg-green-100 { background-color: #dcfce7; }\n.admesh-component .bg-green-500 { background-color: #22c55e; }\n.admesh-component .bg-blue-500 { background-color: #3b82f6; }\n\n/* Solid backgrounds - no gradients for minimal design */\n.admesh-component .bg-primary { background-color: var(--admesh-primary); }\n.admesh-component .bg-secondary { background-color: var(--admesh-secondary); }\n.admesh-component .bg-surface { background-color: var(--admesh-surface); }\n.admesh-component .bg-background { background-color: var(--admesh-background); }\n\n/* Text utilities */\n.admesh-component .text-xs { font-size: 0.75rem; line-height: 1rem; }\n.admesh-component .text-sm { font-size: 0.875rem; line-height: 1.25rem; }\n.admesh-component .text-base { font-size: 1rem; line-height: 1.5rem; }\n.admesh-component .text-lg { font-size: 1.125rem; line-height: 1.75rem; }\n.admesh-component .text-xl { font-size: 1.25rem; line-height: 1.75rem; }\n.admesh-component .font-medium { font-weight: 500; }\n.admesh-component .font-semibold { font-weight: 600; }\n.admesh-component .font-bold { font-weight: 700; }\n.admesh-component .leading-relaxed { line-height: 1.625; }\n\n/* Text colors */\n.admesh-component .text-white { color: #ffffff; }\n.admesh-component .text-gray-400 { color: #9ca3af; }\n.admesh-component .text-gray-500 { color: #6b7280; }\n.admesh-component .text-gray-600 { color: #4b5563; }\n.admesh-component .text-gray-700 { color: #374151; }\n.admesh-component .text-gray-800 { color: #1f2937; }\n.admesh-component .text-blue-600 { color: #2563eb; }\n.admesh-component .text-blue-700 { color: #1d4ed8; }\n.admesh-component .text-green-700 { color: #15803d; }\n\n/* Shadow utilities */\n.admesh-component .shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }\n.admesh-component .shadow { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }\n.admesh-component .shadow-md { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); }\n.admesh-component .shadow-lg { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); }\n.admesh-component .shadow-xl { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); }\n\n/* Transition utilities */\n.admesh-component .transition-all { transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }\n.admesh-component .transition-colors { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }\n.admesh-component .duration-200 { transition-duration: 200ms; }\n.admesh-component .duration-300 { transition-duration: 300ms; }\n\n/* Transform utilities */\n.admesh-component .hover\\\\:-translate-y-1:hover { transform: translateY(-0.25rem); }\n.admesh-component .hover\\\\:scale-105:hover { transform: scale(1.05); }\n\n/* Hover utilities */\n.admesh-component .hover\\\\:shadow-xl:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); }\n.admesh-component .hover\\\\:bg-gray-100:hover { background-color: #f3f4f6; }\n.admesh-component .hover\\\\:text-blue-800:hover { color: #1e40af; }\n\n/* Cursor utilities */\n.admesh-component .cursor-pointer { cursor: pointer; }\n\n/* Overflow utilities */\n.admesh-component .overflow-hidden { overflow: hidden; }\n.admesh-component .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n/* Text decoration */\n.admesh-component .underline { text-decoration-line: underline; }\n\n/* Whitespace */\n.admesh-component .whitespace-nowrap { white-space: nowrap; }\n\n/* Dark mode utilities */\n@media (prefers-color-scheme: dark) {\n .admesh-component .dark\\\\:bg-slate-800 { background-color: #1e293b; }\n .admesh-component .dark\\\\:bg-slate-900 { background-color: #0f172a; }\n .admesh-component .dark\\\\:border-slate-700 { border-color: #334155; }\n .admesh-component .dark\\\\:text-white { color: #ffffff; }\n .admesh-component .dark\\\\:text-gray-200 { color: #e5e7eb; }\n .admesh-component .dark\\\\:text-gray-300 { color: #d1d5db; }\n .admesh-component .dark\\\\:text-gray-400 { color: #9ca3af; }\n .admesh-component .dark\\\\:text-blue-400 { color: #60a5fa; }\n}\n\n/* Responsive utilities */\n@media (min-width: 640px) {\n .admesh-component .sm\\\\:p-5 { padding: 1.25rem; }\n .admesh-component .sm\\\\:text-base { font-size: 1rem; line-height: 1.5rem; }\n .admesh-component .sm\\\\:text-lg { font-size: 1.125rem; line-height: 1.75rem; }\n .admesh-component .sm\\\\:flex-row { flex-direction: row; }\n .admesh-component .sm\\\\:items-center { align-items: center; }\n .admesh-component .sm\\\\:justify-between { justify-content: space-between; }\n}\n\n@media (min-width: 768px) {\n .admesh-component .md\\\\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n\n@media (min-width: 1024px) {\n .admesh-component .lg\\\\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n .admesh-component .lg\\\\:col-span-1 { grid-column: span 1 / span 1; }\n}\n`;\n\nlet stylesInjected = false;\n\n/**\n * Hook to inject AdMesh styles into the document\n * Ensures platform-agnostic, isolated styling that prevents\n * interference from host platform CSS frameworks\n *\n * Usage:\n * const MyComponent = () => {\n * useAdMeshStyles();\n * return <div className=\"admesh-component\">...</div>;\n * };\n */\nexport const useAdMeshStyles = () => {\n useEffect(() => {\n if (stylesInjected) return;\n\n try {\n // Use the new style injection system for better isolation\n injectAdMeshStyles();\n\n // Also inject the legacy styles for backward compatibility\n const styleElement = document.createElement('style');\n styleElement.id = 'admesh-ui-sdk-styles-legacy';\n styleElement.textContent = ADMESH_STYLES;\n\n if (!document.getElementById('admesh-ui-sdk-styles-legacy')) {\n document.head.appendChild(styleElement);\n }\n\n stylesInjected = true;\n } catch (error) {\n logger.error('[AdMesh] Failed to inject styles');\n }\n\n // Cleanup function\n return () => {\n // Note: We don't remove styles on unmount to prevent flickering\n // Styles are designed to be persistent for the lifetime of the app\n };\n }, []);\n};\n","\"use client\";\n\nimport { Fragment, useState, useEffect, useLayoutEffect, useRef, useCallback, useMemo, type CSSProperties, type FC, type ReactNode } from \"react\";\nimport { XIcon, SendIcon, Maximize2, Minimize2, ThumbsUp, ThumbsDown } from \"lucide-react\";\nimport type { PlatformResponse, AdMeshTheme, ChatMessage } from \"../types/index\";\nimport { AdMeshRecommendations } from \"./AdMeshRecommendations\";\nimport { useAdMesh } from \"../hooks/useAdMesh\";\nimport { useAdMeshStyles } from \"../hooks/useAdMeshStyles\";\nimport { useAdMeshContext } from \"../context/AdMeshContext\";\nimport type { PublisherAssistantAnalyticsEvent } from \"../sdk/AdMeshSDK\";\n\nfunction formatGenerationDuration(totalSeconds: number): string {\n const seconds = Math.max(1, Math.round(totalSeconds));\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n const remainder = seconds % 60;\n return remainder > 0 ? `${minutes}m ${remainder}s` : `${minutes}m`;\n}\n\nfunction formatGenerationDurationFromMs(durationMs: number): string {\n return formatGenerationDuration(durationMs / 1000);\n}\n\ntype AnswerFeedbackValue = 'helpful' | 'not_helpful';\n\n// Custom markdown renderer with proper styling\nconst CustomMarkdownRenderer = ({ content, theme, fontSize }: { content: string; theme: AdMeshTheme; fontSize: string }) => {\n const renderInlineFormatting = (text: string) => {\n const parts = text.split(/(\\*\\*[^*]+\\*\\*)/g);\n return parts.map((part, index) => {\n if (part.startsWith('**') && part.endsWith('**') && part.length > 4) {\n return (\n <strong key={index} style={{ fontWeight: '600', color: theme.textColor }}>\n {part.slice(2, -2)}\n </strong>\n );\n }\n return <Fragment key={index}>{part}</Fragment>;\n });\n };\n\n const parseTableRow = (line: string) => {\n const trimmed = line.trim().replace(/^\\|/, '').replace(/\\|$/, '');\n return trimmed.split('|').map((cell) => cell.trim()).filter((cell, index, cells) => (\n cell.length > 0 || index < cells.length - 1\n ));\n };\n\n const isTableSeparator = (line: string) => {\n const cells = parseTableRow(line);\n return cells.length > 1 && cells.every((cell) => /^:?-{3,}:?$/.test(cell));\n };\n\n const splitTablePrefixHeading = (line: string) => {\n const pipeIndex = line.indexOf('|');\n if (pipeIndex <= 0) {\n return { heading: null as string | null, headerLine: line };\n }\n const prefix = line.slice(0, pipeIndex).trim();\n if (!prefix || /^[-|:\\s]+$/.test(prefix)) {\n return { heading: null, headerLine: line };\n }\n return { heading: prefix, headerLine: line.slice(pipeIndex).trim() };\n };\n\n const normalizeTableSeparator = (headerLine: string, separatorLine: string) => {\n const headerCount = parseTableRow(headerLine).length;\n const separatorCount = parseTableRow(separatorLine).length;\n if (headerCount <= 1 || headerCount === separatorCount) {\n return separatorLine;\n }\n return `| ${Array.from({ length: headerCount }, () => '---').join(' | ')} |`;\n };\n\n const normalizeTableLines = (lines: string[]) => {\n if (lines.length < 2 || !lines[0].includes('|')) {\n return { heading: null as string | null, lines };\n }\n const { heading, headerLine } = splitTablePrefixHeading(lines[0]);\n const normalizedHeader = headerLine.startsWith('|') ? headerLine : `| ${headerLine}`;\n const normalizedSeparator = normalizeTableSeparator(normalizedHeader, lines[1]);\n return {\n heading,\n lines: [normalizedHeader, normalizedSeparator, ...lines.slice(2)],\n };\n };\n\n const isMarkdownTable = (lines: string[]) => {\n if (lines.length < 2 || !lines[0].includes('|')) {\n return false;\n }\n const { lines: normalizedLines } = normalizeTableLines(lines);\n return (\n isTableSeparator(normalizedLines[1]) &&\n parseTableRow(normalizedLines[0]).length >= 2\n );\n };\n\n const expandInlineTableLine = (line: string) => {\n if (!line.includes('|')) {\n return [line];\n }\n\n let working = line.trim();\n const result: string[] = [];\n\n const pipeIndex = working.indexOf('|');\n if (pipeIndex > 0) {\n const prefix = working.slice(0, pipeIndex).trim();\n if (prefix && !/^[-|:\\s]+$/.test(prefix)) {\n result.push(prefix);\n working = working.slice(pipeIndex).trim();\n }\n }\n\n // Some models (e.g. Gemma) emit header + separator + rows on one line.\n working = working.replace(/\\|\\s*(\\|(?:\\s*:?-{3,}:?\\s*\\|)+)/g, (_match, separatorRow: string) => `\\n${separatorRow}`);\n working = working.replace(/\\|\\s*\\|\\s*(?=[A-Za-z0-9*])/g, '|\\n| ');\n working = working.replace(/\\|\\s+(?=\\|(?!\\s*:?-{3,}:?\\s*\\|)[^|\\n])/g, '|\\n');\n\n result.push(...working.split('\\n').map((part) => part.trim()).filter(Boolean));\n return result;\n };\n\n const normalizeCompactMarkdownTables = (markdown: string) => {\n const lines = markdown.split('\\n');\n const normalized: string[] = [];\n\n for (const line of lines) {\n if (!line.includes('|')) {\n normalized.push(line);\n continue;\n }\n normalized.push(...expandInlineTableLine(line));\n }\n\n return normalized.join('\\n');\n };\n\n const isolateMarkdownTables = (markdown: string) => {\n const lines = normalizeCompactMarkdownTables(markdown).split('\\n');\n const output: string[] = [];\n let index = 0;\n\n while (index < lines.length) {\n const line = lines[index];\n const nextLine = lines[index + 1] || '';\n\n if (line.includes('|') && isTableSeparator(nextLine)) {\n if (output.length > 0 && output[output.length - 1].trim()) {\n output.push('');\n }\n\n const { heading, headerLine } = splitTablePrefixHeading(line);\n if (heading) {\n output.push(heading);\n }\n output.push(headerLine, normalizeTableSeparator(headerLine, nextLine));\n index += 2;\n\n while (index < lines.length && lines[index].includes('|') && lines[index].trim()) {\n output.push(lines[index]);\n index += 1;\n }\n\n if (index < lines.length && lines[index].trim()) {\n output.push('');\n }\n continue;\n }\n\n output.push(line);\n index += 1;\n }\n\n return output.join('\\n');\n };\n\n const blocks = isolateMarkdownTables(content)\n .split(/\\n\\s*\\n/)\n .map((block) => block.trim())\n .filter(Boolean);\n\n return (\n <div style={{ margin: 0, color: theme.textColor, fontSize }}>\n {blocks.map((block, blockIndex) => {\n const lines = block.split('\\n').map((line) => line.trim()).filter(Boolean);\n const isBulletList = lines.every((line) => /^[-*]\\s+/.test(line));\n const isNumberedList = lines.every((line) => /^\\d+\\.\\s+/.test(line));\n const isHeading = lines.length === 1 && /^#{1,3}\\s+/.test(lines[0]);\n const isTable = isMarkdownTable(lines);\n\n if (isHeading) {\n const text = lines[0].replace(/^#{1,3}\\s+/, '');\n return (\n <h3\n key={blockIndex}\n style={{\n marginTop: blockIndex === 0 ? 0 : '1rem',\n marginBottom: '0.75rem',\n fontWeight: '600',\n fontSize: '1.05em',\n color: theme.textColor,\n }}\n >\n {renderInlineFormatting(text)}\n </h3>\n );\n }\n\n if (isTable) {\n const { heading, lines: tableLines } = normalizeTableLines(lines);\n const headers = parseTableRow(tableLines[0]);\n const rows = tableLines.slice(2).map(parseTableRow).filter((row) => row.length === headers.length);\n\n return (\n <div\n key={blockIndex}\n style={{\n width: '100%',\n overflowX: 'auto',\n marginBottom: '1rem',\n }}\n >\n {heading ? (\n <p\n style={{\n marginTop: blockIndex === 0 ? 0 : '1rem',\n marginBottom: '0.75rem',\n fontWeight: 600,\n color: theme.textColor,\n fontSize,\n }}\n >\n {renderInlineFormatting(heading)}\n </p>\n ) : null}\n <div\n style={{\n border: `1px solid ${theme.borderColor || 'rgba(148, 163, 184, 0.28)'}`,\n borderRadius: 8,\n overflowX: 'auto',\n }}\n >\n <table\n style={{\n width: '100%',\n minWidth: headers.length > 3 ? 520 : undefined,\n borderCollapse: 'collapse',\n color: theme.textColor,\n fontSize,\n lineHeight: 1.45,\n }}\n >\n <thead>\n <tr>\n {headers.map((header, index) => (\n <th\n key={index}\n style={{\n textAlign: 'left',\n padding: '9px 10px',\n fontWeight: 600,\n background: theme.surfaceColor || 'rgba(148, 163, 184, 0.12)',\n borderBottom: `1px solid ${theme.borderColor || 'rgba(148, 163, 184, 0.28)'}`,\n whiteSpace: 'normal',\n }}\n >\n {renderInlineFormatting(header)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((cell, cellIndex) => (\n <td\n key={cellIndex}\n style={{\n padding: '9px 10px',\n verticalAlign: 'top',\n borderBottom:\n rowIndex === rows.length - 1\n ? 'none'\n : `1px solid ${theme.borderColor || 'rgba(148, 163, 184, 0.18)'}`,\n whiteSpace: 'normal',\n }}\n >\n {renderInlineFormatting(cell)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n }\n\n if (isBulletList || isNumberedList) {\n const ListTag = isNumberedList ? 'ol' : 'ul';\n return (\n <ListTag\n key={blockIndex}\n style={{\n marginBottom: '1rem',\n paddingLeft: '1.25rem',\n color: theme.textColor,\n fontSize,\n }}\n >\n {lines.map((line, lineIndex) => (\n <li key={lineIndex} style={{ marginBottom: '0.45rem' }}>\n {renderInlineFormatting(line.replace(/^([-*]|\\d+\\.)\\s+/, ''))}\n </li>\n ))}\n </ListTag>\n );\n }\n\n return (\n <p\n key={blockIndex}\n style={{\n marginBottom: '1rem',\n lineHeight: '1.6',\n color: theme.textColor,\n fontSize,\n whiteSpace: 'pre-wrap',\n }}\n >\n {lines.map((line, lineIndex) => (\n <Fragment key={lineIndex}>\n {lineIndex > 0 && <br />}\n {renderInlineFormatting(line)}\n </Fragment>\n ))}\n </p>\n );\n })}\n </div>\n );\n};\n\n// Types for the Intent Assistant\nexport interface Suggestion {\n id: string;\n text: string;\n type: 'product' | 'comparison' | 'information' | 'action';\n is_sponsored?: boolean;\n recommendation?: PlatformResponse;\n metadata?: Record<string, unknown>;\n}\n\nexport interface AssistantSourceLink {\n title?: string;\n url: string;\n}\n\nexport interface AssistantRelatedItem {\n title?: string;\n url: string;\n snippet?: string;\n image_url?: string | null;\n publisher?: string | null;\n}\n\nexport interface AssistantQueryResult {\n answer: string;\n source_links?: AssistantSourceLink[];\n related_items?: AssistantRelatedItem[];\n recommendation?: PlatformResponse | null;\n followup_suggestions?: Array<{ text: string; type?: Suggestion['type'] }>;\n}\n\nexport interface AssistantQueryContext {\n sponsoredSuggestion?: Suggestion | null;\n}\n\ntype SuggestionStyle = 'carousel' | 'stacked';\n\nfunction toCssSize(value?: number | string) {\n return value === undefined ? undefined : typeof value === 'number' ? `${value}px` : value;\n}\n\nexport interface AdMeshIntentAssistantProps {\n // AssistantModal Root props\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n unstable_openOnRunStart?: boolean;\n \n // UI Configuration\n layout?: 'floating' | 'inline';\n surface?: 'page' | 'ad-slot';\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n size?: 'sm' | 'md' | 'lg' | 'xl';\n theme?: AdMeshTheme;\n className?: string;\n style?: CSSProperties;\n triggerLabel?: string;\n triggerIcon?: ReactNode;\n headerTitle?: string;\n headerIcon?: ReactNode;\n headerLogoUrl?: string | null;\n showHeaderTitle?: boolean;\n showSubtitle?: boolean;\n panelWidth?: number | string;\n panelHeight?: number | string;\n fontScale?: number;\n analyticsPageUrl?: string;\n \n // Behavior\n autoOpen?: boolean;\n showWelcomeMessage?: boolean;\n welcomeMessage?: string;\n placeholder?: string;\n adsEnabled?: boolean;\n suggestions?: Suggestion[]; // Optional - will use context suggestions if not provided\n maxSuggestions?: number;\n suggestionStyle?: SuggestionStyle;\n onlyShowWhenSponsored?: boolean; // Only show modal when sponsored suggestions are available\n variant?: 'default' | 'legacy';\n queryHandler?: (query: string, context: AssistantQueryContext) => Promise<AssistantQueryResult>;\n suggestionsLoader?: () => Promise<Suggestion[]>;\n disclaimerText?: string;\n poweredByLabel?: string;\n subtitle?: string;\n \n // Events\n onOpen?: () => void;\n onClose?: () => void;\n}\n\nfunction normalizeSuggestionText(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\nfunction mergeSuggestionsPreservingOrganic(\n currentSuggestions: Suggestion[],\n nextSuggestions: Suggestion[],\n): Suggestion[] {\n const currentOrganicSuggestions = currentSuggestions\n .filter((suggestion) => !suggestion?.is_sponsored)\n .slice(0, 3);\n const nextOrganicSuggestions = nextSuggestions\n .filter((suggestion) => !suggestion?.is_sponsored)\n .slice(0, 3);\n\n const sponsoredSuggestion = nextSuggestions.find((suggestion) => suggestion?.is_sponsored);\n\n if (!sponsoredSuggestion) {\n return nextOrganicSuggestions.length ? nextOrganicSuggestions : currentOrganicSuggestions;\n }\n\n const organicSuggestions = nextOrganicSuggestions.length ? nextOrganicSuggestions : currentOrganicSuggestions;\n return [sponsoredSuggestion, ...organicSuggestions].slice(0, 4);\n}\n\nfunction buildFollowupSuggestionsFromAnswer(\n query: string,\n answer: string,\n sourceLinks?: AssistantSourceLink[],\n relatedItems?: AssistantRelatedItem[],\n): Suggestion[] {\n const seen = new Set<string>();\n const suggestions: Suggestion[] = [];\n\n const pushSuggestion = (text: string, type: Suggestion['type'] = 'information') => {\n const normalized = normalizeSuggestionText(text);\n if (!normalized) return;\n const key = normalized.toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n suggestions.push({\n id: `followup_${suggestions.length}_${key.replace(/[^a-z0-9]+/g, '_')}`,\n text: normalized,\n type,\n is_sponsored: false,\n });\n };\n\n const topics = new Set<string>();\n\n const collectTopic = (value?: string | null) => {\n const normalized = normalizeSuggestionText(value || '');\n if (!normalized) return;\n const cleaned = normalized\n .replace(/^(how|why|what|when|where|which|who)\\s+/i, '')\n .replace(/\\?+$/g, '')\n .trim();\n if (!cleaned) return;\n topics.add(cleaned);\n };\n\n (relatedItems || []).forEach((item) => collectTopic(item?.title));\n (sourceLinks || []).forEach((item) => collectTopic(item?.title));\n\n const sentenceMatches = answer\n .split(/\\n+/)\n .map((line) => normalizeSuggestionText(line.replace(/^[-*]\\s+/, '')))\n .filter(Boolean)\n .filter((line) => line.length >= 24 && line.length <= 90);\n\n sentenceMatches.forEach((line) => {\n if (topics.size >= 6) return;\n collectTopic(line);\n });\n\n const cleanQuery = normalizeSuggestionText(query.replace(/[?.!]+$/g, ''));\n const topicList = Array.from(topics).slice(0, 3);\n const continuations = [\n topicList[0] ? `Tell me more about ${topicList[0]}` : '',\n topicList[1] ? `Show me examples related to ${topicList[1]}` : '',\n topicList[2] ? `Compare the main options for ${topicList[2]}` : '',\n `Break this down more simply`,\n `What should I look at next about ${cleanQuery}`,\n `Give me the practical takeaway here`,\n ];\n\n continuations.forEach((text, index) => {\n if (suggestions.length >= 3) return;\n pushSuggestion(text, index === 0 ? 'comparison' : 'information');\n });\n\n return suggestions.slice(0, 3);\n}\n\nfunction detectAssistantDeviceType(): PublisherAssistantAnalyticsEvent['device_type'] {\n if (typeof window === 'undefined') return 'unknown';\n const width = window.innerWidth;\n if (width < 768) return 'mobile';\n if (width < 1024) return 'tablet';\n return 'desktop';\n}\n\nfunction isResolvedPageUrl(value?: string) {\n const trimmed = value?.trim();\n if (!trimmed || /%%[^%]+%%/.test(trimmed)) {\n return false;\n }\n try {\n const parsed = new URL(trimmed);\n return Boolean(parsed.protocol && parsed.hostname);\n } catch {\n return false;\n }\n}\n\nfunction getUsableWindowHref() {\n try {\n const href = window.location.href?.trim();\n if (isResolvedPageUrl(href)) {\n return href;\n }\n } catch {\n return undefined;\n }\n return undefined;\n}\n\nfunction getAssistantPageContext(pageUrlOverride?: string) {\n if (typeof window === 'undefined') {\n return {\n page_url: undefined,\n page_path: undefined,\n article_slug: undefined,\n page_title: undefined,\n referrer: undefined,\n device_type: 'unknown' as const,\n };\n }\n\n const resolvedPageUrl = getUsableWindowHref()\n || (isResolvedPageUrl(pageUrlOverride) ? pageUrlOverride!.trim() : undefined);\n let page_path: string | undefined = resolvedPageUrl ? window.location.pathname || '/' : undefined;\n try {\n page_path = resolvedPageUrl ? new URL(resolvedPageUrl).pathname || '/' : undefined;\n } catch {\n page_path = getUsableWindowHref() ? window.location.pathname || '/' : undefined;\n }\n const segments = (page_path || '').split('/').filter(Boolean);\n\n return {\n page_url: resolvedPageUrl,\n page_path,\n article_slug: segments[segments.length - 1],\n page_title: document.title || undefined,\n referrer: document.referrer || undefined,\n device_type: detectAssistantDeviceType(),\n };\n}\n\nfunction buildSponsoredSuggestionFromRecommendation(recommendation?: PlatformResponse | null): Suggestion | null {\n const suggestionText = recommendation?.recommendation?.creative?.follow_up_suggestion;\n const recommendationId = recommendation?.recommendation_id;\n if (!suggestionText || !recommendationId) {\n return null;\n }\n\n return {\n id: recommendationId,\n text: normalizeSuggestionText(suggestionText),\n type: 'action',\n is_sponsored: true,\n recommendation,\n metadata: {\n source: 'assistant_query_recommendation',\n recommendation_id: recommendationId,\n },\n };\n}\n\nfunction prioritizeSponsoredSuggestions(items: Suggestion[]): Suggestion[] {\n return [...items].sort((left, right) => {\n const leftSponsored = Boolean(left.is_sponsored);\n const rightSponsored = Boolean(right.is_sponsored);\n if (leftSponsored === rightSponsored) {\n return 0;\n }\n return leftSponsored ? -1 : 1;\n });\n}\n\n// Default theme\nconst defaultTheme: AdMeshTheme = {\n mode: 'light',\n primaryColor: '#3b82f6',\n secondaryColor: '#64748b',\n backgroundColor: '#ffffff',\n surfaceColor: '#f8fafc',\n borderColor: '#e2e8f0',\n textColor: '#1e293b',\n textSecondaryColor: '#64748b',\n borderRadius: '0.5rem',\n spacing: {\n small: '0.5rem',\n medium: '1rem',\n large: '1.5rem',\n },\n shadows: {\n small: '0 1px 2px 0 rgb(0 0 0 / 0.05)',\n medium: '0 4px 6px -1px rgb(0 0 0 / 0.1)',\n large: '0 10px 15px -3px rgb(0 0 0 / 0.1)',\n },\n};\n\n// Size configurations\nconst sizeConfig = {\n sm: { width: '320px', height: '400px' },\n md: { width: '400px', height: '500px' },\n lg: { width: '480px', height: '600px' },\n xl: { width: '560px', height: '700px' },\n};\n\n// Position configurations\nconst positionConfig = {\n 'bottom-right': { bottom: '20px', right: '20px' },\n 'bottom-left': { bottom: '20px', left: '20px' },\n 'top-right': { top: '20px', right: '20px' },\n 'top-left': { top: '20px', left: '20px' },\n};\n\n// Main Assistant Component\nexport const AdMeshIntentAssistant: FC<AdMeshIntentAssistantProps> = ({\n theme: propTheme,\n className,\n style,\n triggerLabel = 'Ask Ava',\n headerTitle = 'Ask Ava',\n headerLogoUrl,\n showHeaderTitle = true,\n showSubtitle = true,\n layout = 'floating',\n surface = 'page',\n panelWidth,\n panelHeight,\n analyticsPageUrl,\n fontScale = 1,\n position = 'bottom-right',\n size = 'md',\n // AssistantModal Root props\n defaultOpen,\n open,\n onOpenChange,\n // Behavior props\n autoOpen = false,\n showWelcomeMessage = false,\n welcomeMessage = \"Hi, I’m Ava. I’ll help you find the best options.\",\n placeholder = \"Ask me anything about products...\",\n adsEnabled = true,\n suggestions: propSuggestions, // Renamed to avoid conflict\n maxSuggestions = 6,\n suggestionStyle = 'carousel',\n onlyShowWhenSponsored = false, // New prop to only show modal when sponsored suggestions are available\n variant = 'default',\n queryHandler,\n suggestionsLoader,\n disclaimerText,\n poweredByLabel = 'Powered by AdMesh',\n subtitle = 'Publisher Assistant',\n onOpen,\n onClose,\n}) => {\n // Get AdMesh context\n const { sdk, sessionId, theme: contextTheme, apiKey, userId } = useAdMesh();\n const { \n suggestions: contextSuggestions, \n isAnalyzingIntent, \n intentError,\n retryIntentAnalysis,\n activeDelegationSession,\n hasActiveDelegationSession,\n stopDelegationSession,\n refreshDelegationActivity,\n } = useAdMeshContext();\n useAdMeshStyles();\n \n // Debug: Log context availability\n console.log('[AdMeshIntentAssistant] Context:', { \n sdk:sdk, \n sessionId, \n hasContextTheme: !!contextTheme \n });\n \n // Use prop theme or fallback to context theme or default theme\n const theme = propTheme || contextTheme || defaultTheme;\n const themeMode = theme?.mode || 'light';\n const isAdSlotSurface = surface === 'ad-slot';\n // Use controlled or uncontrolled state based on props\n const [internalOpen, setInternalOpen] = useState(defaultOpen || autoOpen);\n const isControlled = open !== undefined;\n const isOpen = isControlled ? open : internalOpen;\n \n const [inputValue, setInputValue] = useState('');\n type RenderMessage = ChatMessage & {\n sourceLinks?: AssistantSourceLink[];\n relatedItems?: AssistantRelatedItem[];\n initialRecommendation?: PlatformResponse | null;\n responseTimeMs?: number;\n };\n const [messages, setMessages] = useState<RenderMessage[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [isExpanded, setIsExpanded] = useState(false);\n const [sponsoredClickedMessages, setSponsoredClickedMessages] = useState<Set<string>>(new Set());\n const [resolvedSuggestions, setResolvedSuggestions] = useState<Suggestion[]>(propSuggestions || contextSuggestions || []);\n const [loadingLabelIndex, setLoadingLabelIndex] = useState(0);\n const [generationElapsedSec, setGenerationElapsedSec] = useState(0);\n const [messageFeedback, setMessageFeedback] = useState<Record<string, AnswerFeedbackValue>>({});\n const generationStartedAtRef = useRef<number | null>(null);\n const currentMessageIsSponsored = useRef(false);\n const currentSponsoredSuggestionRef = useRef<Suggestion | null>(null);\n const suggestionButtonRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\n const suggestionExposureCleanupRef = useRef<Array<() => void>>([]);\n const messagesScrollRef = useRef<HTMLDivElement>(null);\n const activeSubmittedMessageRef = useRef<HTMLDivElement>(null);\n const activeSubmittedMessageIdRef = useRef<string | null>(null);\n const shouldAnchorSubmittedMessageRef = useRef(false);\n const suppressAutoScrollToBottomRef = useRef(false);\n const adSlotRootRef = useRef<HTMLDivElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const suggestionsScrollRef = useRef<HTMLDivElement>(null);\n const generationAbortRef = useRef<AbortController | null>(null);\n const activeAssistantMessageIdRef = useRef<string | null>(null);\n const [canScrollSuggestionsLeft, setCanScrollSuggestionsLeft] = useState(false);\n const [canScrollSuggestionsRight, setCanScrollSuggestionsRight] = useState(false);\n const canUseDirectAdMeshFetch = Boolean(apiKey?.toLowerCase().startsWith('pub_'));\n const connectedDelegationSession =\n hasActiveDelegationSession() && activeDelegationSession?.session_id === sessionId\n ? activeDelegationSession\n : null;\n const trackedSuggestionExposureKeysRef = useRef<Set<string>>(new Set());\n const trackedRecommendationKeysRef = useRef<Set<string>>(new Set());\n const loadedTrackedRef = useRef(false);\n const shouldExpandAdSlot = isAdSlotSurface && (isExpanded || messages.length > 0 || isLoading);\n const adSlotWidthCss = toCssSize(panelWidth) ?? '100%';\n const adSlotHeightCss = toCssSize(panelHeight) ?? '100%';\n\n const setSuggestionButtonRef = useCallback((suggestionId: string) => {\n return (node: HTMLButtonElement | null) => {\n if (node) {\n suggestionButtonRefs.current.set(suggestionId, node);\n } else {\n suggestionButtonRefs.current.delete(suggestionId);\n }\n };\n }, []);\n\n const trackAssistantEvent = useCallback(\n async (\n event_name: PublisherAssistantAnalyticsEvent['event_name'],\n event: Omit<Partial<PublisherAssistantAnalyticsEvent>, 'event_name' | 'timestamp' | 'session_id'> = {},\n ) => {\n if (!sdk || !sessionId) {\n return;\n }\n\n try {\n await sdk.trackPublisherAssistantEvent({\n event_name,\n timestamp: new Date().toISOString(),\n session_id: sessionId,\n ...getAssistantPageContext(analyticsPageUrl),\n ...event,\n });\n } catch (analyticsError) {\n console.warn(`[AdMeshIntentAssistant] Failed to track ${event_name}`, analyticsError);\n }\n },\n [analyticsPageUrl, sdk, sessionId],\n );\n\n const handleRecommendationShown = useCallback(\n (messageId: string, recommendation: PlatformResponse | null, query?: string) => {\n const recommendationId = recommendation?.recommendation_id;\n if (!recommendationId) {\n return;\n }\n const trackKey = `${messageId}:${recommendationId}`;\n if (trackedRecommendationKeysRef.current.has(trackKey)) {\n return;\n }\n trackedRecommendationKeysRef.current.add(trackKey);\n void trackAssistantEvent('recommendation_shown', {\n message_id: messageId,\n query,\n recommendation_id: recommendationId,\n brand_name: recommendation.recommendation?.creative?.brand_name,\n is_sponsored: true,\n });\n },\n [trackAssistantEvent],\n );\n\n const refreshSuggestionsForResponse = useCallback(\n (\n query: string,\n answer: string,\n sourceLinks?: AssistantSourceLink[],\n relatedItems?: AssistantRelatedItem[],\n recommendation?: PlatformResponse | null,\n followupSuggestions?: Array<{ text: string; type?: Suggestion['type'] }>,\n ) => {\n const generated =\n Array.isArray(followupSuggestions) && followupSuggestions.length\n ? followupSuggestions\n .map((item, index) => {\n const normalizedText = normalizeSuggestionText(item.text || '');\n if (!normalizedText) return null;\n return {\n id: `followup_llm_${index}_${normalizedText.toLowerCase().replace(/[^a-z0-9]+/g, '_')}`,\n text: normalizedText,\n type: item.type || 'information',\n is_sponsored: false,\n } satisfies Suggestion;\n })\n .filter((item): item is Suggestion => Boolean(item))\n .slice(0, 3)\n : buildFollowupSuggestionsFromAnswer(query, answer, sourceLinks, relatedItems);\n const sponsoredSuggestion = buildSponsoredSuggestionFromRecommendation(recommendation);\n const nextSuggestions = sponsoredSuggestion\n ? [sponsoredSuggestion, ...generated.slice(0, 2)]\n : generated.slice(0, 3);\n if (nextSuggestions.length) {\n setResolvedSuggestions(prioritizeSponsoredSuggestions(nextSuggestions));\n }\n },\n [],\n );\n\n const upsertSponsoredFollowupSuggestion = useCallback(\n (\n followupSuggestion: {\n query?: string;\n label?: string;\n engagement_url?: string;\n exposure_url?: string;\n },\n recommendationId: string,\n ) => {\n const suggestionText = normalizeSuggestionText(\n followupSuggestion.query || followupSuggestion.label || '',\n );\n if (!suggestionText || !recommendationId) {\n return;\n }\n\n const sponsoredSuggestion: Suggestion = {\n id: recommendationId,\n text: suggestionText,\n type: 'action',\n is_sponsored: true,\n recommendation: {\n recommendation_id: recommendationId,\n recommendation: {\n creative: {\n follow_up_suggestion: suggestionText,\n },\n },\n tracking: {\n followup_engagement_url: followupSuggestion.engagement_url,\n followup_exposure_url: followupSuggestion.exposure_url,\n },\n } as PlatformResponse,\n };\n\n setResolvedSuggestions((current) => {\n const organic = current.filter((item) => !item.is_sponsored).slice(0, 3);\n return prioritizeSponsoredSuggestions([sponsoredSuggestion, ...organic].slice(0, 4));\n });\n },\n [],\n );\n\n const scrollSubmittedMessageToTop = useCallback(() => {\n const scroller = messagesScrollRef.current;\n const activeMessage = activeSubmittedMessageRef.current;\n if (!scroller || !activeMessage) return false;\n\n const scrollerRect = scroller.getBoundingClientRect();\n const activeMessageRect = activeMessage.getBoundingClientRect();\n const targetTop = Math.max(\n 0,\n scroller.scrollTop + activeMessageRect.top - scrollerRect.top,\n );\n\n scroller.scrollTop = targetTop;\n return true;\n }, []);\n\n // New submissions pin the submitted query to the top of the active\n // message panel while the answer streams below it.\n useLayoutEffect(() => {\n if (shouldAnchorSubmittedMessageRef.current) {\n if (scrollSubmittedMessageToTop()) {\n shouldAnchorSubmittedMessageRef.current = false;\n }\n return;\n }\n\n if (suppressAutoScrollToBottomRef.current) return;\n\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages, scrollSubmittedMessageToTop]);\n\n useLayoutEffect(() => {\n if (!isAdSlotSurface) return;\n const root = adSlotRootRef.current;\n if (!root) return;\n\n const mountNode = root.closest('.admesh-publisher-assistant-reactMount') as HTMLElement | null;\n const nextHeight = adSlotHeightCss;\n\n [root, mountNode].forEach((node) => {\n if (!node) return;\n node.style.width = adSlotWidthCss;\n node.style.maxWidth = adSlotWidthCss;\n node.style.height = nextHeight;\n node.style.maxHeight = nextHeight;\n node.style.overflow = 'hidden';\n node.style.boxSizing = 'border-box';\n node.dataset.admeshAdSlotExpanded = shouldExpandAdSlot ? 'true' : 'false';\n });\n\n const host = mountNode?.parentElement;\n if (host && host !== document.body && host !== document.documentElement) {\n host.style.width = adSlotWidthCss;\n host.style.maxWidth = adSlotWidthCss;\n host.style.height = nextHeight;\n host.style.maxHeight = nextHeight;\n host.style.overflow = 'hidden';\n host.style.boxSizing = 'border-box';\n }\n }, [adSlotHeightCss, adSlotWidthCss, isAdSlotSurface, shouldExpandAdSlot]);\n\n useEffect(() => {\n if (propSuggestions && propSuggestions.length) {\n setResolvedSuggestions(propSuggestions);\n return;\n }\n if (contextSuggestions && contextSuggestions.length) {\n setResolvedSuggestions((currentSuggestions) =>\n mergeSuggestionsPreservingOrganic(currentSuggestions, contextSuggestions)\n );\n }\n }, [propSuggestions, contextSuggestions]);\n\n useEffect(() => {\n if (variant !== 'default') return;\n\n if (!suggestionsLoader) return;\n let cancelled = false;\n suggestionsLoader()\n .then((items) => {\n if (!cancelled && Array.isArray(items) && items.length) {\n setResolvedSuggestions(items);\n }\n })\n .catch((loadError) => {\n console.warn('[AdMeshIntentAssistant] Failed to load suggestions', loadError);\n });\n return () => {\n cancelled = true;\n };\n }, [suggestionsLoader, variant]);\n\n useEffect(() => {\n if (!isLoading) {\n setGenerationElapsedSec(0);\n generationStartedAtRef.current = null;\n return;\n }\n\n if (generationStartedAtRef.current == null) {\n generationStartedAtRef.current = typeof performance !== 'undefined' ? performance.now() : Date.now();\n }\n\n const tick = () => {\n const startedAt = generationStartedAtRef.current;\n if (startedAt == null) {\n return;\n }\n const now = typeof performance !== 'undefined' ? performance.now() : Date.now();\n setGenerationElapsedSec(Math.floor((now - startedAt) / 1000));\n };\n\n tick();\n const interval = window.setInterval(tick, 1000);\n return () => window.clearInterval(interval);\n }, [isLoading]);\n\n useEffect(() => {\n if (!isLoading || variant !== 'default') {\n setLoadingLabelIndex(0);\n return;\n }\n const interval = window.setInterval(() => {\n setLoadingLabelIndex((prev) => Math.min(prev + 1, 7));\n }, 3000);\n return () => window.clearInterval(interval);\n }, [isLoading, variant]);\n\n useEffect(() => {\n if (loadedTrackedRef.current || !sdk || !sessionId) {\n return;\n }\n loadedTrackedRef.current = true;\n void trackAssistantEvent('assistant_loaded', {\n metadata: {\n layout,\n surface,\n variant,\n default_open: defaultOpen || autoOpen,\n },\n });\n }, [autoOpen, defaultOpen, layout, sdk, sessionId, surface, trackAssistantEvent, variant]);\n\n // Handle open state changes\n const handleOpenChange = useCallback((newOpen: boolean) => {\n if (isControlled) {\n onOpenChange?.(newOpen);\n } else {\n setInternalOpen(newOpen);\n }\n \n if (newOpen) {\n void trackAssistantEvent('assistant_opened', {\n metadata: {\n layout,\n surface,\n variant,\n expanded: isExpanded,\n },\n });\n onOpen?.();\n } else {\n onClose?.();\n }\n }, [isControlled, isExpanded, layout, onOpenChange, onOpen, onClose, surface, trackAssistantEvent, variant]);\n\n // Handle opening/closing\n const handleOpenClick = useCallback(() => {\n handleOpenChange(true);\n }, [handleOpenChange]);\n\n const handleCloseClick = useCallback(() => {\n handleOpenChange(false);\n }, [handleOpenChange]);\n\n const handleToggleExpand = useCallback(() => {\n setIsExpanded(prev => !prev);\n }, []);\n\n // Call backend API for assistant response with streaming using SDK\n const callAssistantAPI = useCallback(async (\n message: string,\n messageId?: string,\n onContentChunk?: (content: string) => void,\n onStreamStart?: () => void,\n sponsoredRecommendation?: PlatformResponse | null,\n signal?: AbortSignal,\n ) => {\n if (!sdk) {\n console.warn('[AdMeshIntentAssistant] SDK not available - using fallback response');\n // Return a fallback response when SDK is not available\n return {\n text: \"I'm a demo assistant. The SDK is not properly configured, but I can still help with suggestions! Try clicking on one of the suggested questions above.\",\n };\n }\n \n try {\n if (connectedDelegationSession) {\n await refreshDelegationActivity('turn_started', {\n source: 'publisher_assistant',\n recommendation_id: connectedDelegationSession.recommendation_id,\n }).catch((activityError) => {\n console.warn('[AdMeshIntentAssistant] Failed to report delegation turn_started', activityError);\n });\n }\n\n // Use SDK to make the chat assistant API call\n const response = await fetch(`${sdk.getApiBaseUrl()}/api/chat/assistant`, {\n method: 'POST',\n signal,\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'text/plain',\n 'Cache-Control': 'no-cache',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n message,\n session_id: sessionId || 'default-session',\n message_id: messageId,\n user_id: userId,\n context: {\n timestamp: new Date().toISOString(),\n source: 'admesh-ui-sdk',\n page_context: getAssistantPageContext(analyticsPageUrl),\n sponsored_recommendation: sponsoredRecommendation?.recommendation_id\n ? {\n recommendation_id: sponsoredRecommendation.recommendation_id,\n brand_name: sponsoredRecommendation.recommendation?.creative?.brand_name,\n }\n : undefined,\n active_delegation_session: connectedDelegationSession\n ? {\n delegation_session_id: connectedDelegationSession.delegation_session_id,\n recommendation_id: connectedDelegationSession.recommendation_id,\n session_id: connectedDelegationSession.session_id,\n brand_name: connectedDelegationSession.brand_name,\n mcp_endpoint: connectedDelegationSession.mcp_endpoint,\n status: connectedDelegationSession.status,\n }\n : undefined,\n }\n }),\n });\n\n if (!response.ok) {\n throw new Error(`API request failed: ${response.status} ${response.statusText}`);\n }\n\n // Handle streaming response\n const reader = response.body?.getReader();\n const decoder = new TextDecoder();\n \n if (!reader) {\n throw new Error('Response body is not readable');\n }\n\n let fullResponse = '';\n let finalSourceLinks: AssistantSourceLink[] | undefined;\n let finalRelatedItems: AssistantRelatedItem[] | undefined;\n let finalFollowupSuggestions: Array<{ text: string; type?: Suggestion['type'] }> | undefined;\n let finalUsedCapability: string | undefined;\n let finalResponseTimeMs: number | undefined;\n \n const processStream = async () => {\n try {\n while (true) {\n const { done, value } = await reader.read();\n \n if (done) break;\n \n const chunk = decoder.decode(value, { stream: true });\n const lines = chunk.split('\\n');\n \n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6); // Remove 'data: ' prefix\n \n if (data.trim() === '[DONE]') {\n if (connectedDelegationSession) {\n void refreshDelegationActivity('turn_completed', {\n source: 'publisher_assistant',\n recommendation_id: connectedDelegationSession.recommendation_id,\n }).catch((activityError) => {\n console.warn('[AdMeshIntentAssistant] Failed to report delegation turn_completed', activityError);\n });\n }\n return {\n text: fullResponse,\n source_links: finalSourceLinks,\n related_items: finalRelatedItems,\n followup_suggestions: finalFollowupSuggestions,\n used_capability: finalUsedCapability,\n response_time_ms: finalResponseTimeMs,\n };\n }\n \n try {\n const parsedData = JSON.parse(data);\n \n switch (parsedData.type) {\n case 'content': {\n const content = parsedData.content || '';\n fullResponse += content;\n onContentChunk?.(content);\n break;\n }\n \n case 'final': {\n fullResponse = parsedData.reply || fullResponse;\n finalSourceLinks = Array.isArray(parsedData.source_links) ? parsedData.source_links : undefined;\n finalRelatedItems = Array.isArray(parsedData.related_items) ? parsedData.related_items : undefined;\n finalFollowupSuggestions = Array.isArray(parsedData.followup_suggestions) ? parsedData.followup_suggestions : undefined;\n finalUsedCapability = typeof parsedData.used_capability === 'string' ? parsedData.used_capability : finalUsedCapability;\n finalResponseTimeMs =\n typeof parsedData.response_time_ms === 'number' ? parsedData.response_time_ms : finalResponseTimeMs;\n break;\n }\n\n case 'followup_suggestions': {\n finalFollowupSuggestions = Array.isArray(parsedData.followup_suggestions)\n ? parsedData.followup_suggestions\n : finalFollowupSuggestions;\n break;\n }\n \n case 'error':\n throw new Error(parsedData.message || 'Unknown streaming error');\n \n case 'session_start':\n onStreamStart?.();\n console.log('Session started:', parsedData.session_id);\n break;\n }\n } catch (parseError) {\n console.warn('Failed to parse streaming chunk:', data);\n continue;\n }\n }\n }\n }\n } catch (error) {\n if (signal?.aborted) {\n return {\n text: fullResponse,\n source_links: finalSourceLinks,\n related_items: finalRelatedItems,\n followup_suggestions: finalFollowupSuggestions,\n used_capability: finalUsedCapability,\n response_time_ms: finalResponseTimeMs,\n error: 'aborted',\n };\n }\n console.error('Stream processing error:', error);\n throw error;\n } finally {\n reader.releaseLock();\n }\n \n return {\n text: fullResponse,\n source_links: finalSourceLinks,\n related_items: finalRelatedItems,\n followup_suggestions: finalFollowupSuggestions,\n used_capability: finalUsedCapability,\n response_time_ms: finalResponseTimeMs,\n };\n };\n \n return await processStream();\n \n } catch (error) {\n if (signal?.aborted) {\n return {\n text: '',\n error: 'aborted',\n };\n }\n console.error('Error calling assistant API:', error);\n // Fallback to basic response if API fails\n return {\n text: \"I'm having trouble connecting to my services right now. Please try again in a moment.\",\n error: error instanceof Error ? error.message : 'request_failed',\n };\n }\n }, [sdk, sessionId, apiKey, userId, connectedDelegationSession, refreshDelegationActivity]);\n\n const handleStopGeneration = useCallback(() => {\n const controller = generationAbortRef.current;\n if (!controller || controller.signal.aborted) return;\n controller.abort();\n setIsLoading(false);\n currentSponsoredSuggestionRef.current = null;\n currentMessageIsSponsored.current = false;\n const activeAssistantMessageId = activeAssistantMessageIdRef.current;\n if (activeAssistantMessageId) {\n setMessages(prev => prev.map(msg =>\n msg.id === activeAssistantMessageId && !msg.content.trim()\n ? { ...msg, content: 'Generation stopped.' }\n : msg\n ));\n }\n }, []);\n\n // Handle message sending with streaming\n const handleSendMessage = useCallback(async (message: string) => {\n if (!message.trim() || isLoading) return;\n const startedAt = typeof performance !== 'undefined' ? performance.now() : Date.now();\n const normalizedMessage = message.trim();\n const userMessageId = Date.now().toString();\n const generationController = new AbortController();\n const activeSponsoredSuggestion = currentSponsoredSuggestionRef.current;\n const activeSponsoredRecommendation = activeSponsoredSuggestion?.recommendation || null;\n\n generationAbortRef.current = generationController;\n activeAssistantMessageIdRef.current = null;\n activeSubmittedMessageIdRef.current = userMessageId;\n shouldAnchorSubmittedMessageRef.current = true;\n suppressAutoScrollToBottomRef.current = true;\n currentSponsoredSuggestionRef.current = null;\n setResolvedSuggestions((current) => current.some((suggestion) => suggestion.is_sponsored)\n ? current.filter((suggestion) => !suggestion.is_sponsored)\n : current\n );\n\n // Clear any previous errors\n setError(null);\n\n const userMessage: ChatMessage = {\n id: userMessageId,\n role: 'user',\n content: normalizedMessage,\n timestamp: new Date(),\n };\n\n void trackAssistantEvent('query_submitted', {\n message_id: userMessageId,\n query: normalizedMessage,\n });\n\n setMessages(prev => [...prev, userMessage]);\n setInputValue('');\n setIsLoading(true);\n\n if (variant === 'default' && queryHandler) {\n try {\n const assistantMessageId = (Date.now() + 1).toString();\n const initialAssistantMessage: RenderMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n recommendations: [],\n userQuery: message,\n initialRecommendation: null,\n };\n\n if (currentMessageIsSponsored.current) {\n setSponsoredClickedMessages(prev => new Set([...prev, assistantMessageId]));\n currentMessageIsSponsored.current = false;\n }\n\n setMessages(prev => [...prev, initialAssistantMessage]);\n activeAssistantMessageIdRef.current = assistantMessageId;\n\n const response = await queryHandler(normalizedMessage, {\n sponsoredSuggestion: activeSponsoredSuggestion,\n });\n if (generationController.signal.aborted) {\n currentSponsoredSuggestionRef.current = null;\n return;\n }\n const recommendation =\n response.recommendation ||\n activeSponsoredRecommendation ||\n null;\n\n console.log('[AdMeshIntentAssistant] Query handler completed:', {\n query: message,\n hasResponseRecommendation: !!response.recommendation,\n hasSponsoredSuggestionRecommendation: !!activeSponsoredRecommendation,\n finalRecommendationId: recommendation?.recommendation_id,\n });\n\n setMessages(prev => prev.map(msg =>\n msg.id === assistantMessageId\n ? {\n ...msg,\n content: response.answer,\n sourceLinks: response.source_links,\n relatedItems: response.related_items,\n initialRecommendation: recommendation,\n responseTimeMs:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n }\n : msg\n ));\n refreshSuggestionsForResponse(\n normalizedMessage,\n response.answer,\n response.source_links,\n response.related_items,\n response.recommendation || null,\n response.followup_suggestions,\n );\n void trackAssistantEvent('answer_completed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: recommendation?.recommendation_id,\n brand_name: recommendation?.recommendation?.creative?.brand_name,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: 'completed',\n metadata: {\n variant,\n source: 'query_handler',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n } catch (queryError) {\n console.error('Error sending message:', queryError);\n const errorMessage = queryError instanceof Error ? queryError.message : 'Unknown error occurred';\n setError(errorMessage);\n const errorResponse: RenderMessage = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: 'Sorry, I encountered an error. Please try again.',\n timestamp: new Date(),\n };\n setMessages(prev => [...prev, errorResponse]);\n void trackAssistantEvent('answer_failed', {\n query: normalizedMessage,\n status: errorMessage,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n metadata: {\n variant,\n source: 'query_handler',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n } finally {\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n setIsLoading(false);\n }\n }\n return;\n }\n\n // If SDK is not available, still show a response for demo purposes\n if (!sdk) {\n // Simulate a brief loading delay for better UX\n setTimeout(() => {\n if (generationController.signal.aborted) {\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n }\n return;\n }\n const assistantMessage: ChatMessage = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: \"I'm a demo assistant. The SDK is not properly configured, but I can still help! Try clicking on the suggested questions above, or check your AdMesh API key configuration.\",\n timestamp: new Date(),\n recommendations: [],\n userQuery: message,\n };\n\n setMessages(prev => [...prev, assistantMessage]);\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n setIsLoading(false);\n }\n }, 1000);\n return;\n }\n\n try {\n // Create an initial assistant message for streaming\n const assistantMessageId = (Date.now() + 1).toString();\n const sponsoredRecommendationForMessage = activeSponsoredRecommendation;\n const initialAssistantMessage: RenderMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n timestamp: new Date(),\n recommendations: [],\n userQuery: message,\n initialRecommendation: sponsoredRecommendationForMessage,\n };\n\n // If this message was triggered by a sponsored suggestion, track it to prevent duplicate recommendations\n if (currentMessageIsSponsored.current) {\n setSponsoredClickedMessages(prev => new Set([...prev, assistantMessageId]));\n currentMessageIsSponsored.current = false; // Reset the flag\n }\n\n setMessages(prev => [...prev, initialAssistantMessage]);\n activeAssistantMessageIdRef.current = assistantMessageId;\n\n // Call the streaming backend API\n const response = await callAssistantAPI(\n normalizedMessage,\n userMessageId,\n // Callback for real-time content updates\n (contentChunk: string) => {\n setMessages(prev => prev.map(msg => \n msg.id === assistantMessageId \n ? { ...msg, content: msg.content + contentChunk }\n : msg\n ));\n },\n () => {\n setIsLoading(true);\n setLoadingLabelIndex(0);\n },\n sponsoredRecommendationForMessage,\n generationController.signal,\n );\n if (generationController.signal.aborted) {\n if (!response.text.trim()) {\n setMessages(prev => prev.map(msg =>\n msg.id === assistantMessageId && !msg.content.trim()\n ? { ...msg, content: 'Generation stopped.' }\n : msg\n ));\n }\n void trackAssistantEvent('answer_failed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: sponsoredRecommendationForMessage?.recommendation_id,\n brand_name: sponsoredRecommendationForMessage?.recommendation?.creative?.brand_name,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: 'aborted',\n metadata: {\n variant,\n source: 'api_chat_assistant',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n return;\n }\n \n // Final update with complete response\n const resolvedResponseTimeMs =\n typeof response.response_time_ms === 'number'\n ? response.response_time_ms\n : (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt;\n\n setMessages(prev => prev.map(msg => \n msg.id === assistantMessageId \n ? {\n ...msg,\n content: response.text,\n sourceLinks: response.source_links,\n relatedItems: response.related_items,\n initialRecommendation: msg.initialRecommendation || sponsoredRecommendationForMessage,\n responseTimeMs: resolvedResponseTimeMs,\n }\n : msg\n ));\n refreshSuggestionsForResponse(\n normalizedMessage,\n response.text,\n response.source_links,\n response.related_items,\n null,\n response.followup_suggestions,\n );\n if (response.error) {\n void trackAssistantEvent('answer_failed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: sponsoredRecommendationForMessage?.recommendation_id,\n brand_name: sponsoredRecommendationForMessage?.recommendation?.creative?.brand_name,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: response.error,\n metadata: {\n variant,\n source: 'api_chat_assistant',\n },\n });\n } else {\n void trackAssistantEvent('answer_completed', {\n message_id: assistantMessageId,\n query: normalizedMessage,\n recommendation_id: sponsoredRecommendationForMessage?.recommendation_id,\n brand_name: sponsoredRecommendationForMessage?.recommendation?.creative?.brand_name,\n used_capability: response.used_capability,\n latency_ms: resolvedResponseTimeMs,\n status: 'completed',\n metadata: {\n variant,\n source: 'api_chat_assistant',\n response_time_ms: resolvedResponseTimeMs,\n },\n });\n }\n currentSponsoredSuggestionRef.current = null;\n \n } catch (error) {\n console.error('Error sending message:', error);\n const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';\n setError(errorMessage);\n \n const errorResponse: ChatMessage = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: 'Sorry, I encountered an error. Please try again.',\n timestamp: new Date(),\n };\n setMessages(prev => [...prev, errorResponse]);\n void trackAssistantEvent('answer_failed', {\n query: normalizedMessage,\n latency_ms:\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - startedAt,\n status: errorMessage,\n metadata: {\n variant,\n source: 'api_chat_assistant',\n },\n });\n currentSponsoredSuggestionRef.current = null;\n } finally {\n if (generationAbortRef.current === generationController) {\n generationAbortRef.current = null;\n activeAssistantMessageIdRef.current = null;\n setIsLoading(false);\n }\n }\n }, [isLoading, callAssistantAPI, queryHandler, refreshSuggestionsForResponse, sdk, trackAssistantEvent, variant]);\n\n // Use prop suggestions or fallback to context suggestions\n const suggestions = resolvedSuggestions;\n\n // Check if we have any sponsored suggestions (for onlyShowWhenSponsored logic)\n const hasSponsoredSuggestions = useMemo(\n () => suggestions.some(s => s?.is_sponsored),\n [suggestions]\n );\n\n // Filter suggestions based on the onlyShowWhenSponsored option\n const safeSuggestions = useMemo(\n () => suggestions.filter(\n (suggestion): suggestion is Suggestion => {\n const isValid = Boolean(suggestion && typeof suggestion.id === 'string');\n if (!isValid) return false;\n\n // If onlyShowWhenSponsored is true, only show suggestions if we have at least one sponsored\n if (onlyShowWhenSponsored) {\n // Return all valid suggestions, but only if we have at least one sponsored\n return hasSponsoredSuggestions;\n }\n\n // Otherwise, include all valid suggestions\n return true;\n }\n ),\n [hasSponsoredSuggestions, onlyShowWhenSponsored, suggestions]\n );\n const orderedSuggestions = useMemo(\n () => prioritizeSponsoredSuggestions(safeSuggestions),\n [safeSuggestions]\n );\n\n // Handle suggestion click\n const handleSuggestionClick = useCallback(async (suggestion: Suggestion) => {\n console.log('[AdMeshIntentAssistant] 🖱️ Suggestion clicked:', {\n text: suggestion.text,\n is_sponsored: suggestion.is_sponsored,\n hasRecommendation: !!suggestion.recommendation,\n recommendationId: suggestion.recommendation?.recommendation_id || undefined,\n hasFollowupEngagementUrl: !!suggestion.recommendation?.tracking?.followup_engagement_url,\n sessionId: sessionId\n });\n\n // Set sponsored flag for the next message immediately\n currentMessageIsSponsored.current = suggestion.is_sponsored || false;\n currentSponsoredSuggestionRef.current = suggestion.is_sponsored ? suggestion : null;\n const suggestionPosition = orderedSuggestions.findIndex((item) => item.id === suggestion.id);\n void trackAssistantEvent('suggestion_clicked', {\n suggestion_id: suggestion.id,\n suggestion_text: suggestion.text,\n suggestion_type: suggestion.type,\n suggestion_position: suggestionPosition >= 0 ? suggestionPosition : undefined,\n is_sponsored: suggestion.is_sponsored,\n recommendation_id: suggestion.recommendation?.recommendation_id,\n brand_name: suggestion.recommendation?.recommendation?.creative?.brand_name,\n query: suggestion.text,\n });\n \n // Send the message immediately for instant response\n handleSendMessage(suggestion.text);\n \n // Fire engagement URL for sponsored suggestions asynchronously (non-blocking)\n if (suggestion.is_sponsored && suggestion.recommendation && sdk) {\n // Use setTimeout to make this non-blocking\n setTimeout(async () => {\n try {\n const followupEngagementUrl = suggestion.recommendation!.tracking?.followup_engagement_url;\n const recommendationId = suggestion.recommendation!.recommendation_id;\n \n console.log('[AdMeshIntentAssistant] 🎯 Preparing to fire sponsored suggestion engagement:', {\n followupEngagementUrl,\n recommendationId,\n sessionId\n });\n \n if (followupEngagementUrl && recommendationId && sessionId) {\n console.log('[AdMeshIntentAssistant] 🎯 Firing sponsored suggestion engagement tracking');\n await sdk.fireFollowupEngagement(followupEngagementUrl, recommendationId, sessionId);\n console.log('[AdMeshIntentAssistant] ✅ Engagement tracking fired successfully');\n \n } else {\n console.warn('[AdMeshIntentAssistant] ⚠️ Missing required data for engagement tracking:', {\n hasFollowupEngagementUrl: !!followupEngagementUrl,\n hasRecommendationId: !!recommendationId,\n hasSessionId: !!sessionId\n });\n }\n } catch (error) {\n console.error('[AdMeshIntentAssistant] ❌ Error firing sponsored suggestion engagement:', error);\n // Don't block the user action if engagement tracking fails\n }\n }, 0); // Use setTimeout(0) to make it async but execute immediately\n } else {\n console.log('[AdMeshIntentAssistant] ℹ️ Not a sponsored suggestion or missing data, skipping engagement tracking');\n }\n }, [handleSendMessage, orderedSuggestions, sdk, sessionId, trackAssistantEvent]);\n\n // Position and size styles\n const positionStyle = positionConfig[position];\n const sizeStyle = sizeConfig[size];\n\n // Track suggestion exposure only after the suggestion is actually viewable.\n useEffect(() => {\n suggestionExposureCleanupRef.current.forEach((cleanup) => cleanup());\n suggestionExposureCleanupRef.current = [];\n\n if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') {\n return;\n }\n\n orderedSuggestions.forEach((suggestion, index) => {\n const element = suggestionButtonRefs.current.get(suggestion.id);\n if (!element) {\n return;\n }\n\n const exposureKey = `${sessionId || 'anonymous'}:${suggestion.id}:${suggestion.is_sponsored ? 's' : 'o'}`;\n if (trackedSuggestionExposureKeysRef.current.has(exposureKey)) {\n return;\n }\n\n let viewableTimer: ReturnType<typeof setTimeout> | null = null;\n let observer: IntersectionObserver | null = null;\n\n const cleanup = () => {\n if (viewableTimer) {\n clearTimeout(viewableTimer);\n viewableTimer = null;\n }\n observer?.disconnect();\n observer = null;\n };\n\n const fireSuggestionExposure = () => {\n if (trackedSuggestionExposureKeysRef.current.has(exposureKey)) {\n cleanup();\n return;\n }\n\n trackedSuggestionExposureKeysRef.current.add(exposureKey);\n cleanup();\n\n void trackAssistantEvent('suggestion_exposure', {\n suggestion_id: suggestion.id,\n suggestion_text: suggestion.text,\n suggestion_type: suggestion.type,\n suggestion_position: index,\n is_sponsored: suggestion.is_sponsored,\n recommendation_id: suggestion.recommendation?.recommendation_id,\n brand_name: suggestion.recommendation?.recommendation?.creative?.brand_name,\n });\n\n if (sdk && sessionId && suggestion.is_sponsored && suggestion.recommendation) {\n const exposureUrl = suggestion.recommendation.tracking?.followup_exposure_url;\n const recommendationId = suggestion.recommendation.recommendation_id;\n\n if (exposureUrl && recommendationId) {\n console.log('[AdMeshIntentAssistant] 🎯 Firing viewable sponsored suggestion exposure:', {\n exposureUrl,\n recommendationId,\n suggestionText: suggestion.text,\n sessionId\n });\n\n sdk.fireFollowupExposure(exposureUrl, recommendationId, sessionId);\n } else {\n console.warn('[AdMeshIntentAssistant] ⚠️ Missing exposure URL or recommendation ID for sponsored suggestion:', {\n hasExposureUrl: !!exposureUrl,\n hasRecommendationId: !!recommendationId,\n suggestionText: suggestion.text\n });\n }\n }\n };\n\n observer = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (!entry) {\n return;\n }\n\n if (entry.intersectionRatio >= 0.5) {\n if (!viewableTimer) {\n viewableTimer = setTimeout(fireSuggestionExposure, 1000);\n }\n return;\n }\n\n if (viewableTimer) {\n clearTimeout(viewableTimer);\n viewableTimer = null;\n }\n },\n { threshold: [0, 0.25, 0.5, 0.75, 1], rootMargin: '0px' }\n );\n\n observer.observe(element);\n suggestionExposureCleanupRef.current.push(cleanup);\n });\n\n return () => {\n suggestionExposureCleanupRef.current.forEach((cleanup) => cleanup());\n suggestionExposureCleanupRef.current = [];\n };\n }, [orderedSuggestions, sdk, sessionId, trackAssistantEvent]);\n\n // Debug log received suggestions and analysis state\n console.log('[AdMeshIntentAssistant] 📥 Received suggestions:', {\n totalSuggestions: suggestions.length,\n safeSuggestions: safeSuggestions.length,\n isAnalyzingIntent,\n hasIntentError: !!intentError,\n onlyShowWhenSponsored,\n hasSponsoredSuggestions,\n sponsoredCount: suggestions.filter(s => s?.is_sponsored).length,\n nonSponsoredCount: suggestions.filter(s => s && !s?.is_sponsored).length,\n modalShouldAppear: onlyShowWhenSponsored ? hasSponsoredSuggestions : true,\n suggestions: suggestions.map(s => ({\n id: s?.id,\n text: s?.text,\n type: s?.type,\n is_sponsored: s?.is_sponsored,\n hasRecommendation: !!s?.recommendation,\n recommendationId: s?.recommendation?.recommendation_id || undefined,\n hasFollowupEngagementUrl: !!s?.recommendation?.tracking?.followup_engagement_url\n })),\n renderedSuggestions: orderedSuggestions.map(s => ({\n id: s?.id,\n text: s?.text,\n type: s?.type,\n is_sponsored: s?.is_sponsored,\n hasRecommendation: !!s?.recommendation,\n recommendationId: s?.recommendation?.recommendation_id || undefined,\n hasFollowupEngagementUrl: !!s?.recommendation?.tracking?.followup_engagement_url\n }))\n });\n const fontSizes = {\n base: `${16 * fontScale}px`,\n sm: `${14 * fontScale}px`,\n xs: `${12 * fontScale}px`,\n };\n const genericDisclaimer = disclaimerText || 'AI-generated responses may contain errors. Please verify important information independently.';\n const loadingSteps = [\n 'Searching trusted sources...',\n 'Reviewing publisher coverage...',\n 'Checking relevant context...',\n 'Comparing supporting signals...',\n 'Identifying the strongest examples...',\n 'Organizing the most useful details...',\n 'Shaping the response for clarity...',\n 'Preparing the clearest answer...',\n 'Finishing the response...',\n ];\n\n const renderGeneratingIndicator = (options?: {\n compact?: boolean;\n accentColor?: string;\n metaColor?: string;\n includeSteps?: boolean;\n }) => {\n const accent = options?.accentColor || publisherAccent;\n const meta = options?.metaColor || publisherMeta;\n const includeSteps = options?.includeSteps ?? variant === 'default';\n const timerLabel = `${generationElapsedSec}s`;\n const statusLabel = includeSteps\n ? `${loadingSteps[loadingLabelIndex]} (${timerLabel})`\n : `Generating answer... ${timerLabel}`;\n\n return (\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: options?.compact ? '8px' : '10px',\n color: meta,\n fontSize: options?.compact ? fontSizes.xs : fontSizes.sm,\n }}\n >\n <span\n style={{\n width: options?.compact ? 8 : 9,\n height: options?.compact ? 8 : 9,\n borderRadius: 999,\n background: accent,\n animation: 'admeshPulse 1.4s ease-in-out infinite',\n boxShadow: `0 0 0 0 ${withAlpha(brandPrimary, 0.28)}`,\n flexShrink: 0,\n }}\n />\n <span>{statusLabel}</span>\n </div>\n );\n };\n\n const handleAnswerFeedback = useCallback(\n (message: RenderMessage, helpful: boolean) => {\n if (messageFeedback[message.id]) {\n return;\n }\n\n const feedbackValue: AnswerFeedbackValue = helpful ? 'helpful' : 'not_helpful';\n setMessageFeedback((prev) => ({ ...prev, [message.id]: feedbackValue }));\n void trackAssistantEvent('answer_feedback', {\n message_id: message.id,\n query: message.userQuery,\n status: feedbackValue,\n latency_ms: message.responseTimeMs,\n metadata: {\n helpful,\n },\n });\n },\n [messageFeedback, trackAssistantEvent],\n );\n\n function renderAnswerFooter(message: RenderMessage, options?: { accentColor?: string; metaColor?: string }) {\n if (message.role !== 'assistant' || !message.content.trim()) {\n return null;\n }\n\n if (isLoading && message.id === activeAssistantMessageIdRef.current) {\n return null;\n }\n\n const accent = options?.accentColor || publisherAccent;\n const meta = options?.metaColor || publisherMeta;\n const selectedFeedback = messageFeedback[message.id];\n const hasTiming = typeof message.responseTimeMs === 'number';\n\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n marginTop: '10px',\n paddingTop: '10px',\n borderTop: `1px solid ${withAlpha(brandPrimary, 0.08)}`,\n flexWrap: 'nowrap',\n }}\n >\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n minWidth: 0,\n flex: '1 1 auto',\n }}\n >\n <span style={{ fontSize: fontSizes.xs, color: meta, whiteSpace: 'nowrap' }}>\n {selectedFeedback ? 'Thanks for your feedback' : 'Is this helpful?'}\n </span>\n {!selectedFeedback ? (\n <div style={{ display: 'inline-flex', alignItems: 'center', gap: '6px', flexShrink: 0 }}>\n <button\n type=\"button\"\n aria-label=\"Mark answer as helpful\"\n onClick={() => handleAnswerFeedback(message, true)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandPrimary, 0.12)}`,\n background: '#ffffff',\n color: meta,\n cursor: 'pointer',\n }}\n >\n <ThumbsUp size={14} />\n </button>\n <button\n type=\"button\"\n aria-label=\"Mark answer as not helpful\"\n onClick={() => handleAnswerFeedback(message, false)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandPrimary, 0.12)}`,\n background: '#ffffff',\n color: meta,\n cursor: 'pointer',\n }}\n >\n <ThumbsDown size={14} />\n </button>\n </div>\n ) : (\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 28,\n height: 28,\n borderRadius: 999,\n background: withAlpha(accent, 0.12),\n color: accent,\n flexShrink: 0,\n }}\n >\n {selectedFeedback === 'helpful' ? <ThumbsUp size={14} /> : <ThumbsDown size={14} />}\n </span>\n )}\n </div>\n {hasTiming ? (\n <span\n style={{\n fontSize: fontSizes.xs,\n color: meta,\n whiteSpace: 'nowrap',\n flexShrink: 0,\n marginLeft: 'auto',\n }}\n >\n Answer Completed in {formatGenerationDurationFromMs(message.responseTimeMs!)}\n </span>\n ) : null}\n </div>\n );\n }\n\n const updateSuggestionScrollState = useCallback(() => {\n const node = suggestionsScrollRef.current;\n if (!node) return;\n const maxScrollLeft = Math.max(0, node.scrollWidth - node.clientWidth);\n setCanScrollSuggestionsLeft(node.scrollLeft > 4);\n setCanScrollSuggestionsRight(node.scrollLeft < maxScrollLeft - 4);\n }, []);\n\n useEffect(() => {\n updateSuggestionScrollState();\n window.addEventListener('resize', updateSuggestionScrollState);\n return () => window.removeEventListener('resize', updateSuggestionScrollState);\n }, [updateSuggestionScrollState, orderedSuggestions.length]);\n\n const scrollSuggestions = useCallback((direction: 'left' | 'right') => {\n const node = suggestionsScrollRef.current;\n if (!node) return;\n node.scrollBy({\n left: direction === 'left' ? -Math.max(160, Math.floor(node.clientWidth * 0.75)) : Math.max(160, Math.floor(node.clientWidth * 0.75)),\n behavior: 'smooth',\n });\n }, []);\n\n const withAlpha = (hex: string | undefined, alpha: number) => {\n if (!hex || !hex.startsWith('#')) return `rgba(15, 23, 42, ${alpha})`;\n const raw = hex.slice(1);\n const full = raw.length === 3 ? raw.split('').map((char) => `${char}${char}`).join('') : raw;\n if (full.length !== 6) return hex;\n const red = parseInt(full.slice(0, 2), 16);\n const green = parseInt(full.slice(2, 4), 16);\n const blue = parseInt(full.slice(4, 6), 16);\n return `rgba(${red}, ${green}, ${blue}, ${alpha})`;\n };\n\n const brandPrimary = theme.primaryColor || '#3F037F';\n const brandSurface = theme.surfaceColor || '#ffffff';\n const brandBackground = theme.backgroundColor || '#eef2ff';\n const brandBorder = theme.borderColor || '#e5e7eb';\n const brandText = theme.textColor || '#111827';\n const brandMuted = theme.textSecondaryColor || '#6b7280';\n const brandAccentSoft = withAlpha(brandPrimary, 0.12);\n const purpleBorderSoft = withAlpha(brandPrimary, 0.24);\n const purpleBorderStrong = withAlpha(brandPrimary, 0.38);\n const purpleShadowSoft = withAlpha(brandPrimary, 0.12);\n const publisherPanelWidth = isAdSlotSurface ? adSlotWidthCss : isExpanded ? 'min(960px, calc(100vw - 24px))' : layout === 'inline' ? '100%' : 'min(420px, calc(100vw - 32px))';\n const publisherPanelHeight = isAdSlotSurface ? adSlotHeightCss : isExpanded ? 'min(78vh, 760px)' : 'auto';\n const publisherPanelMaxWidth = isAdSlotSurface ? adSlotWidthCss : '100%';\n const publisherPanelMaxHeight = isAdSlotSurface ? adSlotHeightCss : undefined;\n const publisherMessageFontSize = isAdSlotSurface ? '13px' : '16.25px';\n const publisherSurfaceBg = `linear-gradient(180deg, ${withAlpha(brandPrimary, 0.04)} 0%, ${withAlpha(brandPrimary, 0.08)} 100%)`;\n const publisherAccent = brandPrimary;\n const publisherMuted = brandMuted;\n const publisherMeta = brandMuted;\n const assistantSubtitle = subtitle || 'Publisher Assistant';\n const shouldShowSuggestionSkeletons = isAnalyzingIntent && orderedSuggestions.length === 0 && messages.length === 0;\n const expandedShellBackground = '#f7f8fc';\n const expandedPanelBackground = '#ffffff';\n const expandedHeaderBackground = 'linear-gradient(180deg, rgba(255,255,255,0.96) 0%, rgba(248,250,252,0.98) 100%)';\n const expandedBorder = 'rgba(15, 23, 42, 0.08)';\n const expandedBorderStrong = 'rgba(15, 23, 42, 0.12)';\n const expandedShadow = '0 24px 60px rgba(15, 23, 42, 0.16)';\n const expandedMutedText = '#667085';\n const expandedSubtleText = '#98a2b3';\n const expandedUserBubble = publisherAccent;\n const expandedAssistantBubble = '#f8fafc';\n const expandedChipBackground = '#f8fafc';\n const expandedChipBorder = 'rgba(15, 23, 42, 0.08)';\n const expandedComposerBackground = '#ffffff';\n const expandedComposerShadow = '0 8px 24px rgba(15, 23, 42, 0.08)';\n const expandedOverlay = 'rgba(15, 23, 42, 0.18)';\n\n function renderDelegationBanner(mode: 'default' | 'legacy') {\n if (!connectedDelegationSession) {\n return null;\n }\n\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n padding: mode === 'default' ? '10px 12px' : '8px 10px',\n borderRadius: mode === 'default' ? '14px' : '12px',\n border: `1px solid ${purpleBorderSoft}`,\n background: withAlpha('#ffffff', 0.9),\n marginBottom: '4px',\n }}\n >\n <div style={{ minWidth: 0 }}>\n <div\n style={{\n color: publisherAccent,\n fontSize: fontSizes.xs,\n fontWeight: 700,\n textTransform: 'uppercase',\n letterSpacing: '0.06em',\n }}\n >\n Agent Connected\n </div>\n <div style={{ color: brandText, fontSize: fontSizes.sm, fontWeight: 600, lineHeight: 1.3 }}>\n {connectedDelegationSession.brand_name} agent is active\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => {\n void stopDelegationSession('user_stopped', { source: 'publisher_assistant' });\n }}\n style={{\n border: `1px solid ${purpleBorderSoft}`,\n borderRadius: 999,\n background: withAlpha('#ffffff', 0.92),\n color: publisherAccent,\n padding: '7px 12px',\n fontSize: fontSizes.xs,\n fontWeight: 700,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n }}\n >\n Stop\n </button>\n </div>\n );\n }\n\n function renderExpandedBranding(mode: 'default' | 'legacy') {\n const compact = isAdSlotSurface;\n\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: compact ? 'column' : 'row',\n alignItems: compact ? 'center' : mode === 'default' ? 'center' : 'flex-start',\n justifyContent: compact ? 'center' : 'space-between',\n gap: compact ? '2px' : '12px',\n flexWrap: 'wrap',\n paddingTop: compact ? '2px' : mode === 'default' ? '2px' : '8px',\n borderTop: mode === 'default' ? `1px solid ${expandedBorder}` : 'none',\n marginTop: compact ? '0' : mode === 'default' ? '4px' : 0,\n flexShrink: 0,\n }}\n >\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: compact ? '4px' : '8px',\n color: expandedSubtleText,\n fontSize: compact ? '9.5px' : '11px',\n fontWeight: 700,\n letterSpacing: '0.01em',\n }}\n >\n <span>\n Powered by{' '}\n <a\n href=\"https://useadmesh.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit', textDecoration: 'none', fontWeight: 700 }}\n >\n AdMesh\n </a>\n </span>\n </div>\n <div\n style={{\n color: expandedSubtleText,\n fontSize: compact ? '9px' : '11px',\n lineHeight: compact ? 1.25 : 1.45,\n maxWidth: compact ? '100%' : mode === 'default' ? '68%' : '100%',\n textAlign: compact ? 'center' : mode === 'default' ? 'right' : 'left',\n }}\n >\n {genericDisclaimer}\n </div>\n </div>\n );\n }\n\n function renderSuggestionSkeletons(mode: 'publisher' | 'legacy') {\n const skeletonWidths = mode === 'publisher' ? [180, 220, 196] : ['100%', '82%', '68%'];\n if (mode === 'publisher') {\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div\n style={{\n width: 28,\n height: 28,\n borderRadius: 999,\n background: withAlpha(brandPrimary, 0.10),\n flexShrink: 0,\n }}\n />\n <div\n style={{\n display: 'flex',\n gap: '10px',\n overflow: 'hidden',\n flex: 1,\n }}\n >\n {skeletonWidths.map((width, index) => (\n <div\n key={`suggestion-skeleton-${index}`}\n style={{\n width,\n maxWidth: '100%',\n height: 40,\n borderRadius: 999,\n background: `linear-gradient(90deg, ${withAlpha(brandPrimary, 0.08)} 0%, ${withAlpha(brandPrimary, 0.18)} 50%, ${withAlpha(brandPrimary, 0.08)} 100%)`,\n backgroundSize: '200% 100%',\n animation: 'admeshShimmer 1.4s ease-in-out infinite',\n boxShadow: `0 8px 22px ${withAlpha(brandPrimary, 0.08)}`,\n flexShrink: 0,\n }}\n />\n ))}\n </div>\n <div\n style={{\n width: 28,\n height: 28,\n borderRadius: 999,\n background: withAlpha(brandPrimary, 0.10),\n flexShrink: 0,\n }}\n />\n </div>\n );\n }\n\n return (\n <div\n aria-hidden=\"true\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: mode === 'publisher' ? '10px' : '12px',\n }}\n >\n {skeletonWidths.map((width, index) => (\n <div\n key={`suggestion-skeleton-${index}`}\n style={{\n width,\n maxWidth: '100%',\n height: mode === 'publisher' ? 40 : 52,\n borderRadius: 999,\n background: `linear-gradient(90deg, ${withAlpha(brandPrimary, 0.08)} 0%, ${withAlpha(brandPrimary, 0.18)} 50%, ${withAlpha(brandPrimary, 0.08)} 100%)`,\n backgroundSize: '200% 100%',\n animation: 'admeshShimmer 1.4s ease-in-out infinite',\n boxShadow: mode === 'publisher' ? `0 8px 22px ${withAlpha(brandPrimary, 0.08)}` : 'none',\n }}\n />\n ))}\n </div>\n );\n }\n\n function renderPublisherSuggestions() {\n if (isLoading) return null;\n if (shouldShowSuggestionSkeletons) {\n return renderSuggestionSkeletons('publisher');\n }\n if (!orderedSuggestions.length) return null;\n const visibleSuggestions = orderedSuggestions.slice(0, maxSuggestions);\n if (suggestionStyle === 'stacked') {\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: isAdSlotSurface ? '6px' : '8px',\n flexShrink: 0,\n overflowY: 'auto',\n maxHeight: isAdSlotSurface ? '240px' : undefined,\n paddingRight: isAdSlotSurface ? '2px' : 0,\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n }}\n >\n {visibleSuggestions.map((suggestion) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => {\n if (variant === 'default') {\n setIsExpanded(true);\n if (layout === 'floating') {\n handleOpenChange(true);\n }\n }\n handleSuggestionClick(suggestion);\n }}\n type=\"button\"\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n width: '100%',\n minWidth: 0,\n borderRadius: isAdSlotSurface ? '12px' : '14px',\n border: suggestion.is_sponsored\n ? `1px solid ${withAlpha(brandPrimary, 0.32)}`\n : `1px solid ${withAlpha(brandPrimary, 0.42)}`,\n background: suggestion.is_sponsored ? brandPrimary : withAlpha('#ffffff', 0.94),\n color: suggestion.is_sponsored ? '#ffffff' : brandText,\n padding: isAdSlotSurface ? '8px 10px' : '10px 14px',\n fontSize: isAdSlotSurface ? '12px' : '13px',\n fontWeight: 500,\n lineHeight: 1.25,\n textAlign: 'left',\n boxShadow: suggestion.is_sponsored\n ? `0 8px 18px ${withAlpha(brandPrimary, 0.14)}`\n : '0 4px 12px rgba(15, 23, 42, 0.05)',\n cursor: 'pointer',\n }}\n >\n <span style={{ minWidth: 0 }}>{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <span\n style={{\n flexShrink: 0,\n borderRadius: 999,\n background: withAlpha('#ffffff', 0.18),\n padding: '2px 6px',\n fontSize: '10px',\n fontWeight: 700,\n }}\n >\n Ad\n </span>\n )}\n </button>\n ))}\n </div>\n );\n }\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: isAdSlotSurface ? '6px' : '10px', flexShrink: 0 }}>\n <button\n type=\"button\"\n onClick={() => scrollSuggestions('left')}\n disabled={!canScrollSuggestionsLeft}\n aria-label=\"Scroll suggestions left\"\n style={{\n width: isAdSlotSurface ? 24 : 28,\n height: isAdSlotSurface ? 24 : 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandBorder, 0.8)}`,\n background: withAlpha('#ffffff', 0.9),\n color: '#6b7280',\n cursor: canScrollSuggestionsLeft ? 'pointer' : 'default',\n opacity: canScrollSuggestionsLeft ? 1 : 0.55,\n }}\n >\n ‹\n </button>\n <div\n ref={suggestionsScrollRef}\n onScroll={updateSuggestionScrollState}\n style={{\n display: 'flex',\n gap: isAdSlotSurface ? '6px' : '10px',\n overflowX: 'auto',\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n flex: 1,\n }}\n >\n {visibleSuggestions.map((suggestion) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => {\n if (variant === 'default') {\n setIsExpanded(true);\n if (layout === 'floating') {\n handleOpenChange(true);\n }\n }\n handleSuggestionClick(suggestion);\n }}\n type=\"button\"\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n whiteSpace: 'nowrap',\n borderRadius: 999,\n border: suggestion.is_sponsored\n ? `1px solid ${withAlpha(brandPrimary, 0.32)}`\n : `1px solid ${withAlpha(brandPrimary, 0.42)}`,\n background: suggestion.is_sponsored ? brandPrimary : withAlpha('#ffffff', 0.94),\n color: suggestion.is_sponsored ? '#ffffff' : brandText,\n padding: isAdSlotSurface ? '7px 10px' : '8px 14px',\n fontSize: isAdSlotSurface ? '12px' : '13px',\n fontWeight: 500,\n boxShadow: suggestion.is_sponsored\n ? `0 8px 18px ${withAlpha(brandPrimary, 0.14)}`\n : '0 4px 12px rgba(15, 23, 42, 0.05)',\n cursor: 'pointer',\n }}\n >\n <span>{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <sup style={{ fontSize: '10px', opacity: 0.9 }}>Ad</sup>\n )}\n </button>\n ))}\n </div>\n <button\n type=\"button\"\n onClick={() => scrollSuggestions('right')}\n disabled={!canScrollSuggestionsRight}\n aria-label=\"Scroll suggestions right\"\n style={{\n width: isAdSlotSurface ? 24 : 28,\n height: isAdSlotSurface ? 24 : 28,\n borderRadius: 999,\n border: `1px solid ${withAlpha(brandBorder, 0.8)}`,\n background: withAlpha('#ffffff', 0.9),\n color: '#6b7280',\n cursor: canScrollSuggestionsRight ? 'pointer' : 'default',\n opacity: canScrollSuggestionsRight ? 1 : 0.55,\n }}\n >\n ›\n </button>\n </div>\n );\n }\n\n function renderSourceLinks(message: RenderMessage) {\n if (message.relatedItems?.length) return null;\n if (!message.sourceLinks?.length) return null;\n return (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '12px' }}>\n {message.sourceLinks.map((link) => (\n <a\n key={`${message.id}-${link.url}`}\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={() => {\n void trackAssistantEvent('source_link_clicked', {\n message_id: message.id,\n query: message.userQuery,\n metadata: {\n source_title: link.title,\n source_url: link.url,\n },\n });\n }}\n style={{\n color: publisherAccent,\n fontSize: fontSizes.xs,\n textDecoration: 'none',\n borderBottom: `1px solid ${withAlpha(brandPrimary, 0.18)}`,\n }}\n >\n {link.title || link.url}\n </a>\n ))}\n </div>\n );\n }\n\n function renderRelatedItems(message: RenderMessage) {\n if (!message.relatedItems?.length) return null;\n return (\n <div style={{ marginTop: '14px' }}>\n <div style={{ fontSize: fontSizes.xs, fontWeight: 700, color: '#4b5563', marginBottom: '8px' }}>Related</div>\n <div\n style={{\n display: 'flex',\n gap: isAdSlotSurface ? '8px' : '10px',\n overflowX: 'auto',\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n padding: '2px 2px 6px',\n maxWidth: '100%',\n scrollSnapType: 'x proximity',\n }}\n >\n {message.relatedItems.slice(0, 4).map((item) => (\n <a\n key={`${message.id}-${item.url}`}\n href={item.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={() => {\n void trackAssistantEvent('source_link_clicked', {\n message_id: message.id,\n query: message.userQuery,\n metadata: {\n source_title: item.title,\n source_url: item.url,\n source_publisher: item.publisher,\n source_type: 'related_item',\n },\n });\n }}\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: isAdSlotSurface ? '6px' : '10px',\n padding: isAdSlotSurface ? '10px' : '14px',\n borderRadius: isAdSlotSurface ? '12px' : '14px',\n textDecoration: 'none',\n color: brandText,\n border: `1px solid ${withAlpha(brandPrimary, 0.18)}`,\n background: '#ffffff',\n boxShadow: '0 10px 24px rgba(15, 23, 42, 0.08)',\n flex: isAdSlotSurface\n ? '0 0 min(220px, calc(100% - 8px))'\n : '0 0 min(250px, calc(100% - 16px))',\n minWidth: 0,\n maxWidth: isAdSlotSurface ? '220px' : '250px',\n flexShrink: 0,\n scrollSnapAlign: 'start',\n boxSizing: 'border-box',\n }}\n >\n <div\n style={{\n fontSize: isAdSlotSurface ? '13px' : '18px',\n fontWeight: 650,\n lineHeight: 1.35,\n color: brandPrimary,\n overflowWrap: 'anywhere',\n }}\n >\n {item.title || item.url}\n </div>\n {item.publisher && (\n <div\n style={{\n fontSize: isAdSlotSurface ? '11px' : '15px',\n color: '#6b7280',\n lineHeight: 1.4,\n overflowWrap: 'anywhere',\n }}\n >\n {item.publisher}\n </div>\n )}\n </a>\n ))}\n </div>\n </div>\n );\n }\n\n function renderPublisherMessages() {\n return (\n <div\n ref={messagesScrollRef}\n style={{\n flex: isAdSlotSurface ? '1 1 0' : 1,\n minHeight: 0,\n maxHeight: '100%',\n overflowY: 'auto',\n overscrollBehavior: isAdSlotSurface ? 'contain' : undefined,\n WebkitOverflowScrolling: 'touch',\n scrollbarWidth: 'none',\n msOverflowStyle: 'none',\n padding: isAdSlotSurface ? '0 2px 4px' : isExpanded ? '16px 16px 8px' : 0,\n }}\n >\n {messages.map((message) => {\n const isActiveSubmittedMessage =\n message.role === 'user' &&\n message.id === activeSubmittedMessageIdRef.current;\n\n return (\n <div\n key={message.id}\n ref={isActiveSubmittedMessage ? activeSubmittedMessageRef : undefined}\n style={{ marginBottom: '12px', textAlign: message.role === 'user' ? 'right' : 'left' }}\n >\n {(() => {\n const answerHasStarted = Boolean(message.content.trim());\n const shouldShowRecommendations = answerHasStarted || !isLoading;\n\n return (\n <>\n <div\n style={{\n display: message.role === 'assistant' ? 'block' : 'inline-block',\n width: message.role === 'assistant' ? '100%' : undefined,\n maxWidth: message.role === 'assistant' ? '100%' : '76%',\n padding: message.role === 'assistant' ? '4px 6px 4px 2px' : '10px 14px',\n borderRadius: message.role === 'assistant' ? 0 : '18px',\n background: message.role === 'user' ? publisherAccent : 'transparent',\n color: message.role === 'user' ? '#ffffff' : brandText,\n boxShadow: 'none',\n border: 'none',\n fontSize: message.role === 'assistant' ? publisherMessageFontSize : isAdSlotSurface ? '12px' : '13px',\n lineHeight: message.role === 'assistant' ? 1.62 : 1.4,\n }}\n >\n {message.role === 'assistant' ? (\n message.content.trim() ? (\n <CustomMarkdownRenderer content={message.content} theme={{ ...theme, textColor: brandText }} fontSize={publisherMessageFontSize} />\n ) : isLoading && message.id === activeAssistantMessageIdRef.current ? (\n renderGeneratingIndicator({ includeSteps: true })\n ) : null\n ) : (\n <p style={{ margin: 0 }}>{message.content}</p>\n )}\n {message.role === 'assistant' && renderSourceLinks(message)}\n {message.role === 'assistant' && renderRelatedItems(message)}\n {message.role === 'assistant' && renderAnswerFooter(message)}\n {message.role === 'assistant' && shouldShowRecommendations && sponsoredClickedMessages.has(message.id) && message.initialRecommendation && (\n <div style={{ marginTop: '14px' }}>\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n initialRecommendation={message.initialRecommendation}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(recommendationError) => {\n console.error('[AdMeshIntentAssistant] Recommendation error:', recommendationError);\n }}\n />\n </div>\n )}\n {message.role === 'assistant' && shouldShowRecommendations && !sponsoredClickedMessages.has(message.id) && (message.initialRecommendation || canUseDirectAdMeshFetch) && (\n <div style={{ marginTop: '14px' }}>\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n initialRecommendation={message.initialRecommendation || undefined}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(recommendationError) => {\n console.error('[AdMeshIntentAssistant] Recommendation error:', recommendationError);\n }}\n />\n </div>\n )}\n </div>\n </>\n );\n })()}\n </div>\n );\n })}\n\n {error && (\n <div style={{ color: publisherMeta, fontSize: fontSizes.sm }}>Connection issue. Please try again.</div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n );\n }\n\n if (variant === 'default') {\n const teaser = (\n <div\n style={{\n width: publisherPanelWidth,\n maxWidth: publisherPanelMaxWidth,\n height: publisherPanelHeight,\n maxHeight: publisherPanelMaxHeight,\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n background: isExpanded ? expandedShellBackground : publisherSurfaceBg,\n borderRadius: isAdSlotSurface ? '12px' : isExpanded ? '18px' : '20px',\n padding: isExpanded ? 0 : isAdSlotSurface ? '8px' : '12px',\n boxShadow: isExpanded ? expandedShadow : 'none',\n border: isExpanded ? `1px solid ${expandedBorderStrong}` : 'none',\n overflow: 'hidden',\n minHeight: isAdSlotSurface ? 0 : undefined,\n }}\n >\n {(isExpanded || isAdSlotSurface) && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: isAdSlotSurface ? '10px 12px' : '16px 18px',\n background: isExpanded ? expandedHeaderBackground : '#ffffff29',\n color: brandText,\n borderBottom: `1px solid ${expandedBorder}`,\n flexShrink: 0,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>\n <div\n style={{\n width: isAdSlotSurface ? 30 : 40,\n height: isAdSlotSurface ? 30 : 40,\n borderRadius: isAdSlotSurface ? '10px' : '14px',\n background: withAlpha(brandPrimary, 0.08),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 16,\n fontWeight: 700,\n color: publisherAccent,\n overflow: 'hidden',\n }}\n >\n {headerLogoUrl ? (\n <img src={headerLogoUrl} alt={`${headerTitle || 'Assistant'} logo`} style={{ width: '100%', height: '100%', objectFit: 'contain', background: '#ffffff', padding: 4 }} />\n ) : (\n (headerTitle || 'AA').slice(0, 2).toUpperCase()\n )}\n </div>\n {(showHeaderTitle || showSubtitle) && (\n <div>\n {showHeaderTitle && <div style={{ fontSize: isAdSlotSurface ? '14px' : '20px', fontWeight: 700, lineHeight: 1.1, letterSpacing: 0 }}>{headerTitle}</div>}\n {showSubtitle && <div style={{ fontSize: isAdSlotSurface ? '10px' : '12px', color: expandedMutedText, marginTop: '2px' }}>{assistantSubtitle}</div>}\n </div>\n )}\n </div>\n {!isAdSlotSurface && (\n <button\n type=\"button\"\n onClick={() => setIsExpanded(false)}\n aria-label=\"Minimize assistant\"\n style={{\n width: 36,\n height: 36,\n borderRadius: '12px',\n border: `1px solid ${expandedBorder}`,\n background: '#ffffff',\n color: expandedMutedText,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <span style={{ fontSize: '18px', lineHeight: 1, fontWeight: 700, transform: 'translateY(-1px)' }}>-</span>\n </button>\n )}\n </div>\n )}\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: isAdSlotSurface ? '6px' : '16px',\n minHeight: 0,\n flex: isAdSlotSurface ? '1 1 0' : undefined,\n overflow: isAdSlotSurface ? 'hidden' : undefined,\n padding: isAdSlotSurface ? '8px 10px 6px' : isExpanded ? '18px' : '14px',\n background: isExpanded ? expandedShellBackground : withAlpha('#ffffff', 0.16),\n height: isAdSlotSurface ? undefined : isExpanded ? publisherPanelHeight : 'auto',\n }}\n >\n {renderDelegationBanner('default')}\n {isExpanded && renderPublisherMessages()}\n {isAdSlotSurface && !isExpanded && <div aria-hidden=\"true\" style={{ flex: '1 1 auto', minHeight: 0 }} />}\n {isAdSlotSurface && !isExpanded && showWelcomeMessage && messages.length === 0 && (\n <div\n style={{\n color: brandText,\n fontSize: '15px',\n lineHeight: 1.3,\n fontWeight: 700,\n letterSpacing: 0,\n padding: '2px 2px 0',\n textAlign: 'center',\n }}\n >\n {welcomeMessage}\n </div>\n )}\n {renderPublisherSuggestions()}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n borderRadius: isAdSlotSurface ? '12px' : '16px',\n background: expandedComposerBackground,\n padding: isAdSlotSurface ? '6px 6px 6px 10px' : '8px 8px 8px 14px',\n boxShadow: isExpanded ? expandedComposerShadow : `0 8px 22px ${purpleShadowSoft}`,\n border: `1px solid ${isExpanded ? expandedBorder : purpleBorderSoft}`,\n flexShrink: 0,\n }}\n >\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyPress={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n if (isLoading) return;\n currentSponsoredSuggestionRef.current = null;\n currentMessageIsSponsored.current = false;\n setIsExpanded(true);\n if (layout === 'floating') handleOpenChange(true);\n handleSendMessage(inputValue);\n }\n }}\n placeholder={placeholder}\n style={{\n flex: 1,\n border: 'none',\n outline: 'none',\n borderRadius: '12px',\n padding: isAdSlotSurface ? '8px 2px' : '10px 4px',\n color: brandText,\n fontSize: isAdSlotSurface ? '13px' : '15px',\n background: 'transparent',\n }}\n />\n <button\n type=\"button\"\n onClick={() => {\n if (isLoading) {\n handleStopGeneration();\n return;\n }\n currentSponsoredSuggestionRef.current = null;\n currentMessageIsSponsored.current = false;\n setIsExpanded(true);\n if (layout === 'floating') handleOpenChange(true);\n handleSendMessage(inputValue);\n }}\n disabled={!isLoading && !inputValue.trim()}\n style={{\n border: 'none',\n borderRadius: '12px',\n background: isLoading ? '#dc2626' : publisherAccent,\n color: '#ffffff',\n minWidth: isAdSlotSurface ? '40px' : '48px',\n height: isAdSlotSurface ? '36px' : '44px',\n padding: isAdSlotSurface ? '0 10px' : '0 16px',\n fontSize: isAdSlotSurface ? '12px' : '14px',\n fontWeight: 700,\n cursor: !isLoading && !inputValue.trim() ? 'default' : 'pointer',\n opacity: !isLoading && !inputValue.trim() ? 0.6 : 1,\n boxShadow: `0 10px 20px ${isLoading ? 'rgba(220, 38, 38, 0.18)' : withAlpha(brandPrimary, 0.18)}`,\n }}\n >\n {isLoading ? 'Stop' : 'Send'}\n </button>\n </div>\n {isExpanded && renderExpandedBranding('default')}\n {!isExpanded && (\n <div style={{ textAlign: 'center', paddingTop: '2px' }}>\n <div style={{ color: publisherMeta, fontSize: isAdSlotSurface ? '9.5px' : fontSizes.xs, fontWeight: 600 }}>\n Powered by{' '}\n <a\n href=\"https://useadmesh.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit', textDecoration: 'none', fontWeight: 700 }}\n >\n AdMesh\n </a>\n </div>\n <div style={{ color: publisherMeta, fontSize: isAdSlotSurface ? '9px' : fontSizes.xs, lineHeight: isAdSlotSurface ? 1.25 : 1.5 }}>{genericDisclaimer}</div>\n </div>\n )}\n </div>\n </div>\n );\n\n if (layout === 'inline') {\n if (isAdSlotSurface) {\n return (\n <div\n ref={adSlotRootRef}\n className=\"admesh-component\"\n data-admesh-theme={themeMode}\n data-admesh-surface=\"ad-slot\"\n data-admesh-ad-slot-expanded={shouldExpandAdSlot ? 'true' : 'false'}\n style={{\n width: adSlotWidthCss,\n height: adSlotHeightCss,\n maxWidth: adSlotWidthCss,\n maxHeight: adSlotHeightCss,\n position: 'relative',\n overflow: 'hidden',\n }}\n >\n {teaser}\n </div>\n );\n }\n\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode} style={{ width: '100%', position: 'relative' }}>\n {teaser}\n {isExpanded && (\n <div\n onClick={() => setIsExpanded(false)}\n style={{\n position: 'fixed',\n inset: 0,\n background: expandedOverlay,\n backdropFilter: 'blur(6px)',\n zIndex: 2147483000,\n }}\n />\n )}\n {isExpanded && (\n <div\n style={{\n position: 'fixed',\n left: '50%',\n bottom: '12px',\n transform: 'translateX(-50%)',\n width: 'min(960px, calc(100vw - 24px))',\n zIndex: 2147483001,\n }}\n >\n {teaser}\n </div>\n )}\n </div>\n );\n }\n\n if (!isOpen) {\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <button\n type=\"button\"\n onClick={handleOpenClick}\n style={{\n position: 'fixed',\n ...positionStyle,\n zIndex: 2147483000,\n border: 'none',\n borderRadius: 999,\n background: theme.primaryColor,\n color: '#ffffff',\n padding: '14px 18px',\n boxShadow: '0 18px 40px rgba(15, 23, 42, 0.18)',\n cursor: 'pointer',\n }}\n >\n {triggerLabel}\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n {isExpanded && (\n <div\n onClick={() => setIsExpanded(false)}\n style={{\n position: 'fixed',\n inset: 0,\n background: expandedOverlay,\n backdropFilter: 'blur(6px)',\n zIndex: 2147483000,\n }}\n />\n )}\n <div\n style={{\n position: 'fixed',\n ...(isExpanded ? { left: '50%', bottom: '12px', transform: 'translateX(-50%)' } : positionStyle),\n zIndex: 2147483001,\n }}\n >\n {teaser}\n </div>\n </div>\n );\n }\n\n // Conditional rendering: only show if we have suggestions\n if (orderedSuggestions.length === 0 && !shouldShowSuggestionSkeletons) {\n console.log('[AdMeshIntentAssistant] No suggestions available - not rendering');\n return null;\n }\n\n if (layout === 'inline') {\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <div\n className={`overflow-hidden rounded-[2rem] ${className || ''}`}\n style={{\n width: toCssSize(panelWidth) ?? '100%',\n backgroundColor: '#eef2ff',\n fontSize: fontSizes.base,\n ...style,\n }}\n >\n <div\n className=\"space-y-4 rounded-[1.75rem] p-4\"\n style={{ backgroundColor: 'rgba(255, 255, 255, 0.35)' }}\n >\n {shouldShowSuggestionSkeletons ? (\n renderSuggestionSkeletons('legacy')\n ) : orderedSuggestions.length > 0 && (\n <div className=\"flex flex-col gap-3\">\n {orderedSuggestions.slice(0, maxSuggestions).map((suggestion, index) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => handleSuggestionClick(suggestion)}\n className=\"rounded-full px-5 py-4 text-left shadow-sm transition-transform duration-200 hover:scale-[1.01] active:scale-[0.99]\"\n style={{\n width: index === 0 ? '100%' : index === 1 ? '82%' : '68%',\n backgroundColor: theme.surfaceColor || '#ffffff',\n color: theme.textColor || '#1e293b',\n border: `1px solid ${theme.borderColor || '#e2e8f0'}`,\n fontSize: fontSizes.sm,\n }}\n >\n <span className=\"leading-tight\">{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <sup\n className=\"ml-1 rounded-full px-1.5 py-0.5\"\n style={{\n backgroundColor: theme.backgroundColor || '#ffffff',\n color: theme.textSecondaryColor || '#64748b',\n fontSize: '9px',\n lineHeight: 1,\n }}\n >\n Ad\n </sup>\n )}\n </button>\n ))}\n </div>\n )}\n\n {messages.length > 0 && (\n <div\n ref={messagesScrollRef}\n className=\"max-h-[280px] space-y-3 overflow-y-auto rounded-[1.5rem] bg-white/80 p-4\"\n style={{ color: theme.textColor }}\n >\n {messages.map((message) => {\n const isActiveSubmittedMessage =\n message.role === 'user' &&\n message.id === activeSubmittedMessageIdRef.current;\n\n return (\n <div\n key={message.id}\n ref={isActiveSubmittedMessage ? activeSubmittedMessageRef : undefined}\n className={message.role === 'user' ? 'text-right' : 'text-left'}\n >\n <div\n className=\"inline-block max-w-[85%] rounded-2xl px-4 py-3\"\n style={{\n backgroundColor: message.role === 'user' ? theme.primaryColor : '#ffffff',\n color: message.role === 'user' ? '#ffffff' : theme.textColor,\n fontSize: fontSizes.sm,\n }}\n >\n {message.role === 'assistant' ? (\n message.content.trim() ? (\n <>\n <CustomMarkdownRenderer content={message.content} theme={theme} fontSize={fontSizes.sm} />\n {renderAnswerFooter(message, {\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n })}\n </>\n ) : isLoading && message.id === activeAssistantMessageIdRef.current ? (\n renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })\n ) : null\n ) : (\n <p style={{ margin: 0, lineHeight: '1.4' }}>{message.content}</p>\n )}\n </div>\n </div>\n );\n })}\n\n {isLoading && !messages.some(\n (message) =>\n message.role === 'assistant' &&\n message.id === activeAssistantMessageIdRef.current &&\n !message.content.trim(),\n ) && (\n <div className=\"text-sm\" style={{ color: theme.textSecondaryColor }}>\n {renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })}\n </div>\n )}\n\n {error && (\n <div className=\"text-sm\" style={{ color: theme.textSecondaryColor }}>\n Connection issue. Please try again.\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n )}\n\n <div className=\"rounded-[1.5rem] bg-white p-3 shadow-sm\">\n <div className=\"flex items-center gap-3\">\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyPress={(e) => {\n if (e.key !== 'Enter') return;\n if (isLoading) {\n e.preventDefault();\n return;\n }\n handleSendMessage(inputValue);\n }}\n placeholder={placeholder}\n className=\"min-w-0 flex-1 rounded-full px-4 py-3 focus:outline-none\"\n style={{\n backgroundColor: theme.backgroundColor || '#ffffff',\n color: theme.textColor,\n fontSize: fontSizes.sm,\n }}\n />\n <button\n onClick={() => {\n if (isLoading) {\n handleStopGeneration();\n return;\n }\n handleSendMessage(inputValue);\n }}\n disabled={!isLoading && !inputValue.trim()}\n className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-50\"\n style={{\n backgroundColor: isLoading ? '#dc2626' : theme.primaryColor,\n color: '#ffffff',\n }}\n >\n {isLoading ? <XIcon size={18} /> : <SendIcon size={18} />}\n </button>\n </div>\n </div>\n\n <div className=\"space-y-2 text-center\">\n <p style={{ color: theme.textSecondaryColor, fontSize: fontSizes.xs, fontWeight: 600 }}>\n Powered by{' '}\n <a\n href=\"https://useadmesh.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit', textDecoration: 'none', fontWeight: 700 }}\n >\n AdMesh\n </a>\n </p>\n <p style={{ color: theme.textSecondaryColor, fontSize: fontSizes.xs, lineHeight: 1.5 }}>\n {genericDisclaimer}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n if (!isOpen) {\n // Floating button when closed\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <button\n onClick={handleOpenClick}\n className=\"flex items-center gap-2 px-4 py-3 rounded-full shadow-lg transition-all duration-200 hover:scale-105 active:scale-95\"\n style={{\n position: 'fixed',\n ...positionStyle,\n backgroundColor: theme.primaryColor,\n color: '#ffffff',\n zIndex: 9999,\n fontSize: fontSizes.base,\n ...style,\n }}\n >\n {/* {triggerIcon ?? <BotIcon size={20} />} */}\n <span className=\"font-medium\">{triggerLabel}</span>\n </button>\n </div>\n );\n }\n\n // Main assistant interface when open\n return (\n <div className=\"admesh-component\" data-admesh-theme={themeMode}>\n <div\n className={`flex flex-col overflow-hidden ${className || ''}`}\n style={{\n position: 'fixed',\n display: 'flex',\n flexDirection: 'column',\n ...(isExpanded ? {\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: 'min(1040px, calc(100vw - 40px))',\n height: 'min(84vh, 820px)',\n maxWidth: '1040px',\n maxHeight: '820px',\n } : {\n ...positionStyle,\n width: toCssSize(panelWidth) ?? sizeStyle.width,\n height: toCssSize(panelHeight) ?? sizeStyle.height,\n }),\n backgroundColor: isExpanded ? expandedShellBackground : theme.backgroundColor,\n zIndex: 9999,\n fontSize: fontSizes.base,\n borderRadius: isExpanded ? '20px' : '16px',\n border: isExpanded ? `1px solid ${expandedBorderStrong}` : '1px solid transparent',\n boxShadow: isExpanded ? expandedShadow : '0 20px 40px rgba(15, 23, 42, 0.12)',\n ...style,\n }}\n >\n {/* Header */}\n <div\n className=\"sticky top-0 z-10 flex items-center justify-between p-4 border-b\"\n style={{ \n position: 'sticky',\n top: 0,\n zIndex: 10,\n borderColor: isExpanded ? expandedBorder : 'transparent',\n background: isExpanded ? expandedHeaderBackground : theme.backgroundColor,\n padding: isExpanded ? '18px 20px' : '16px',\n }}\n >\n <div className=\"flex items-center gap-3\">\n <div\n style={{\n width: isExpanded ? 40 : 32,\n height: isExpanded ? 40 : 32,\n borderRadius: isExpanded ? '14px' : '10px',\n background: withAlpha(brandPrimary, 0.08),\n color: publisherAccent,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: isExpanded ? '15px' : '13px',\n fontWeight: 700,\n flexShrink: 0,\n overflow: 'hidden',\n }}\n >\n {headerLogoUrl ? (\n <img src={headerLogoUrl} alt={`${headerTitle || 'Assistant'} logo`} style={{ width: '100%', height: '100%', objectFit: 'contain', background: '#ffffff', padding: 4 }} />\n ) : (\n (headerTitle || 'AA').slice(0, 2).toUpperCase()\n )}\n </div>\n {(showHeaderTitle || (showSubtitle && isExpanded)) && (\n <div>\n {showHeaderTitle && (\n <div\n className=\"font-medium\"\n style={{ color: theme.textColor, fontSize: isExpanded ? '20px' : fontSizes.base, fontWeight: 700, letterSpacing: isExpanded ? '-0.02em' : 0 }}\n >\n {headerTitle}\n </div>\n )}\n {showSubtitle && isExpanded && (\n <div style={{ color: expandedMutedText, fontSize: '12px', marginTop: '2px' }}>\n {assistantSubtitle}\n </div>\n )}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n {!isAdSlotSurface && (\n <button\n onClick={handleToggleExpand}\n className=\"transition-colors\"\n title={isExpanded ? \"Minimize\" : \"Expand\"}\n style={{\n width: isExpanded ? 36 : 28,\n height: isExpanded ? 36 : 28,\n borderRadius: isExpanded ? '12px' : '10px',\n border: `1px solid ${isExpanded ? expandedBorder : 'transparent'}`,\n background: isExpanded ? '#ffffff' : 'transparent',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {isExpanded ? (\n <Minimize2 size={16} style={{ color: theme.textSecondaryColor }} />\n ) : (\n <Maximize2 size={16} style={{ color: theme.textSecondaryColor }} />\n )}\n </button>\n )}\n <button\n onClick={handleCloseClick}\n className=\"transition-colors\"\n style={{\n width: isExpanded ? 36 : 28,\n height: isExpanded ? 36 : 28,\n borderRadius: isExpanded ? '12px' : '10px',\n border: `1px solid ${isExpanded ? expandedBorder : 'transparent'}`,\n background: isExpanded ? '#ffffff' : 'transparent',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <XIcon size={16} style={{ color: theme.textSecondaryColor }} />\n </button>\n </div>\n </div>\n\n {/* Messages */}\n <div\n ref={messagesScrollRef}\n className=\"flex-1 min-h-0 overflow-y-auto p-4\"\n style={{\n flex: '1 1 0%',\n minHeight: 0,\n overflowY: 'auto',\n padding: isExpanded ? '20px' : '16px',\n }}\n >\n {renderDelegationBanner('legacy')}\n {showWelcomeMessage && messages.length === 0 && (\n <div className=\"mb-3\">\n <div\n className=\"inline-block p-2 rounded-lg\"\n \n >\n <p style={{ color: theme.textColor, margin: 0, fontSize: fontSizes.sm }}>{welcomeMessage}</p>\n </div>\n </div>\n )}\n\n {messages.map((message) => {\n const isActiveSubmittedMessage =\n message.role === 'user' &&\n message.id === activeSubmittedMessageIdRef.current;\n\n return (\n <div\n key={message.id}\n ref={isActiveSubmittedMessage ? activeSubmittedMessageRef : undefined}\n className=\"mb-3\"\n >\n <div\n className={message.role === 'user' ? 'inline-block max-w-[85%] ml-auto' : 'max-w-[92%]'}\n style={{\n backgroundColor: message.role === 'user' ? expandedUserBubble : 'transparent',\n color: message.role === 'user' \n ? '#ffffff' \n : theme.textColor,\n border: 'none',\n borderRadius: message.role === 'user' ? (isExpanded ? '14px' : '12px') : 0,\n padding: message.role === 'user' ? (isExpanded ? '12px 14px' : undefined) : '2px 6px 2px 2px',\n boxShadow: 'none',\n }}\n >\n {message.role === 'assistant' ? (\n message.content.trim() ? (\n <>\n <div style={{ fontSize: `calc(${fontSizes.sm} * 1.3)`, lineHeight: 1.65 }}>\n <CustomMarkdownRenderer \n content={message.content}\n theme={theme}\n fontSize={`calc(${fontSizes.sm} * 1.3)`}\n />\n </div>\n {renderAnswerFooter(message, {\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n })}\n </>\n ) : isLoading && message.id === activeAssistantMessageIdRef.current ? (\n renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })\n ) : null\n ) : (\n <p style={{ margin: 0, fontSize: fontSizes.sm, lineHeight: '1.4' }}>{message.content}</p>\n )}\n </div>\n \n {/* Add recommendations after assistant messages */}\n {message.role === 'assistant' && !sponsoredClickedMessages.has(message.id) && (\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(error) => {\n console.error(`[AdMeshIntentAssistant] Recommendations error:`, error);\n }}\n />\n )}\n \n {/* Display sponsored recommendation after assistant content if available */}\n {message.role === 'assistant' && sponsoredClickedMessages.has(message.id) && message.initialRecommendation && !isLoading && (\n <div className=\"mb-4\">\n <div className=\"text-xs text-gray-500 mb-2 font-semibold\">Sponsored Recommendation</div>\n <AdMeshRecommendations\n messageId={message.id}\n query={message.userQuery}\n initialRecommendation={message.initialRecommendation}\n onFollowupDetected={upsertSponsoredFollowupSuggestion}\n onRecommendationsShown={(messageId, recommendation) => {\n handleRecommendationShown(messageId, recommendation, message.userQuery);\n }}\n onError={(error) => {\n console.error(`[AdMeshIntentAssistant] Recommendations error:`, error);\n }}\n />\n </div>\n )}\n </div>\n );\n })}\n\n {isLoading && !messages.some(\n (message) =>\n message.role === 'assistant' &&\n message.id === activeAssistantMessageIdRef.current &&\n !message.content.trim(),\n ) && (\n <div className=\"mb-3\">\n <div\n className=\"inline-block p-2 rounded-lg\"\n style={{ backgroundColor: 'transparent' }}\n >\n {renderGeneratingIndicator({\n compact: true,\n accentColor: theme.primaryColor,\n metaColor: theme.textSecondaryColor,\n includeSteps: false,\n })}\n </div>\n </div>\n )}\n\n {error && (\n <div className=\"mb-3\">\n <div\n className=\"inline-block p-2 rounded-lg border\"\n style={{ \n backgroundColor: 'transparent',\n borderColor: 'transparent',\n color: theme.textSecondaryColor\n }}\n >\n <div className=\"flex items-center gap-2\">\n <span style={{ fontSize: fontSizes.xs }}>⚠️</span>\n <span style={{ fontSize: fontSizes.sm }}>Connection issue. Please try again.</span>\n </div>\n </div>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n \n\n {/* Suggestions */}\n {messages.length === 0 && shouldShowSuggestionSkeletons && (\n <div className=\"px-4 pb-2\">\n {renderSuggestionSkeletons('legacy')}\n </div>\n )}\n\n {orderedSuggestions.length > 0 && messages.length === 0 && !shouldShowSuggestionSkeletons && (\n <div className=\"px-4 pb-2\">\n <div className=\"flex flex-col gap-2\">\n {orderedSuggestions.slice(0, maxSuggestions).map((suggestion) => (\n <button\n key={suggestion.id}\n ref={setSuggestionButtonRef(suggestion.id)}\n onClick={() => handleSuggestionClick(suggestion)}\n className=\"relative flex w-full items-center text-left transition-all duration-200\"\n style={{\n backgroundColor: theme.surfaceColor || '#f8fafc',\n color: theme.textColor || '#1e293b',\n border: `1px solid ${theme.borderColor || '#e2e8f0'}`,\n fontSize: fontSizes.sm,\n padding: '10px 12px',\n borderRadius: '999px',\n fontWeight: 500,\n }}\n >\n <span className=\"leading-tight\">{suggestion.text}</span>\n {adsEnabled && suggestion.is_sponsored && (\n <sup\n className=\"absolute right-1 top-1 rounded-full px-1.5 py-0.5 tracking-wide\"\n style={{\n fontSize: '9px',\n lineHeight: 1,\n backgroundColor: theme.backgroundColor || '#ffffff',\n color: theme.textSecondaryColor || '#64748b'\n }}\n >\n Ad\n </sup>\n )}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {/* Intent Analysis Error */}\n {intentError && !isAnalyzingIntent && safeSuggestions.length === 0 && (\n <div className=\"px-4 pb-2\">\n <div className=\"flex flex-col gap-2\">\n <div className=\"p-3 rounded-lg border\" style={{ \n backgroundColor: theme.surfaceColor,\n borderColor: theme.borderColor,\n color: theme.textSecondaryColor\n }}>\n <div className=\"flex items-center justify-between mb-2\">\n <span style={{ fontSize: fontSizes.sm }}>Intent analysis failed</span>\n <button\n onClick={retryIntentAnalysis}\n className=\"text-xs px-2 py-1 rounded\"\n style={{ \n backgroundColor: theme.primaryColor,\n color: '#ffffff'\n }}\n >\n Retry\n </button>\n </div>\n <span style={{ fontSize: fontSizes.xs }}>{intentError}</span>\n </div>\n </div>\n </div>\n )}\n\n {/* Input */}\n <div className=\"p-3 border-t\" style={{ borderColor: isExpanded ? expandedBorder : 'transparent', padding: isExpanded ? '18px 20px' : undefined, background: isExpanded ? expandedHeaderBackground : undefined }}>\n <div className=\"flex gap-2\" style={{ alignItems: 'center', border: `1px solid ${expandedBorder}`, borderRadius: isExpanded ? '16px' : '12px', background: expandedComposerBackground, boxShadow: isExpanded ? expandedComposerShadow : 'none', padding: isExpanded ? '8px 8px 8px 14px' : undefined }}>\n <input\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyPress={(e) => {\n if (e.key !== 'Enter') return;\n if (isLoading) {\n e.preventDefault();\n return;\n }\n handleSendMessage(inputValue);\n }}\n placeholder={placeholder}\n className=\"flex-1 px-3 py-2 rounded-lg border focus:outline-none focus:ring-2\"\n style={{\n backgroundColor: 'transparent',\n borderColor: 'transparent',\n color: theme.textColor,\n fontSize: isExpanded ? '15px' : fontSizes.sm,\n '--tw-ring-color': theme.primaryColor,\n } as CSSProperties}\n />\n <button\n onClick={() => {\n if (isLoading) {\n handleStopGeneration();\n return;\n }\n handleSendMessage(inputValue);\n }}\n disabled={!isLoading && !inputValue.trim()}\n className=\"transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n style={{\n backgroundColor: isLoading ? '#dc2626' : theme.primaryColor,\n color: '#ffffff',\n borderRadius: isExpanded ? '12px' : '10px',\n width: isExpanded ? '46px' : undefined,\n height: isExpanded ? '46px' : undefined,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n boxShadow: isExpanded ? `0 10px 20px ${withAlpha(brandPrimary, 0.18)}` : 'none',\n }}\n >\n {isLoading ? <XIcon size={14} /> : <SendIcon size={14} />}\n </button>\n </div>\n {renderExpandedBranding('legacy')}\n </div>\n </div>\n </div>\n );\n};\n\nexport default AdMeshIntentAssistant;\n","/**\n * Streaming Events Utilities\n * \n * Custom event system for communicating LLM streaming lifecycle events\n * between the chat frontend and AdMesh WeaveAdFormatContainer.\n * \n * This allows WeaveAdFormatContainer to trigger final link detection\n * when streaming completes, rather than using arbitrary timeouts.\n */\n\nimport { logger } from './logger';\n\nexport const STREAMING_START_EVENT = 'admesh:streamingStart';\nexport const STREAMING_COMPLETE_EVENT = 'admesh:streamingComplete';\n\nexport interface StreamingStartEventDetail {\n messageId: string;\n sessionId: string;\n timestamp: number;\n}\n\nexport interface StreamingCompleteEventDetail {\n messageId: string;\n sessionId: string;\n timestamp: number;\n metadata?: {\n hasRecommendations?: boolean;\n recommendationCount?: number;\n };\n}\n\n/**\n * Dispatch a streaming start event\n * \n * Call this when the backend starts streaming the LLM response.\n * This signals to WeaveAdFormatContainer that content is being received.\n * \n * @param messageId - Unique identifier for the message\n * @param sessionId - Session/chat identifier\n */\nexport function dispatchStreamingStartEvent(\n messageId: string,\n sessionId: string\n): void {\n const detail: StreamingStartEventDetail = {\n messageId,\n sessionId,\n timestamp: Date.now(),\n };\n\n const event = new CustomEvent(STREAMING_START_EVENT, { detail });\n window.dispatchEvent(event);\n\n logger.log('[StreamingEvents] 📢 Dispatched streamingStart event', {\n messageId,\n sessionId\n });\n}\n\n/**\n * Dispatch a streaming complete event\n * \n * Call this when the backend finishes streaming the LLM response.\n * This triggers WeaveAdFormatContainer to perform final link detection.\n * \n * @param messageId - Unique identifier for the message\n * @param sessionId - Session/chat identifier\n * @param metadata - Optional metadata about recommendations\n */\nexport function dispatchStreamingCompleteEvent(\n messageId: string,\n sessionId: string,\n metadata?: {\n hasRecommendations?: boolean;\n recommendationCount?: number;\n }\n): void {\n const detail: StreamingCompleteEventDetail = {\n messageId,\n sessionId,\n timestamp: Date.now(),\n metadata,\n };\n\n const event = new CustomEvent(STREAMING_COMPLETE_EVENT, { detail });\n window.dispatchEvent(event);\n\n logger.log('[StreamingEvents] 📢 Dispatched streamingComplete event', {\n messageId,\n sessionId,\n metadata\n });\n}\n\n/**\n * Listen for streaming start events\n * \n * @param messageId - Filter events by this messageId\n * @param sessionId - Filter events by this sessionId\n * @param callback - Called when matching event is received\n * @returns Cleanup function to remove the event listener\n */\nexport function onStreamingStart(\n messageId: string,\n sessionId: string,\n callback: (detail: StreamingStartEventDetail) => void\n): () => void {\n const handler = (event: Event) => {\n const customEvent = event as CustomEvent<StreamingStartEventDetail>;\n \n // Only trigger callback if this is the message we're waiting for\n if (\n customEvent.detail.messageId === messageId &&\n customEvent.detail.sessionId === sessionId\n ) {\n logger.log('[StreamingEvents] 📨 Received streamingStart event');\n callback(customEvent.detail);\n }\n };\n\n window.addEventListener(STREAMING_START_EVENT, handler);\n\n // Return cleanup function\n return () => {\n window.removeEventListener(STREAMING_START_EVENT, handler);\n };\n}\n\n/**\n * Listen for streaming complete events\n * \n * @param messageId - Filter events by this messageId\n * @param sessionId - Filter events by this sessionId\n * @param callback - Called when matching event is received\n * @returns Cleanup function to remove the event listener\n */\nexport function onStreamingComplete(\n messageId: string,\n sessionId: string,\n callback: (detail: StreamingCompleteEventDetail) => void\n): () => void {\n logger.log('[StreamingEvents] 👂 Setting up streamingComplete listener', {\n expectedMessageId: messageId,\n expectedSessionId: sessionId\n });\n\n const handler = (event: Event) => {\n const customEvent = event as CustomEvent<StreamingCompleteEventDetail>;\n \n logger.log('[StreamingEvents] 📨 Received streamingComplete event (checking match)', {\n receivedMessageId: customEvent.detail.messageId,\n receivedSessionId: customEvent.detail.sessionId,\n expectedMessageId: messageId,\n expectedSessionId: sessionId,\n messageIdMatch: customEvent.detail.messageId === messageId,\n sessionIdMatch: customEvent.detail.sessionId === sessionId\n });\n \n // Only trigger callback if this is the message we're waiting for\n if (\n customEvent.detail.messageId === messageId &&\n customEvent.detail.sessionId === sessionId\n ) {\n logger.log('[StreamingEvents] ✅ Event matched! Calling callback');\n callback(customEvent.detail);\n } else {\n logger.log('[StreamingEvents] ⚠️ Event did not match - ignoring');\n }\n };\n\n window.addEventListener(STREAMING_COMPLETE_EVENT, handler);\n\n // Return cleanup function\n return () => {\n logger.log('[StreamingEvents] 🧹 Removing streamingComplete listener');\n window.removeEventListener(STREAMING_COMPLETE_EVENT, handler);\n };\n}\n","import { logger } from './logger';\n\ninterface InlineExposureTrackerState {\n observer: IntersectionObserver;\n timeoutId: ReturnType<typeof setTimeout> | null;\n viewableStart: number | null;\n}\n\nexport interface InlineExposureTrackingParams {\n exposureUrl?: string;\n recommendationId?: string;\n linkElement?: HTMLElement | null;\n sessionId?: string;\n logPrefix?: string;\n}\n\nexport interface InlineExposureTracker {\n startTracking: (params: InlineExposureTrackingParams) => void;\n cleanup: () => void;\n}\n\n/**\n * Creates an inline exposure tracker that fires AdMesh exposure pixels when\n * detected links meet the MRC viewability threshold (50% visible for 1 second).\n */\nexport const createInlineExposureTracker = (): InlineExposureTracker => {\n const firedKeys = new Set<string>();\n const activeTrackers = new Map<string, InlineExposureTrackerState>();\n\n const cleanupTracker = (key: string) => {\n const tracker = activeTrackers.get(key);\n if (!tracker) {\n return;\n }\n tracker.observer.disconnect();\n if (tracker.timeoutId) {\n clearTimeout(tracker.timeoutId);\n }\n activeTrackers.delete(key);\n };\n\n const startTracking = ({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId,\n logPrefix = '[AdMesh Exposure]'\n }: InlineExposureTrackingParams) => {\n if (typeof window === 'undefined') {\n return;\n }\n\n if (!exposureUrl || !linkElement) {\n if (logPrefix) {\n logger.warn(`${logPrefix} ⚠️ Missing exposure tracking data`);\n }\n return;\n }\n\n const dedupeKey = `${sessionId || 'anonymous'}::${recommendationId || exposureUrl}`;\n\n if (firedKeys.has(dedupeKey) || activeTrackers.has(dedupeKey)) {\n return;\n }\n\n const trackerState: InlineExposureTrackerState = {\n observer: undefined as unknown as IntersectionObserver,\n timeoutId: null,\n viewableStart: null\n };\n\n const fireExposurePixel = () => {\n cleanupTracker(dedupeKey);\n firedKeys.add(dedupeKey);\n\n fetch(exposureUrl, { method: 'GET', keepalive: true })\n .then(() => {\n if (logPrefix) {\n logger.log(`${logPrefix} ✅ Exposure pixel fired`);\n }\n })\n .catch(() => {\n if (logPrefix) {\n logger.warn(`${logPrefix} ⚠️ Failed to fire exposure pixel`);\n }\n firedKeys.delete(dedupeKey);\n });\n };\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const visibility = entry.intersectionRatio;\n\n if (visibility >= 0.5) {\n if (trackerState.viewableStart === null) {\n trackerState.viewableStart = performance.now();\n trackerState.timeoutId = setTimeout(fireExposurePixel, 1000);\n }\n } else {\n trackerState.viewableStart = null;\n if (trackerState.timeoutId) {\n clearTimeout(trackerState.timeoutId);\n trackerState.timeoutId = null;\n }\n }\n });\n },\n {\n threshold: [0, 0.25, 0.5, 0.75, 1],\n rootMargin: '0px'\n }\n );\n\n trackerState.observer = observer;\n observer.observe(linkElement as Element);\n activeTrackers.set(dedupeKey, trackerState);\n };\n\n const cleanup = () => {\n Array.from(activeTrackers.keys()).forEach(cleanupTracker);\n };\n\n return {\n startTracking,\n cleanup\n };\n};\n","'use client';\n\nimport React, { useRef, useState, useEffect, useCallback } from 'react';\nimport { useAdMesh } from '../hooks/useAdMesh';\nimport { WeaveFallbackRecommendations } from './WeaveFallbackRecommendations';\nimport { onStreamingComplete } from '../utils/streamingEvents';\nimport {\n createInlineExposureTracker,\n type InlineExposureTrackingParams\n} from '../utils/inlineExposureTracker';\nimport { WeaveResponseProcessor } from '../sdk/WeaveResponseProcessor';\nimport { logger } from '../utils/logger';\nimport type {\n PlatformResponse,\n} from '../types/index';\n\n/**\n * FinalLinkDetectionCheck - Event-driven link detection component\n *\n * This component waits for the 'admesh:streamingComplete' event from ChatWindow\n * before performing final link detection. This eliminates race conditions where\n * timeout-based detection would trigger before streaming completes.\n */\ninterface FinalLinkDetectionCheckProps {\n containerId: string;\n messageId: string;\n sessionId: string;\n sdk: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n query?: string;\n recommendations?: any[]; // eslint-disable-line @typescript-eslint/no-explicit-any\n onLinksFound: (count: number) => void;\n onNoLinksFound: () => void;\n children: React.ReactNode;\n}\n\nconst FinalLinkDetectionCheck: React.FC<FinalLinkDetectionCheckProps> = ({\n containerId,\n messageId,\n sessionId,\n sdk,\n query,\n recommendations = [],\n onLinksFound,\n onNoLinksFound,\n children\n}) => {\n const [checkComplete, setCheckComplete] = useState(false);\n const [waitingForStreamEnd, setWaitingForStreamEnd] = useState(true);\n const [linksFound, setLinksFound] = useState(false);\n const exposureTrackerRef = useRef(createInlineExposureTracker());\n\n // Use refs to avoid recreating the callback on every render\n const onLinksFoundRef = useRef(onLinksFound);\n const onNoLinksFoundRef = useRef(onNoLinksFound);\n const containerIdRef = useRef(containerId);\n const sdkRef = useRef(sdk);\n const sessionIdRef = useRef(sessionId);\n const queryRef = useRef(query);\n\n // Update refs when values change\n useEffect(() => {\n onLinksFoundRef.current = onLinksFound;\n onNoLinksFoundRef.current = onNoLinksFound;\n containerIdRef.current = containerId;\n sdkRef.current = sdk;\n sessionIdRef.current = sessionId;\n queryRef.current = query;\n }, [onLinksFound, onNoLinksFound, containerId, sdk, sessionId, query]);\n\n useEffect(() => {\n return () => {\n exposureTrackerRef.current.cleanup();\n };\n }, []);\n\n const trackExposurePixel = useCallback(\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) => {\n exposureTrackerRef.current.startTracking({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId: sessionIdRef.current,\n logPrefix: '[FinalLinkDetectionCheck]'\n });\n },\n []\n );\n\n const performFinalCheck = useCallback(() => {\n logger.log('[FinalLinkDetectionCheck] 🔍 Performing final link detection...');\n\n try {\n const container = document.getElementById(containerIdRef.current);\n if (!container) {\n logger.warn('[FinalLinkDetectionCheck] ❌ Container not found');\n setCheckComplete(true);\n onNoLinksFound();\n return;\n }\n\n // Create WeaveResponseProcessor instance\n const weaveProcessor = new WeaveResponseProcessor({\n autoAddLabels: true,\n fireExposurePixels: true\n });\n\n // Use fetched recommendations if available, otherwise fall back to pattern-based detection\n const recsToUse = recommendations.length > 0 ? recommendations : [];\n logger.log(`[FinalLinkDetectionCheck] 📋 Using ${recsToUse.length} recommendations for link detection`);\n \n // Development logging: Log recommendation details used for link detection\n if (recsToUse.length > 0 && process.env.NODE_ENV === 'development') {\n recsToUse.forEach((rec, index) => {\n logger.log(`[FinalLinkDetectionCheck] 📋 Recommendation ${index + 1} (DEV):`, {\n recommendation_id: rec?.recommendation_id,\n click_url:\n rec?.tracking?.click_url ||\n rec?.recommendation?.creative?.landing_page_url,\n format: rec?.recommendation?.format,\n brand_name: rec.render?.creative?.advertiser?.brand_name,\n cta_url: rec.render?.creative?.landing_page_url,\n });\n });\n }\n\n // Scan for AdMesh links one final time\n const detectedLinks = weaveProcessor.scanAndProcessLinks(\n container,\n recsToUse, // Use fetched recommendations for brand URL matching\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) =>\n trackExposurePixel({ exposureUrl, recommendationId, linkElement })\n );\n\n logger.log(`[FinalLinkDetectionCheck] 📊 Final check result: ${detectedLinks.length} links`);\n\n if (detectedLinks.length > 0) {\n // Links found! Cancel fallback\n logger.log('[FinalLinkDetectionCheck] ✅ Links detected - canceling fallback (no API call)');\n setLinksFound(true);\n onLinksFoundRef.current(detectedLinks.length);\n } else {\n // No links found, proceed with fallback\n logger.log(`[FinalLinkDetectionCheck] ⚠️ No links found - rendering fallback (will use ${recsToUse.length} previous recommendation(s) if available)`);\n setLinksFound(false);\n onNoLinksFoundRef.current();\n }\n\n setCheckComplete(true);\n } catch (error) {\n logger.error('[FinalLinkDetectionCheck] ❌ Error during final check');\n setCheckComplete(true);\n onNoLinksFoundRef.current();\n }\n }, [trackExposurePixel, recommendations]);\n\n useEffect(() => {\n logger.log('[FinalLinkDetectionCheck] ⏳ Setting up listener', {\n messageId,\n sessionId,\n recommendationsCount: recommendations.length\n });\n\n let timeoutId: NodeJS.Timeout | null = null;\n let eventReceived = false;\n\n // Listen for the streamingComplete event from ChatWindow\n const cleanup = onStreamingComplete(messageId, sessionId, (detail) => {\n logger.log('[FinalLinkDetectionCheck] 🎯 Received streamingComplete event', {\n messageId: detail.messageId,\n sessionId: detail.sessionId,\n timestamp: detail.timestamp\n });\n eventReceived = true;\n \n // Clear timeout since event was received\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n \n setWaitingForStreamEnd(false);\n\n // Small delay to ensure DOM is fully updated\n setTimeout(() => {\n performFinalCheck();\n }, 100);\n });\n\n // Fallback timeout: If streamingComplete doesn't fire within 5 seconds, trigger check anyway\n // This ensures fallback recommendations display even if event system fails\n timeoutId = setTimeout(() => {\n if (!eventReceived) {\n logger.warn('[FinalLinkDetectionCheck] ⏱️ Timeout: streamingComplete event not received, triggering fallback check anyway');\n setWaitingForStreamEnd(false);\n setTimeout(() => {\n performFinalCheck();\n }, 100);\n }\n }, 5000); // 5 second timeout\n\n return () => {\n logger.log('[FinalLinkDetectionCheck] 🧹 Cleaning up listener');\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n cleanup();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messageId, sessionId]); // performFinalCheck depends on recommendations prop, but recommendations should be stable for a given messageId\n\n // Show loading state while waiting for stream to complete\n if (waitingForStreamEnd) {\n return <></>;\n }\n\n // Show checking state while performing final detection\n if (!checkComplete) {\n return <></>;\n }\n\n // Only render children (fallback) if NO links were found\n if (linksFound) {\n logger.log('[FinalLinkDetectionCheck] 🚫 Links found - NOT rendering fallback');\n return <></>;\n }\n\n logger.log('[FinalLinkDetectionCheck] ✅ No links found - rendering fallback');\n return <>{children}</>;\n};\n\nexport interface WeaveAdFormatContainerProps {\n /** Unique ID for this message container */\n messageId: string;\n\n /** The LLM response content (may contain AdMesh links) */\n children: React.ReactNode;\n\n /** Fallback format if no links detected (default: 'tail') */\n fallbackFormat?: 'product' | 'tail';\n\n /** Optional callback when AdMesh links are detected */\n onLinksDetected?: (count: number) => void;\n\n /** Optional callback when no links are detected (fallback should be rendered) */\n onNoLinksDetected?: () => void;\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /** Optional CSS class for the container */\n className?: string;\n\n /** Optional query text for fallback API calls (used when no links are detected) */\n query?: string;\n\n /** Optional callback to notify parent when fallback state changes */\n onFallbackChange?: (shouldFallback: boolean) => void;\n\n /** Optional callback when weave injection is attempted */\n onWeaveAttempt?: (messageId: string) => void;\n\n /** Optional callback when weave injection outcome is determined */\n onWeaveOutcome?: (messageId: string, success: boolean, reason?: string) => void;\n\n /** Optional container ID for follow-up suggestions */\n followups_container_id?: string;\n\n /** Callback to execute query when follow-up is selected (required for follow-up functionality) */\n onExecuteQuery?: (query: string) => void | Promise<void>;\n\n /** Optional callback when a sponsored followup is detected */\n onFollowupDetected?: (\n followupSuggestion: any, // Will be updated to proper type later\n recommendationId: string,\n ) => void;\n\n /** Signal indicating if the followup container is ready in the DOM */\n isContainerReady?: boolean;\n}\n\n/**\n * WeaveAdFormatContainer - Automatic Weave Ad Format handling component\n *\n * Wraps LLM response content and automatically:\n * - Detects AdMesh links in the content\n * - Fires exposure tracking for detected links\n * - Adds Ad labels to links\n * - Shows \"Why this ad?\" tooltip on hover\n * - Provides context for WeaveFallbackRecommendations component\n *\n * @example\n * ```tsx\n * <WeaveAdFormatContainer\n * messageId={message.id}\n * query={userQuery}\n * onLinksDetected={(count) => console.log(`Found ${count} ads`)}\n * >\n * {llmResponseContent}\n * </WeaveAdFormatContainer>\n * ```\n */\nexport const WeaveAdFormatContainer: React.FC<WeaveAdFormatContainerProps> = ({\n messageId,\n children,\n fallbackFormat = 'tail',\n onLinksDetected,\n onNoLinksDetected,\n onError,\n className,\n query,\n onFallbackChange,\n onWeaveAttempt,\n onWeaveOutcome\n}) => {\n const { sessionId, sdk, language, location, userId, model, messages } = useAdMesh();\n const containerRef = useRef<HTMLDivElement>(null);\n const containerId = `weave-ad-container-${messageId}`;\n const exposureTrackerRef = useRef(createInlineExposureTracker());\n const scannedRef = useRef(false);\n const weaveProcessorRef = useRef<WeaveResponseProcessor | null>(null);\n const [recommendations, setRecommendations] = useState<PlatformResponse[]>([]);\n const recommendationsRef = useRef<PlatformResponse[]>([]);\n\n // Initialize WeaveResponseProcessor once\n useEffect(() => {\n if (!weaveProcessorRef.current) {\n weaveProcessorRef.current = new WeaveResponseProcessor({\n autoAddLabels: true,\n fireExposurePixels: true\n });\n }\n return () => {\n if (weaveProcessorRef.current) {\n weaveProcessorRef.current.stopWatching();\n weaveProcessorRef.current.clearCache();\n }\n };\n }, []);\n\n // Cleanup exposure tracker on unmount\n useEffect(() => {\n return () => {\n exposureTrackerRef.current.cleanup();\n };\n }, []);\n\n // Fetch recommendations from SDK cache if available\n useEffect(() => {\n const fetchRecommendations = async () => {\n if (!sdk || !query?.trim() || !messageId) {\n logger.log('[WeaveAdFormatContainer] ⚠️ Missing SDK, query, or messageId - using pattern-based detection');\n return;\n }\n\n try {\n logger.log('[WeaveAdFormatContainer] 📤 Fetching recommendations from SDK for brand URL matching');\n // Use context values (from AdMeshProvider) for canonical AIP PlatformRequest fields\n const platformResponse = await sdk.fetchPlatformResponse({\n query: query.trim(),\n sessionId: sessionId,\n messageId: messageId,\n language: language,\n location: location,\n userId: userId,\n model: model,\n messages: messages,\n });\n const recs = platformResponse?.status === 'generated' ? [platformResponse] : [];\n setRecommendations(recs);\n recommendationsRef.current = recs; // Update ref to avoid dependency issues\n logger.log('[WeaveAdFormatContainer] 📥 Got platform response:', {\n status: platformResponse?.status,\n recommendationId: platformResponse?.recommendation_id,\n hasRecommendation: !!platformResponse?.recommendation,\n format: platformResponse?.recommendation?.format\n });\n \n if (platformResponse?.recommendation) {\n const creative = platformResponse.recommendation.creative;\n const brandUrl = creative.landing_page_url;\n logger.log('[WeaveAdFormatContainer] 🎯 Found creative in platform response:', {\n brandName: creative.brand_name,\n headline: creative.headline,\n description: creative.description,\n brandUrl: brandUrl\n });\n } else {\n logger.log('[WeaveAdFormatContainer] ⚠️ No recommendation found in platform response');\n }\n } catch (error) {\n logger.warn('[WeaveAdFormatContainer] ⚠️ Failed to fetch recommendations, falling back to pattern-based detection:', error);\n setRecommendations([]);\n }\n };\n\n fetchRecommendations();\n }, [sdk, sessionId, messageId, query]);\n\n // Scan for links immediately when container is ready and on children changes\n useEffect(() => {\n const container = containerRef.current;\n if (!container || !weaveProcessorRef.current) {\n return;\n }\n\n const weaveProcessor = weaveProcessorRef.current;\n\n const trackExposurePixel = ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) => {\n exposureTrackerRef.current.startTracking({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId,\n logPrefix: '[WeaveAdFormatContainer]'\n });\n };\n\n // Scan immediately\n const scanLinks = () => {\n // Emit weave attempt signal\n logger.log('[WeaveAdFormatContainer] 🔍 Weave injection attempt started');\n onWeaveAttempt?.(messageId);\n\n // Use fetched recommendations if available, otherwise fall back to pattern-based detection\n // Use ref to avoid triggering re-runs when recommendations change\n const recsToUse = recommendationsRef.current.length > 0 ? recommendationsRef.current : [];\n logger.log(`[WeaveAdFormatContainer] 📋 Using ${recsToUse.length} recommendations for link detection`);\n\n try {\n const detectedLinks = weaveProcessor.scanAndProcessLinks(\n container,\n recsToUse, // Use fetched recommendations for brand URL matching\n trackExposurePixel\n );\n\n if (detectedLinks.length > 0 && !scannedRef.current) {\n scannedRef.current = true;\n logger.log(`[WeaveAdFormatContainer] ✅ Weave injection succeeded: ${detectedLinks.length} links detected`);\n onWeaveOutcome?.(messageId, true, `Found ${detectedLinks.length} links`);\n onLinksDetected?.(detectedLinks.length);\n onFallbackChange?.(false);\n } else if (!scannedRef.current) {\n // No links found on first scan - will be handled by FinalLinkDetectionCheck\n // But we emit the outcome signal here for immediate feedback\n logger.log('[WeaveAdFormatContainer] ⚠️ Weave injection: no links found on initial scan');\n // Don't emit outcome yet - wait for FinalLinkDetectionCheck to confirm\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`[WeaveAdFormatContainer] ❌ Weave injection failed: ${errorMessage}`);\n onWeaveOutcome?.(messageId, false, errorMessage);\n // Immediately trigger fallback on error\n onNoLinksDetected?.();\n onFallbackChange?.(true);\n }\n };\n\n // Initial scan after a small delay to ensure DOM is ready\n const timeoutId = setTimeout(scanLinks, 100);\n\n // Watch for new links (streaming support)\n // Use ref to avoid triggering re-runs when recommendations change\n weaveProcessor.watchForNewLinks(container, recommendationsRef.current, trackExposurePixel);\n\n return () => {\n clearTimeout(timeoutId);\n weaveProcessor.stopWatching();\n };\n }, [children, sessionId, messageId, onLinksDetected, onFallbackChange, onWeaveAttempt, onWeaveOutcome]); // Removed recommendations from deps to prevent infinite loop\n\n const preferredFormat = recommendations[0]?.recommendation?.format;\n const isWeaveFormat = preferredFormat === 'weave';\n\n // Log when format is weave (for debugging)\n useEffect(() => {\n if (query && isWeaveFormat) {\n logger.log(`[WeaveAdFormatContainer] 🎯 Format is \"weave\" (preferred: ${preferredFormat}) - skipping fallback recommendations`);\n }\n }, [query, isWeaveFormat, preferredFormat]);\n\n return (\n <>\n <div\n ref={containerRef}\n id={containerId}\n className={className}\n data-weave-ad-format=\"true\"\n data-message-id={messageId}\n >\n {children}\n </div>\n\n {/* Event-driven link detection and fallback rendering - only show if format is NOT weave */}\n {query && !isWeaveFormat && (\n <FinalLinkDetectionCheck\n containerId={containerId}\n messageId={messageId}\n sessionId={sessionId}\n sdk={sdk}\n query={query}\n recommendations={recommendations}\n onLinksFound={(count) => {\n logger.log(`[WeaveAdFormatContainer] ✅ Links found (${count}) - no fallback needed`);\n // Emit weave outcome success if not already emitted\n onWeaveOutcome?.(messageId, true, `Found ${count} links in final check`);\n onLinksDetected?.(count);\n onFallbackChange?.(false);\n }}\n onNoLinksFound={() => {\n logger.log(`[WeaveAdFormatContainer] ⚠️ No links found - rendering fallback`);\n logger.log(`[WeaveAdFormatContainer] 📋 Passing ${recommendations.length} recommendation(s) to fallback component`);\n // Emit weave outcome failure\n onWeaveOutcome?.(messageId, false, 'No links detected in final check');\n onNoLinksDetected?.();\n onFallbackChange?.(true);\n }}\n >\n <WeaveFallbackRecommendations\n format={fallbackFormat}\n messageId={messageId}\n query={query}\n fallback={true}\n onError={onError}\n previousRecommendations={recommendations.length > 0 ? recommendations : undefined}\n />\n </FinalLinkDetectionCheck>\n )}\n\n {/* Render follow-up portal if follow-up exists */}\n </>\n );\n};\n\nexport default WeaveAdFormatContainer;\n","'use client';\n\nimport { useEffect, useRef, useCallback } from 'react';\nimport { useAdMesh } from './useAdMesh';\nimport {\n createInlineExposureTracker,\n type InlineExposureTrackingParams\n} from '../utils/inlineExposureTracker';\n\nexport interface UseWeaveAdFormatOptions {\n /** Container ID for the LLM output (where AdMesh links will be detected) */\n llmOutputContainerId: string;\n\n /** Timeout for link detection (default: 900ms) */\n timeoutMs?: number;\n\n /** Fallback format if no links detected (default: 'tail') */\n fallbackFormat?: 'product' | 'tail';\n\n /** Optional callback when AdMesh links are detected */\n onLinksDetected?: (count: number) => void;\n\n /** Optional callback when no links are detected (fallback should be rendered) */\n onNoLinksDetected?: () => void;\n\n /** Optional callback on error */\n onError?: (error: Error) => void;\n\n /** Optional query for fallback API calls (used when no links are detected) */\n query?: string;\n\n /** Optional message ID for fallback API calls (used when no links are detected) */\n messageId?: string;\n}\n\n/**\n * useWeaveAdFormat - Hook for automatic Weave Ad Format handling\n * \n * Automatically:\n * - Detects AdMesh links in LLM output\n * - Fires exposure tracking for detected links\n * - Adds Ad labels to links\n * - Shows \"Why this ad?\" tooltip on hover\n * - Renders fallback UI if no links detected\n * \n * @example\n * ```tsx\n * const { isProcessing, detectedLinksCount } = useWeaveAdFormat({\n * llmOutputContainerId: 'llm-output-123',\n * timeoutMs: 1500,\n * fallbackFormat: 'tail'\n * });\n * ```\n */\nexport const useWeaveAdFormat = (options: UseWeaveAdFormatOptions) => {\n const { sdk, sessionId } = useAdMesh();\n const processingRef = useRef(false);\n const detectedLinksRef = useRef(0);\n const linksFoundRef = useRef(false);\n const callbackFiredRef = useRef(false);\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);\n const exposureTrackerRef = useRef(createInlineExposureTracker());\n\n useEffect(() => {\n return () => {\n exposureTrackerRef.current.cleanup();\n };\n }, []);\n\n const trackInlineExposure = useCallback(\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) => {\n exposureTrackerRef.current.startTracking({\n exposureUrl,\n recommendationId,\n linkElement,\n sessionId,\n logPrefix: '[useWeaveAdFormat]'\n });\n },\n [sessionId]\n );\n\n // Phase 1: Enhanced Mutation Silence Detection\n // Track when last mutation occurred for silence detection\n const lastMutationTimeRef = useRef<number>(Date.now());\n // Count consecutive silence checks (requires 2 for confirmation)\n const mutationSilenceCountRef = useRef<number>(0);\n // Store interval timer for cleanup\n const silenceCheckIntervalRef = useRef<NodeJS.Timeout | null>(null);\n\n // Phase 2: Adaptive Debounce Detection\n // Track timestamps of recent mutations to calculate adaptive timeout\n const mutationTimestampsRef = useRef<number[]>([]);\n // Store the calculated adaptive timeout value\n const adaptiveTimeoutRef = useRef<number>(300); // Default to 300ms\n\n const processWeaveFormat = useCallback(async () => {\n if (!sdk || !sessionId || processingRef.current) {\n return;\n }\n\n processingRef.current = true;\n detectedLinksRef.current = 0;\n\n try {\n const container = document.getElementById(options.llmOutputContainerId);\n if (!container) {\n \n return;\n }\n\n // Get the WeaveResponseProcessor from SDK\n const weaveProcessor = (sdk as any).getWeaveProcessor?.(); // eslint-disable-line @typescript-eslint/no-explicit-any\n if (!weaveProcessor) {\n return;\n }\n\n // Scan and process AdMesh links in the container\n const detectedLinks = weaveProcessor.scanAndProcessLinks(\n container,\n [], // Recommendations will be fetched from SDK cache\n ({ exposureUrl, recommendationId, linkElement }: InlineExposureTrackingParams) =>\n trackInlineExposure({ exposureUrl, recommendationId, linkElement })\n );\n\n detectedLinksRef.current = detectedLinks.length;\n const hasLinks = detectedLinks.length > 0;\n\n // Update the flag indicating whether links were found\n if (hasLinks && !linksFoundRef.current) {\n // Links detected (first time or after streaming)\n linksFoundRef.current = true;\n options.onLinksDetected?.(detectedLinks.length);\n callbackFiredRef.current = true;\n } else if (!hasLinks && linksFoundRef.current) {\n // Links were found before but now they're gone (shouldn't happen in normal flow)\n linksFoundRef.current = false;\n callbackFiredRef.current = false;\n } else if (!hasLinks && !callbackFiredRef.current) {\n // No links found and callback hasn't been fired yet\n // Use enhanced mutation silence detection to wait for streaming to complete\n // This prevents firing the callback too early during streaming\n\n // Clear existing debounce timer\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n\n // Clear existing silence check interval\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n }\n\n // Reset silence counter when starting new detection\n mutationSilenceCountRef.current = 0;\n lastMutationTimeRef.current = Date.now();\n\n // Phase 1 + Phase 2: Enhanced Mutation Silence Detection with Adaptive Timeout\n // Check for mutation silence at adaptive intervals\n // Require 2 consecutive silence checks before declaring streaming complete\n const silenceCheckInterval = Math.max(100, adaptiveTimeoutRef.current / 3); // Check 3x per adaptive timeout\n\n silenceCheckIntervalRef.current = setInterval(() => {\n const timeSinceLastMutation = Date.now() - lastMutationTimeRef.current;\n const SILENCE_THRESHOLD = adaptiveTimeoutRef.current; // Use adaptive timeout as silence threshold\n\n if (timeSinceLastMutation >= SILENCE_THRESHOLD) {\n // Mutation silence detected\n mutationSilenceCountRef.current++;\n\n // Require 2 consecutive silence checks for confirmation\n if (mutationSilenceCountRef.current >= 2) {\n // Clear the interval\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n silenceCheckIntervalRef.current = null;\n }\n\n // Fire callback if no links were found\n if (!linksFoundRef.current && !callbackFiredRef.current) {\n options.onNoLinksDetected?.();\n callbackFiredRef.current = true;\n }\n }\n } else {\n // Mutations still happening, reset counter\n mutationSilenceCountRef.current = 0;\n }\n }, silenceCheckInterval);\n\n // Phase 2: Fallback timeout using adaptive timeout\n // Set a maximum timeout to ensure we eventually fire the callback\n // This handles edge cases where mutations might be very infrequent\n const maxFallbackTimeout = Math.max(1500, adaptiveTimeoutRef.current * 5); // At least 1500ms, or 5x adaptive timeout\n\n debounceTimerRef.current = setTimeout(() => {\n // Clear the silence check interval\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n silenceCheckIntervalRef.current = null;\n }\n\n // Fire callback if no links were found\n if (!linksFoundRef.current && !callbackFiredRef.current) {\n options.onNoLinksDetected?.();\n callbackFiredRef.current = true;\n }\n }, maxFallbackTimeout);\n } else if (hasLinks && callbackFiredRef.current && !linksFoundRef.current) {\n // Links detected after we initially said \"no links found\"\n // This happens when links arrive during streaming\n\n\n // Clear debounce timer since we found links\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = null;\n }\n\n linksFoundRef.current = true;\n options.onLinksDetected?.(detectedLinks.length);\n callbackFiredRef.current = true;\n } else {\n \n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n options.onError?.(err);\n } finally {\n processingRef.current = false;\n }\n }, [sdk, sessionId, options, trackInlineExposure]);\n\n // Phase 2: Calculate adaptive debounce timeout based on mutation frequency\n const calculateAdaptiveTimeout = useCallback(() => {\n const timestamps = mutationTimestampsRef.current;\n\n // Need at least 2 timestamps to calculate interval\n if (timestamps.length < 2) {\n adaptiveTimeoutRef.current = 300; // Default to 300ms\n return;\n }\n\n // Calculate intervals between consecutive mutations\n const intervals: number[] = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i] - timestamps[i - 1]);\n }\n\n // Calculate average interval\n const avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n\n // Adaptive timeout: 3x the average interval, min 100ms, max 1000ms\n const adaptiveTimeout = Math.max(100, Math.min(avgInterval * 3, 1000));\n\n adaptiveTimeoutRef.current = adaptiveTimeout;\n }, []);\n\n // Watch for changes in the LLM output container\n useEffect(() => {\n const container = document.getElementById(options.llmOutputContainerId);\n if (!container) {\n return;\n }\n\n // Initial scan\n processWeaveFormat();\n\n // Set up MutationObserver for streaming responses\n const observer = new MutationObserver(() => {\n const now = Date.now();\n\n // Phase 1: Update last mutation time for silence detection\n lastMutationTimeRef.current = now;\n // Reset silence counter since we detected a mutation\n mutationSilenceCountRef.current = 0;\n\n // Phase 2: Track mutation timestamp for adaptive debounce calculation\n mutationTimestampsRef.current.push(now);\n // Keep only last 10 timestamps to avoid memory bloat\n if (mutationTimestampsRef.current.length > 10) {\n mutationTimestampsRef.current.shift();\n }\n // Recalculate adaptive timeout based on recent mutation pattern\n calculateAdaptiveTimeout();\n\n processWeaveFormat();\n });\n\n observer.observe(container, {\n childList: true,\n subtree: true,\n characterData: false\n });\n\n return () => {\n observer.disconnect();\n // Clean up debounce timer on unmount\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n // Phase 1: Clean up silence check interval on unmount\n if (silenceCheckIntervalRef.current) {\n clearInterval(silenceCheckIntervalRef.current);\n }\n };\n }, [options.llmOutputContainerId, processWeaveFormat, calculateAdaptiveTimeout]);\n\n return {\n isProcessing: processingRef.current,\n detectedLinksCount: detectedLinksRef.current,\n linksFound: linksFoundRef.current,\n shouldRenderFallback: !linksFoundRef.current && callbackFiredRef.current,\n processWeaveFormat\n };\n};\n\nexport default useWeaveAdFormat;\n","/**\n * AdMesh UI SDK - Main Entry Point\n * \n * Zero-code integration for displaying AdMesh recommendations\n */\n\n// Import Tailwind CSS for markdown styling\nimport './styles/globals.css';\n\n// Core SDK\nexport { AdMeshSDK } from './sdk/AdMeshSDK';\nexport type { AdMeshSDKConfig, ShowRecommendationsOptions } from './sdk/AdMeshSDK';\n\n// Tracking\nexport { AdMeshTracker } from './sdk/AdMeshTracker';\nexport type { TrackerConfig } from './sdk/AdMeshTracker';\n\n// Rendering\nexport { AdMeshRenderer } from './sdk/AdMeshRenderer';\nexport type { RenderOptions } from './sdk/AdMeshRenderer';\n\n// ACIE API integration\nexport { callAnalyzeIntentEndpoint } from './utils/acieApi';\nexport type { \n CommercialIntentRequest, \n CommercialIntentResult\n} from './utils/acieApi';\n\n// Weave Response Processing\nexport { WeaveResponseProcessor } from './sdk/WeaveResponseProcessor';\nexport type { DetectedLink, ProcessorConfig } from './sdk/WeaveResponseProcessor';\n\n// Weave format is now integrated into AdMeshSDK\n// Use format: 'weave' option in showRecommendations() method\n\n// Provider Pattern (Simplified Integration)\nexport { AdMeshProvider } from './context/AdMeshProvider';\nexport type { AdMeshProviderProps } from './context/AdMeshProvider';\n\n// Components\nexport { AdMeshRecommendations } from './components/AdMeshRecommendations';\nexport type { AdMeshRecommendationsProps } from './components/AdMeshRecommendations';\nexport { WeaveFallbackRecommendations } from './components/WeaveFallbackRecommendations';\nexport type { WeaveFallbackRecommendationsProps } from './components/WeaveFallbackRecommendations';\n\n// Context\nexport { AdMeshContext, useAdMeshContext } from './context/AdMeshContext';\nexport type { AdMeshContextValue } from './context/AdMeshContext';\nexport { WeaveAdFormatProvider, useWeaveAdFormatContext } from './context/WeaveAdFormatContext';\nexport type { WeaveAdFormatContextType } from './context/WeaveAdFormatContext';\n\n// Components\nexport { AdMeshLayout } from './components/AdMeshLayout';\nexport { AdMeshTailAd } from './components/AdMeshTailAd';\nexport type { AdMeshTailAdProps } from './components/AdMeshTailAd';\nexport { AdMeshCompactCard } from './components/AdMeshCompactCard';\nexport { AdMeshFollowup } from './components/AdMeshFollowup';\nexport type { AdMeshFollowupProps } from './components/AdMeshFollowup';\nexport { AdMeshViewabilityTracker } from './components/AdMeshViewabilityTracker';\nexport { AdMeshLinkTracker } from './components/AdMeshLinkTracker';\nexport { AdMeshBadge } from './components/AdMeshBadge';\nexport { AdMeshIntentAssistant } from './components/AdMeshIntentAssistant';\nexport type { AdMeshIntentAssistantProps } from './components/AdMeshIntentAssistant';\nexport { WeaveAdFormatContainer } from './components/WeaveAdFormatContainer';\nexport type { WeaveAdFormatContainerProps } from './components/WeaveAdFormatContainer';\n\n// Hooks\nexport { useAdMesh } from './hooks/useAdMesh';\nexport { useAdMeshStyles } from './hooks/useAdMeshStyles';\nexport { useViewabilityTracker } from './hooks/useViewabilityTracker';\nexport { useWeaveAdFormat } from './hooks/useWeaveAdFormat';\nexport type { UseWeaveAdFormatOptions } from './hooks/useWeaveAdFormat';\n\n// Types\nexport type { AdMeshTheme, PlatformResponse, DelegationActivationPayload, ActiveDelegationSession } from './types/index';\n\n// Streaming Events (for event-driven link detection)\nexport {\n dispatchStreamingStartEvent,\n dispatchStreamingCompleteEvent,\n onStreamingStart,\n onStreamingComplete,\n STREAMING_START_EVENT,\n STREAMING_COMPLETE_EVENT\n} from './utils/streamingEvents';\nexport type {\n StreamingStartEventDetail,\n StreamingCompleteEventDetail\n} from './utils/streamingEvents';\n\n// Inline exposure tracking helper\nexport {\n createInlineExposureTracker\n} from './utils/inlineExposureTracker';\nexport type {\n InlineExposureTracker,\n InlineExposureTrackingParams\n} from './utils/inlineExposureTracker';\n\n// Headings extraction utility\nexport { extractHeadingsDirectly } from './utils/extractHeadings';\nexport type { HeadingsExtractionResult } from './utils/extractHeadings';\n\n// Version\nexport const VERSION = '1.0.31';\n"],"names":["isProduction","_a","logger","args","calculateMRCStandards","adWidth","adHeight","customStandards","isLargeAd","detectDeviceType","viewportWidth","calculateVisibilityPercentage","element","rect","viewportHeight","elementHeight","elementWidth","visibleTop","visibleBottom","visibleLeft","visibleRight","visibleHeight","visibleWidth","visibleArea","totalArea","calculateScrollDepth","windowHeight","documentHeight","scrollTop","scrollableHeight","getElementPosition","scrollLeft","collectContextMetrics","position","isDarkMode","generateSessionId","meetsViewabilityThreshold","visibilityPercentage","visibleDuration","standards","formatTimestamp","date","calculateAverage","numbers","acc","num","throttle","func","limit","inThrottle","DEFAULT_CONFIG","globalConfig","ANALYTICS_DISABLED","useViewabilityTracker","productId","offerId","agentId","recommendationId","elementRef","customConfig","config","sessionId","useRef","state","setState","useState","mrcStandards","visibilityStartTime","viewableStartTime","hoverStartTime","focusStartTime","visibilityPercentages","eventBatch","batchTimeout","log","useCallback","message","sendEvent","eventType","additionalData","contextMetrics","event","flushBatch","updateVisibility","now","loadTime","prev","newState","wasVisible","isNowVisible","wasViewable","isNowViewable","viewableDuration","useEffect","observer","entries","handleScroll","handleMouseEnter","handleMouseLeave","hoverDuration","handleFocus","handleBlur","focusDuration","handleClick","sessionDuration","AdMeshViewabilityTracker","exposureUrl","triggerExposureUrl","children","className","style","onViewabilityChange","onVisible","onViewable","onClick","exposureFired","viewabilityState","previousViewable","error","previousVisible","jsx","isValidUrl","url","getDisplayText","value","asOptionalString","getCTALabel","ctaLabel","formatProductPrice","price","currency","AdMeshCompactCard","recommendations","theme","onDelegationConsent","onDelegationActivated","onStartDelegation","firstRecommendation","recommendation","creative","tracking","delegation","brandName","headline","description","logoUrl","clickUrl","disclosure","relatedProducts","visibleProducts","hasProductRail","isBridgeRecommendation","hasDelegation","shouldShowDelegationButton","delegationBrandName","delegationCtaText","shouldShowPrimaryCta","compactTitle","compactSummary","normalizedBrandName","normalizedCompactTitle","shouldShowBrandEyebrow","showConsentPrompt","setShowConsentPrompt","consentResolverRef","resolveConsentPrompt","requestConsent","resolve","handleContainerClick","source","e","handleCardClick","handleCardKeyDown","trackDelegationEngagement","apiBaseUrl","response","handleDelegationClick","delegationPayload","logoError","setLogoError","cardBackground","_b","cardBorder","_d","_c","cardShadow","_e","_g","_f","accentColor","mutedText","bodyText","titleText","railCardBackground","textColumnOffset","footerAction","jsxs","_i","_h","product","productName","productLink","productPrice","productImageUrl","displayImage","hasProductLink","AdMeshLayout","validRecs","rec","renderContent","firstRec","preferredFormat","AdMeshTracker","__publicField","key","timeoutId","entry","cleanupTimeout","threshold","engagementUrl","_recommendationId","AdMeshContext","createContext","useAdMeshContext","context","useContext","titleFromPath","pathname","segments","cleaned","char","extractHeadingsDirectly","cleanText","text","getArticleText","selectors","ignoredSelector","clone","selector","node","candidate","a","b","paragraphs","fallbackTitle","title","headings","allHeadings","headingElements","resolvedHeadings","result","isPlatformResponse","normalizeAcieRecommendation","products","_j","_k","normalizeCommercialIntentResult","suggestion","extractArticleSlug","pathSegments","segment","callAnalyzeIntentEndpoint","headingsData","pathTopic","fallbackHeading","articleSlug","normalizedSource","normalizedDomain","payload","apiUrl","errorText","rawAnalysisResult","analysisResult","err","fetchPageContext","base","params","body","isInIframe","getUsableWindowHref","href","isResolvedArticleUrl","trimmed","parsed","titleFromUrlPath","buildUrlFallbackContext","resolveArticleUrlForContext","articleUrl","currentHref","AdMeshProvider","apiKey","extension","language","location","userId","model","messages","pageContext","contextMode","agentDisplayId","sdk","setSdk","processedMessageIds","setProcessedMessageIds","recommendationResults","setRecommendationResults","activeDelegationSession","setActiveDelegationSessionState","suggestions","setSuggestions","isAnalyzingIntent","setIsAnalyzingIntent","intentError","setIntentError","isResolvingPageContext","setIsResolvingPageContext","hasAttemptedInitialAnalysisRef","usesAdSlotContext","resolveHeadingsForAnalysis","targetUrl","prependSponsoredSuggestion","currentSuggestions","sponsoredSuggestion","organicSuggestions","mergeOrganicSuggestions","nextOrganicSuggestions","sdkInstance","AdMeshSDK","performIntentAnalysis","prefetchedHeadingsData","current","prefetchSponsoredSuggestion","query","platformResult","suggestionText","retryIntentAnalysis","isDelegationSessionActive","session","expiresAtMs","postDelegationEvent","endpoint","metadata","sessionOverride","timestamp","errorBody","updatedSession","interval","contextValue","messageId","updated","next","reason","analyticsError","AdMeshRenderer","options","container","existingRoot","root","ReactDOM","containerId","normalizeCountryCode","_AdMeshSDK","configuredDomain","random","outcomeType","renderer","tracker","cacheKey","inFlightResponse","turnIndex","devicePlatform","formFactor","countryCode","resolvedUserId","jsonBody","_m","_l","headers","sourceDomain","requestPromise","errorMessage","data","WeaveResponseProcessor","optimizedLinks","onExposurePixel","detectedLinks","links","clickUrlMap","r","brandUrlMap","redirectUrl","normalizedUrl","link","linkKey","actualHref","normalizedHref","recommendationClickUrl","detectedLink","childElements","child","prevNode","tagName","nextNode","parentNode","subLabel","isTooltipVisible","closeTooltipOnClickOutside","nextSibling","domain","match","useAdMesh","PlusIcon","size","AdMeshFollowup","_theme","onExecuteQuery","followupSuggestion","followupQuery","followupEngagementUrl","followupExposureUrl","handleFollowupClick","AdMeshRecommendations","onRecommendationsShown","onError","propUserId","initialRecommendation","followups_container_id","onPasteToInput","onFollowupDetected","isContainerReady","contextUserId","getRecommendationResult","hasRecommendationResult","setRecommendationResult","setActiveDelegationSession","hasActiveDelegationSession","isFilledAuctionResponse","setPlatformResult","detectedFormat","setDetectedFormat","isLoading","setIsLoading","setError","fetchedMessageIdRef","isFetchingRef","reusedInitialRecommendationRef","onRecommendationsShownRef","onErrorRef","hasActiveDelegatedSessionForConversation","storedResult","selectedFormat","canonicalResponse","initialStatus","resultStatus","handleSdkDelegationActivated","activation","resolvedPayload","activeSession","eventError","callbackError","followupContainer","Fragment","createPortal","WeaveFallbackRecommendations","format","fallback","previousRecommendations","containerRef","setContainerId","hasPreviousRecs","aipResponse","sdkAny","getRendererMethod","getTrackerMethod","sdkTheme","WeaveAdFormatContext","WeaveAdFormatProvider","shouldRenderFallback","useWeaveAdFormatContext","truncateWords","maxWords","words","formatProductDiscount","discount","discountType","normalizedType","TAIL_AD_COLORS","AdMeshTailAd","shortDescription","_n","_p","_o","_r","_q","_t","_s","recommendationFormat","_u","_v","_w","headlineText","headlineSuffix","_x","_z","_y","handleBrandNameClick","handleCTAClick","handleLogoClick","fallbackPrompt","brandInitial","cardBorderRadius","_B","_A","defaultShadow","hoverShadow","_C","_E","_D","cardHoverShadow","_F","_G","productDescription","productDiscount","fallbackLogoUrl","displayProductImageUrl","productCtaLabel","AdMeshLinkTracker","admeshLink","_productId","_trackingData","hasOwn","classNames","classes","i","arg","appendClass","parseValue","newClass","module","badgeTypeVariants","badgeTypeIcons","AdMeshBadge","type","variant","effectiveVariant","icon","badgeClasses","mergeClasses","index","array","toKebabCase","string","toCamelCase","p1","p2","toPascalCase","camelCase","defaultAttributes","hasA11yProp","props","prop","Icon","forwardRef","color","strokeWidth","absoluteStrokeWidth","iconNode","rest","ref","createElement","tag","attrs","createLucideIcon","iconName","Component","__iconNode","Maximize2","Minimize2","Send","ThumbsDown","ThumbsUp","X","ADMESH_STYLE_ID","ADMESH_RESET_ID","ADMESH_CSS_RESET","ADMESH_CORE_STYLES","injectAdMeshStyles","resetStyle","coreStyle","ADMESH_STYLES","stylesInjected","useAdMeshStyles","styleElement","formatGenerationDuration","totalSeconds","seconds","minutes","remainder","formatGenerationDurationFromMs","durationMs","CustomMarkdownRenderer","content","fontSize","renderInlineFormatting","part","parseTableRow","line","cell","cells","isTableSeparator","splitTablePrefixHeading","pipeIndex","prefix","normalizeTableSeparator","headerLine","separatorLine","headerCount","separatorCount","normalizeTableLines","lines","heading","normalizedHeader","normalizedSeparator","isMarkdownTable","normalizedLines","expandInlineTableLine","working","_match","separatorRow","normalizeCompactMarkdownTables","markdown","normalized","blocks","output","nextLine","block","blockIndex","isBulletList","isNumberedList","isHeading","isTable","tableLines","rows","row","header","rowIndex","cellIndex","ListTag","lineIndex","toCssSize","normalizeSuggestionText","mergeSuggestionsPreservingOrganic","nextSuggestions","currentOrganicSuggestions","buildFollowupSuggestionsFromAnswer","answer","sourceLinks","relatedItems","seen","pushSuggestion","topics","collectTopic","item","cleanQuery","topicList","detectAssistantDeviceType","width","isResolvedPageUrl","getAssistantPageContext","pageUrlOverride","resolvedPageUrl","page_path","buildSponsoredSuggestionFromRecommendation","prioritizeSponsoredSuggestions","items","left","right","leftSponsored","rightSponsored","defaultTheme","sizeConfig","positionConfig","AdMeshIntentAssistant","propTheme","triggerLabel","headerTitle","headerLogoUrl","showHeaderTitle","showSubtitle","layout","surface","panelWidth","panelHeight","analyticsPageUrl","fontScale","defaultOpen","open","onOpenChange","autoOpen","showWelcomeMessage","welcomeMessage","placeholder","adsEnabled","propSuggestions","maxSuggestions","suggestionStyle","onlyShowWhenSponsored","queryHandler","suggestionsLoader","disclaimerText","poweredByLabel","subtitle","onOpen","onClose","contextTheme","contextSuggestions","stopDelegationSession","refreshDelegationActivity","themeMode","isAdSlotSurface","internalOpen","setInternalOpen","isControlled","isOpen","inputValue","setInputValue","setMessages","isExpanded","setIsExpanded","sponsoredClickedMessages","setSponsoredClickedMessages","resolvedSuggestions","setResolvedSuggestions","loadingLabelIndex","setLoadingLabelIndex","generationElapsedSec","setGenerationElapsedSec","messageFeedback","setMessageFeedback","generationStartedAtRef","currentMessageIsSponsored","currentSponsoredSuggestionRef","suggestionButtonRefs","suggestionExposureCleanupRef","messagesScrollRef","activeSubmittedMessageRef","activeSubmittedMessageIdRef","shouldAnchorSubmittedMessageRef","suppressAutoScrollToBottomRef","adSlotRootRef","messagesEndRef","suggestionsScrollRef","generationAbortRef","activeAssistantMessageIdRef","canScrollSuggestionsLeft","setCanScrollSuggestionsLeft","canScrollSuggestionsRight","setCanScrollSuggestionsRight","canUseDirectAdMeshFetch","connectedDelegationSession","trackedSuggestionExposureKeysRef","trackedRecommendationKeysRef","loadedTrackedRef","shouldExpandAdSlot","adSlotWidthCss","adSlotHeightCss","setSuggestionButtonRef","suggestionId","trackAssistantEvent","event_name","handleRecommendationShown","trackKey","refreshSuggestionsForResponse","followupSuggestions","generated","normalizedText","upsertSponsoredFollowupSuggestion","organic","scrollSubmittedMessageToTop","scroller","activeMessage","scrollerRect","activeMessageRect","targetTop","useLayoutEffect","mountNode","nextHeight","host","cancelled","loadError","tick","startedAt","handleOpenChange","newOpen","handleOpenClick","handleCloseClick","handleToggleExpand","callAssistantAPI","onContentChunk","onStreamStart","sponsoredRecommendation","signal","activityError","reader","decoder","fullResponse","finalSourceLinks","finalRelatedItems","finalFollowupSuggestions","finalUsedCapability","finalResponseTimeMs","done","parsedData","handleStopGeneration","controller","activeAssistantMessageId","msg","handleSendMessage","normalizedMessage","userMessageId","generationController","activeSponsoredSuggestion","activeSponsoredRecommendation","userMessage","assistantMessageId","initialAssistantMessage","queryError","errorResponse","assistantMessage","sponsoredRecommendationForMessage","contentChunk","resolvedResponseTimeMs","hasSponsoredSuggestions","useMemo","s","safeSuggestions","orderedSuggestions","handleSuggestionClick","suggestionPosition","positionStyle","sizeStyle","cleanup","exposureKey","viewableTimer","fireSuggestionExposure","fontSizes","genericDisclaimer","loadingSteps","renderGeneratingIndicator","accent","publisherAccent","meta","publisherMeta","includeSteps","timerLabel","statusLabel","withAlpha","brandPrimary","handleAnswerFeedback","helpful","feedbackValue","renderAnswerFooter","selectedFeedback","hasTiming","updateSuggestionScrollState","maxScrollLeft","scrollSuggestions","direction","hex","alpha","raw","full","red","green","blue","brandBorder","brandText","brandMuted","purpleBorderSoft","purpleShadowSoft","publisherPanelWidth","publisherPanelHeight","publisherPanelMaxWidth","publisherPanelMaxHeight","publisherMessageFontSize","publisherSurfaceBg","assistantSubtitle","shouldShowSuggestionSkeletons","expandedShellBackground","expandedHeaderBackground","expandedBorder","expandedBorderStrong","expandedShadow","expandedMutedText","expandedSubtleText","expandedUserBubble","expandedComposerBackground","expandedComposerShadow","expandedOverlay","renderDelegationBanner","mode","renderExpandedBranding","compact","renderSuggestionSkeletons","skeletonWidths","renderPublisherSuggestions","visibleSuggestions","renderSourceLinks","renderRelatedItems","renderPublisherMessages","isActiveSubmittedMessage","shouldShowRecommendations","recommendationError","teaser","XIcon","SendIcon","STREAMING_START_EVENT","STREAMING_COMPLETE_EVENT","dispatchStreamingStartEvent","detail","dispatchStreamingCompleteEvent","onStreamingStart","callback","handler","customEvent","onStreamingComplete","createInlineExposureTracker","firedKeys","activeTrackers","cleanupTracker","linkElement","logPrefix","dedupeKey","trackerState","fireExposurePixel","FinalLinkDetectionCheck","onLinksFound","onNoLinksFound","checkComplete","setCheckComplete","waitingForStreamEnd","setWaitingForStreamEnd","linksFound","setLinksFound","exposureTrackerRef","onLinksFoundRef","onNoLinksFoundRef","containerIdRef","sdkRef","sessionIdRef","queryRef","trackExposurePixel","performFinalCheck","weaveProcessor","recsToUse","eventReceived","WeaveAdFormatContainer","fallbackFormat","onLinksDetected","onNoLinksDetected","onFallbackChange","onWeaveAttempt","onWeaveOutcome","scannedRef","weaveProcessorRef","setRecommendations","recommendationsRef","platformResponse","recs","brandUrl","isWeaveFormat","count","useWeaveAdFormat","processingRef","detectedLinksRef","linksFoundRef","callbackFiredRef","debounceTimerRef","trackInlineExposure","lastMutationTimeRef","mutationSilenceCountRef","silenceCheckIntervalRef","mutationTimestampsRef","adaptiveTimeoutRef","processWeaveFormat","hasLinks","silenceCheckInterval","timeSinceLastMutation","SILENCE_THRESHOLD","maxFallbackTimeout","calculateAdaptiveTimeout","timestamps","intervals","avgInterval","adaptiveTimeout","VERSION"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","x_google_ignoreList":[22,24,25,26,27,28,29,30,31,32,33,34,35,36,37]}