{"version":3,"file":"DAsf-1.50.e9l3rrkg.js","names":[],"sources":["../../../../src/js/components/perf.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/core.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/metrics.ts","../../../../src/js/components/state/page/pageState.ts","../../../../src/js/components/weblabs.ts","../../../../src/js/components/metrics/csaMetrics.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/logging.ts","../../../../src/js/components/metrics/emitErrorLog.ts","../../../../src/js/components/utils/hasOwn.ts","../../../../src/js/components/bridge/core/receiver.ts","../../../../src/js/components/bridge/core/wire.ts","../../../../src/js/components/bridge/core/sender.ts","../../../../src/js/components/bridge/csa/csaBridgeReceiver.ts","../../../../src/js/components/bridge/csm/csmBridgeReceiver.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/latency.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csm/latency.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/latency.ts","../../../../src/js/host/components/placement.ts","../../../../src/js/components/bridge/events/dispatchClickForCsaAttribution.ts","../../../../src/js/components/bridge/events/shouldSafeFrameFireLoadedMetrics.ts","../../../../src/js/components/bridge/safeFrameExt/safeFrameExtBridgeSender.ts","../../../../src/js/components/collapsePlacement.ts","../../../../src/js/components/metrics/assetMetricLogger.ts","../../../../src/js/components/metrics/coordinate-logger.ts","../../../../src/js/components/pixels/pixelIdentifiers.ts","../../../../src/js/components/state/placement/placementState.ts","../../../../src/js/components/state/placement/pixelState.ts","../../../../src/js/components/pixels/pixel.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/domObstructions/getDOMObstructionPercentage.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/nativeObstructionsUtils.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/getObstructions.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/obstructionsEventListeners.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/getNativeObstructionPercentage.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.ts","../../../../src/js/components/intersectionObserver.ts","../../../../src/js/components/pixels/mrcObstructionViewPixel.ts","../../../../src/js/components/pixels/viewPixelUtil.ts","../../../../src/js/components/pixels/services/viewabilityServiceImpl.ts","../../../../src/js/components/pixels/services/visibilityChangeService.ts","../../../../src/js/components/skadnetwork/skanAppAdsAttribution.ts","../../../../src/js/components/pixels/skanImpressionPixel.ts","../../../../src/js/components/pixels/skanViewPixel.ts","../../../../src/js/components/aax/aax.ts","../../../../src/js/components/urlQueryParams/addJSONQueryParamToURL.ts","../../../../src/js/components/util.ts","../../../../src/js/components/pixels/urlGenerators/btrPixelUrlGenerator.ts","../../../../src/js/components/pixels/urlGenerators/impressionPixelUrlGenerator.ts","../../../../src/js/components/viewability.ts","../../../../src/js/components/pixels/urlGenerators/measurabilityPixelUrlGenerator.ts","../../../../src/js/components/pixels/placementData.ts","../../../../src/js/components/pixels/urlGenerators/mrcObstructionViewPixelUrlGenerator.ts","../../../../src/js/components/pixels/viewabilityStandards.ts","../../../../src/js/components/pixels/viewabilityTrackerImpl.ts","../../../../src/js/components/pixels/pixelMapper.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/logging.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/retail-click-tracking.ts","../../../../src/js/host/api-client/handlers/retailClickTrackingHandler.ts","../../../../src/js/components/viewRateExperimentUtil.ts","../../../../../../../node_modules/throttle-debounce/esm/index.js","../../../../src/js/host/components/loading.ts","../../../../src/js/host/components/waitUntilReadyForTracking.ts","../../../../src/js/host/api-client/handlers/sendEventCreativeBeginToRenderHandler.ts","../../../../src/js/components/events/customEvents.ts","../../../../src/js/components/pixels/services/videoFirePixelValidator.ts","../../../../src/js/host/components/skanViewabilityTracker.ts","../../../../src/js/host/api-client/handlers/sendEventCreativeLoadedHandler.ts","../../../../src/js/host/components/iframe.ts","../../../../src/js/host/api-client/handlers/sendSafeFrameExt.ts","../../../../src/js/host/components/logIframePostMessage.ts","../../../../src/js/host/slotSpecific/navCartClassToggle.ts","../../../../src/js/components/bridge/events/eventsBridgeReceiver.ts","../../../../src/js/components/bridge/core/bridge.ts","../../../../src/js/components/bridge/mash/mashBridgeHost.ts","../../../../src/js/components/bridge/msfclient/msfClientBridgeHost.ts","../../../../src/js/host/components/css.ts","../../../../src/js/components/bridge/sfclient/changeSizeHandler.ts","../../../../src/js/components/feedback.ts","../../../../src/js/components/bridge/sfclient/sfClientBridgeReceiver.ts","../../../../src/js/components/homepage/homepageVideoOrchestrator.ts","../../../../src/js/components/bridge/video/videoHandlers.ts","../../../../src/js/components/bridge/video/videoBridgeReceiver.ts","../../../../src/js/host/app/resolveAdDetailsFromIframe.ts","../../../../src/js/host/app/safeFrameHost.ts","../../../../src/js/host/app/initSafeFrameHost.ts","../../../../src/js/host/app/entrypoints/DAsf.ts"],"sourcesContent":["import type { AdDetails } from '@amzn/safeframe-model';\n\nexport const PERF_SF_HOST = 'perf:sf:host';\nexport const PERF_SF_CLIENT = 'perf:sf:client';\nexport const PERF_SF_SETUP = 'perf:sf:setup';\nexport const PERF_LA = 'perf:la';\n\n/** The only ad-identity field perf marks read. Any AdDetails-like shape (full, wire-slim, light-ad) satisfies it. */\ntype MarkAdDetails = Pick<AdDetails, 'placementName'>;\n\nexport const getMarkName = (scope: string, message: string, adDetails?: MarkAdDetails): string =>\n    `${scope}${adDetails ? `:${adDetails.placementName}` : ''} - ${message}`;\n\nexport const mark = (scope: string, message: string, adDetails?: MarkAdDetails): string => {\n    const markString = getMarkName(scope, message, adDetails);\n\n    performance?.mark?.(markString);\n\n    return markString;\n};\n\nexport interface LatencyTracker {\n    readonly startTime: number;\n    elapsed: () => number;\n}\n\nexport const createLatencyTracker = (): LatencyTracker => {\n    const startTime = performance.now();\n    return { startTime, elapsed: () => performance.now() - startTime };\n};\n","export const METRICS_SOURCE_GROUP = 'com.amazon.apm.stores.csa.metrics.prod';\nexport const LOGS_SOURCE_GROUP = 'com.amazon.apm.stores.csa.logs.prod';\nexport const NEXUS_SCHEMA_ID = 'com.amazon.apm.stores.ClientMetric.2';\nexport const NEXUS_PRODUCER_ID = 'apm-stores';\n\ntype LogCsaEventInput = {\n    sushiSourceGroup?: string;\n    producerId?: string;\n    data: Record<string, unknown>;\n};\n\n/**\n * Low-level transport: sends a single event to the CSA Events plugin.\n * Routes to either a Sushi source group or a Nexus producer depending on which\n * option is provided. Callers should use {@link emitCsaMetric} or {@link emitCsaLog} instead.\n *\n * @param sushiSourceGroup - Sushi source group to route the event to.\n * @param producerId - Nexus producer ID for the Nexus/Spektr emit path.\n * @param data - Arbitrary event payload.\n */\nexport const logCsaEvent = ({ sushiSourceGroup, producerId, data }: LogCsaEventInput): void =>\n    window.csa?.('Events', {\n        ...(producerId && { producerId }),\n        ...(sushiSourceGroup && { sushiSourceGroup }),\n    })?.('log', data, { ent: 'all' });\n","import { logCsaEvent, METRICS_SOURCE_GROUP, NEXUS_PRODUCER_ID, NEXUS_SCHEMA_ID } from './core.js';\n\nexport type CsaMetricInput = {\n    metricName: string;\n    metricValue: number;\n    timestamp?: Date;\n    dimensions: Record<string, string>;\n    weblabs?: Record<string, string>;\n};\n\n/**\n * Emits a CSA metric event to the metrics source group, which also routes to\n * the default CSA source group (Nexus → Spektr) for downstream analytics.\n *\n * Dual-emits: once to Sushi (full-precision metricValue, epoch ms timestamp) and once to\n * Nexus (rounded metricValue as int per the ClientMetric schema, ISO 8601 timestamp).\n *\n * @param metricName - Name of the metric to emit.\n * @param metricValue - Numeric value of the metric.\n * @param timestamp - When the metric was recorded. Defaults to now.\n * @param dimensions - Key-value pairs for metric dimensions.\n * @param weblabs - Active weblab treatments. Only included when provided.\n */\nexport const emitCsaMetric = ({\n    metricName,\n    metricValue,\n    timestamp = new Date(),\n    dimensions,\n    weblabs,\n}: CsaMetricInput): void => {\n    const base = { metricName, metricValue, dimensions };\n    logCsaEvent({\n        sushiSourceGroup: METRICS_SOURCE_GROUP,\n        data: { ...base, timestamp: timestamp.getTime(), ...(weblabs && { weblabs }) },\n    });\n    logCsaEvent({\n        producerId: NEXUS_PRODUCER_ID,\n        data: {\n            ...base,\n            metricValue: Math.round(metricValue),\n            timestamp: timestamp.toISOString(),\n            schemaId: NEXUS_SCHEMA_ID,\n        },\n    });\n};\n","type PageState = Record<string, Set<string>>;\n\ndeclare global {\n    interface Window {\n        AD_PLACEMENT: PageState;\n    }\n}\n\nconst getPageState = (): PageState => (window.AD_PLACEMENT ??= {});\n\nexport const getNamespace = (namespace: string): Set<string> => (getPageState()[namespace] ??= new Set());\n\nexport const createPageSet = (namespace: string) => {\n    const set = () => getNamespace(namespace);\n    return {\n        has: (key: string): boolean => set().has(key),\n        mark: (key: string): void => {\n            set().add(key);\n        },\n    };\n};\n\nexport const collapsedPlacements = createPageSet('collapsedPlacements');\nexport const emittedMetrics = createPageSet('loggedMetricNames');\nexport const feedbackState = createPageSet('feedback');\n","declare global {\n    // oxlint-disable-next-line\n    interface Window extends WeblabsWindow {}\n}\n\nexport type WeblabTreatment = `t${number}`;\n\nexport type AllWeblabTreatment = WeblabTreatment | 'c';\n\nexport interface WeblabsWindow {\n    renderingWeblabs?: { [key: string]: string };\n}\n\nexport interface Weblab {\n    is(treatment: WeblabTreatment): boolean;\n    isAssigned(): boolean;\n    isInTreatment(): boolean;\n    getTreatment(): AllWeblabTreatment;\n}\n\nexport const createWeblab = (weblabsWindow: WeblabsWindow, prefix: string): Weblab => {\n    const weblabTreatment = (): AllWeblabTreatment | undefined =>\n        weblabsWindow?.renderingWeblabs?.[prefix]?.toLowerCase() as AllWeblabTreatment;\n\n    return {\n        is(treatment: WeblabTreatment): boolean {\n            return weblabTreatment() === treatment;\n        },\n        isAssigned(): boolean {\n            return weblabTreatment() !== undefined;\n        },\n        isInTreatment(): boolean {\n            return !!weblabTreatment() && weblabTreatment() !== 'c';\n        },\n        getTreatment(): AllWeblabTreatment {\n            return weblabTreatment() ?? 'c';\n        },\n    };\n};\n\n/*\n * Used for gating IN art event styling\n * @link https://weblab.amazon.com/wl/ADPT_SF_HOMEPAGE_ART_THEMING_1298909\n */\nexport const ADPT_SF_HOMEPAGE_ART_THEMING = () => createWeblab(window, 'ADPT_SF_HOMEPAGE_ART_THEMING_1298909');\n\n/**\n * Used to enable new retail tracking with the JRS test painter.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_CLICK_TRACKING_PAINTER_TEST_1259727\n */\nexport const CLICK_TRACKING_PAINTER_TEST = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_CLICK_TRACKING_PAINTER_TEST_1259727');\n\n/**\n * Used to enable viewability-based impression pixel firing for CA, JP, and UK marketplaces.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_1289633\n */\nexport const VIEW_RATE_EXPERIMENT = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_1289633');\n\n/**\n * Used to control timeout for placement viewability of Stores View Rate experiment in ES and FR marketplaces.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_TIMEOUT_1373183\n */\nexport const VIEW_RATE_EXPERIMENT_TIMEOUT = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_TIMEOUT_1373183');\n\n/**\n * Used to disable user agent access for creatives\n * @link https://shepherd.a2z.com/issues/e4e8cd86-419a-4e1a-96ff-b20a6615b8b5\n */\nexport const DISABLE_USER_AGENT_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_USER_AGENT_1326744');\n\n/**\n * Used to enable new viewability tracker implementation\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_NEW_VIEWABILITY_TRACKER_1354300\n */\nexport const NEW_VIEWABILITY_TRACKER_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_NEW_VIEWABILITY_TRACKER_1354300');\n\n/**\n * Used to enable LightFrames on all eligible placement\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_ADS_EVERYWHERE_1362485\n */\nexport const LIGHT_ADS_EVERYWHERE_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_ADS_EVERYWHERE_1362485');\n\n/**\n * Used to disable window.top\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_POSTMESSAGE_1327371\n */\nexport const DISABLE_POSTMESSAGE_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_POSTMESSAGE_1327371');\n\n/**\n * Compares per-placement Light Ad assets with page-level loading at window load and at the first Light Ad placement.\n * @link https://app.weblab.amazon.dev/setup/APM_STORES_PAGE_LEVEL_LIGHT_AD_JS_1418728\n */\nexport const PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME = 'APM_STORES_PAGE_LEVEL_LIGHT_AD_JS_1418728';\nexport const PAGE_LEVEL_LIGHT_AD_JS_WEBLAB = () => createWeblab(window, PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME);\n\n/**\n * Collapses a Light Ad slot when Light Ad init fails, for example when the placement div is missing.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_AD_INIT_FAILURE_COLLAPSE_1483332\n */\nexport const LIGHT_AD_INIT_FAILURE_COLLAPSE_WEBLAB_NAME =\n    'APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_AD_INIT_FAILURE_COLLAPSE_1483332';\nexport const LIGHT_AD_INIT_FAILURE_COLLAPSE_WEBLAB = () =>\n    createWeblab(window, LIGHT_AD_INIT_FAILURE_COLLAPSE_WEBLAB_NAME);\n\n/**\n * Reuses the last known placement or iframe node when the page detaches it, for example the Events deals grid.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_DETACHED_PLACEMENT_REUSE_1483333\n */\nexport const DETACHED_PLACEMENT_REUSE_WEBLAB_NAME = 'APM_STORES_JPS_JRS_SAFEFRAME_DETACHED_PLACEMENT_REUSE_1483333';\nexport const DETACHED_PLACEMENT_REUSE_WEBLAB = () => createWeblab(window, DETACHED_PLACEMENT_REUSE_WEBLAB_NAME);\n","import { emitCsaMetric } from '@amzn/grandprix-runtime/src/instrumentation/csa/metrics.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emittedMetrics } from '@/components/state/page/pageState.js';\nimport { PAGE_LEVEL_LIGHT_AD_JS_WEBLAB, PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME } from '@/components/weblabs.js';\n\ntype LifecycleMetricName = 'event:start' | 'event:prewrite' | 'event:postwrite' | 'event:btr' | 'event:load';\ntype CoordinateMetricName = 'coordinate:x' | 'coordinate:y';\nexport type PixelMetricName =\n    | 'pixel:imp:cod'\n    | 'pixel:imp:cod:single-video-ads'\n    | 'pixel:imp:cod:video'\n    | 'pixel:imp:cod:display'\n    | 'pixel:imp:btr'\n    | 'pixel:imp:btr:unknown'\n    | 'pixel:imp:btr:missing'\n    | 'pixel:imp:3p'\n    | 'pixel:imp:atf'\n    | 'pixel:view:iab'\n    | 'pixel:view:iab:video'\n    | 'pixel:view:iab:display'\n    | 'pixel:imp:skan'\n    | 'pixel:view:skan';\nexport type PixelErrorMetricName = `${PixelMetricName}:error`;\nexport type LightAdTimingMetricName = 'lightad:init:timing' | `${PixelMetricName}:timing`;\ntype MobileApiMetricName =\n    | 'sf:mobileapi:getPlacementInfo'\n    | 'sf:mobileapi:getUserAgentInfo'\n    | 'sf:mobileapi:getDocumentCookie'\n    | 'sf:mobileapi:getUserConnectionInfo';\n\ntype MashHandlerMetricName =\n    | 'sf:mash:openInApp3pBrowser'\n    | 'sf:mash:openInApp3pBrowser:success'\n    | 'sf:mash:openInApp3pBrowser:fail'\n    | 'sf:mash:openInExternalBrowser'\n    | 'sf:mash:showEmbeddedBrowser'\n    | 'sf:mash:isAUIAvailable';\nexport type CollapseMetricCode = 'creative' | 'client-setup' | 'host-setup' | 'client-error' | 'light-ad-init';\ntype CollapseMetricName = `placement:collapse:${CollapseMetricCode}` | 'placement:collapse';\n/**\n * Metric names emitted automatically by `bindReceiver` for every bridge call.\n * Csm and Csa are excluded since they are metric/logging channels themselves.\n *\n * If you add a method to a bridge interface, you MUST add the corresponding\n * metric name here — the test in bridgeMetricNames.test.ts will fail otherwise.\n */\nexport const BRIDGE_METRIC_NAMES = [\n    'sf:bridge:Video:updatePlayingTimeForVideo',\n    'sf:bridge:Video:requestVideoAutoplay',\n    'sf:bridge:Video:releaseVideoAutoplay',\n    'sf:bridge:Video:haveVideoAutoplayPermission',\n    'sf:bridge:Events:onSafeFrameReady',\n    'sf:bridge:Events:onPreCreativeWrite',\n    'sf:bridge:Events:onPostCreativeWrite',\n    'sf:bridge:Events:onCreativeBeginToRender',\n    'sf:bridge:Events:onCreativeLoad',\n    'sf:bridge:Events:onError',\n    'sf:bridge:Events:onClick',\n    'sf:bridge:SFClient:changeSize',\n    'sf:bridge:SFClient:collapseSlot',\n    'sf:bridge:SFClient:signalAdLoadedAndInteractive',\n    'sf:bridge:SFClient:feedbackLabelRendered',\n    'sf:bridge:SFClient:feedbackOpenModal',\n    'sf:bridge:SFClient:isOnAmazon',\n    'sf:bridge:CustomMessage:dispatch',\n    'sf:bridge:SafeFrameExt:populateSafeFrameExt',\n    'sf:bridge:SafeFrameExt:populateGeom',\n    'sf:bridge:Mash:openInApp3pBrowser',\n    'sf:bridge:Mash:openInApp3pBrowserReply',\n    'sf:bridge:MSFClient:onPageEvent',\n    'sf:bridge:MSFClient:onPageEventReply',\n    'sf:bridge:MSFClient:renderClickThroughAppAds',\n] as const;\nexport type BridgeMetricName = (typeof BRIDGE_METRIC_NAMES)[number];\n\n/** Client-local API metrics (not bridge calls, emitted directly by the client). */\ntype CustomMessageApiMetricName = 'sf:bridge:CustomMessage:registerCustomMessageListener';\n\ntype BlankAdMetricName = 'blank:ad:validation' | 'blank:ad:validation:error';\nexport type ObstructionMetricName = 'viewpixel:iab:obstruction' | 'viewpixel:iab:obstruction:recovered';\ntype DiagnosticMetricName =\n    | 'html:element:missing:placement'\n    | 'html:element:missing:iframe'\n    | 'html:element:detached:placement'\n    | 'html:element:detached:iframe'\n    | 'asset:load:timing'\n    | 'intersection:observer:invalid:target'\n    | 'reporting-observer:heavy-ad-intervention'\n    | 'sf:useragent:access'\n    | 'sf:host:port:rebind';\ntype ShepherdMetricName = 'shepherd:postmessage:parent';\ntype FeedbackMetricName = 'gpat:sponsored:label:rendered';\nexport type VideoMilestoneMetricName =\n    | 'lightad:video:canplay:duration'\n    | 'lightad:video:canplaythrough:duration'\n    | 'lightad:video:playing:duration';\ntype VideoMetricName =\n    | VideoMilestoneMetricName\n    | 'lightad:video:attach:duration'\n    | 'lightad:video:buffer:count'\n    | 'lightad:video:buffer:duration'\n    | 'lightad:video:prerender';\nexport type MetricName =\n    | LifecycleMetricName\n    | CoordinateMetricName\n    | PixelMetricName\n    | PixelErrorMetricName\n    | MobileApiMetricName\n    | MashHandlerMetricName\n    | CollapseMetricName\n    | BridgeMetricName\n    | CustomMessageApiMetricName\n    | BlankAdMetricName\n    | ObstructionMetricName\n    | DiagnosticMetricName\n    | ShepherdMetricName\n    | FeedbackMetricName\n    | VideoMetricName;\n\ninterface EmitPlacementMetricParams {\n    metricName: MetricName;\n    metricValue?: number;\n    adDetails: AdDetails | LightAdDetails;\n    timestamp?: Date;\n}\n\ninterface EmitMetricParams extends EmitPlacementMetricParams {\n    /** Low-cardinality dimensions to add without replacing canonical placement context. */\n    additionalDimensions?: Record<string, string>;\n    /** When set, emit at most once per metric and deduplication key on the page. */\n    deduplicationKey?: string;\n}\n\nexport const emitMetric = ({\n    metricName,\n    metricValue = 1,\n    adDetails: { logCxt },\n    timestamp,\n    additionalDimensions,\n    deduplicationKey,\n}: EmitMetricParams): void => {\n    if (deduplicationKey !== undefined) {\n        const key = `${metricName}:${deduplicationKey}`;\n        if (emittedMetrics.has(key)) return;\n        emittedMetrics.mark(key);\n    }\n\n    emitCsaMetric({\n        metricName,\n        metricValue,\n        timestamp,\n        dimensions: { ...additionalDimensions, ...logCxt },\n    });\n};\n\nexport const emitMetricOnce = (params: EmitPlacementMetricParams): void => {\n    if (emittedMetrics.has(params.metricName)) return;\n    emittedMetrics.mark(params.metricName);\n    emitMetric(params);\n};\n\nconst WEBLAB_METRIC_NAME = 'session:weblabs';\n\nconst emitWeblabMetricOnce = (adDetails: AdDetails | LightAdDetails): void => {\n    if (emittedMetrics.has(WEBLAB_METRIC_NAME)) return;\n    emittedMetrics.mark(WEBLAB_METRIC_NAME);\n\n    emitCsaMetric({\n        metricName: WEBLAB_METRIC_NAME,\n        metricValue: 1,\n        dimensions: { requestId: adDetails.logCxt.requestId },\n        weblabs: window.renderingWeblabs ?? {},\n    });\n};\n\nexport const emitWeblabMetric = (adDetails: AdDetails | LightAdDetails): void => {\n    emitWeblabMetricOnce(adDetails);\n};\n\ninterface EmitLightAdTimingMetricParams {\n    metricName: LightAdTimingMetricName;\n    metricValue: number;\n    adDetails: AdDetails | LightAdDetails;\n}\n\n/**\n * Emits milliseconds since time origin for Light Ad events.\n *\n * The metric is emitted only for page-level asset Weblab traffic, with its treatment attached to\n * the same event for direct Athena segmentation without a session-event join.\n */\nexport const emitLightAdTimingMetric = ({\n    metricName,\n    metricValue,\n    adDetails: { logCxt },\n}: EmitLightAdTimingMetricParams): void => {\n    const pageLevelWeblab = PAGE_LEVEL_LIGHT_AD_JS_WEBLAB();\n    if (logCxt.app !== 'LA' || !pageLevelWeblab.isAssigned()) return;\n\n    emitCsaMetric({\n        metricName,\n        metricValue,\n        dimensions: { ...logCxt },\n        weblabs: {\n            [PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME]: pageLevelWeblab.getTreatment().toUpperCase(),\n        },\n    });\n};\n","import { logCsaEvent, LOGS_SOURCE_GROUP } from './core.js';\n\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info';\n\nexport type CsaLogInput = {\n    level: LogLevel;\n    message: string;\n    errorType?: string;\n    stack?: string;\n    code?: string;\n    source?: string;\n    lineno?: number;\n    colno?: number;\n    timestamp?: Date;\n    dimensions: Record<string, string>;\n};\n\n/**\n * Emits a structured log event to the CSA logs source group (our logs pipeline →\n * CloudWatch Logs, searched via Logs Insights). Not routed to Nexus.\n *\n * The event also carries metric fields (`metricName: log:level:${level}`, `metricValue: 1`)\n * so this single emission can be sliced and counted as a metric downstream by the CSA metrics\n * Lambda (for error/fatal alarming) without the client emitting twice — Sushi fans the logs\n * source group out to both the logs and metrics sinks.\n *\n * @param level - Severity: fatal | error | warn | info. Also forms the metricName.\n * @param message - Log message.\n * @param errorType - Error class name, when derived from an Error.\n * @param stack - Error stack, when available.\n * @param code - Error code, when available.\n * @param source - Source file or module where the error originated.\n * @param lineno - Line number where the error occurred.\n * @param colno - Column number where the error occurred.\n * @param timestamp - When the log was recorded. Defaults to now.\n * @param dimensions - Key-value log dimensions; also the metric dimensions for slicing.\n */\nexport const emitCsaLog = ({\n    level,\n    message,\n    errorType,\n    stack,\n    code,\n    source,\n    lineno,\n    colno,\n    timestamp = new Date(),\n    dimensions,\n}: CsaLogInput): void =>\n    logCsaEvent({\n        sushiSourceGroup: LOGS_SOURCE_GROUP,\n        data: {\n            metricName: `log:level:${level}`,\n            metricValue: 1,\n            level,\n            errorType,\n            message,\n            stack,\n            code,\n            source,\n            lineno,\n            colno,\n            timestamp: timestamp.getTime(),\n            dimensions,\n        },\n    });\n","import { emitCsaLog } from '@amzn/grandprix-runtime/src/instrumentation/csa/logging.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\n// At least one of `message` or `error` must be provided.\ntype LogWithMessage = { message: string; error?: unknown };\ntype LogWithError = { message?: string; error: unknown };\ntype EmitErrorLogParams = {\n    adDetails: AdDetails | LightAdDetails;\n    code?: string;\n    source?: string;\n    lineno?: number;\n    colno?: number;\n} & (LogWithMessage | LogWithError);\n\n/**\n * Emits a structured client error log to the CSA logs source group (→ our logs pipeline →\n * CloudWatch Logs, searched via Logs Insights) for search and triage. The level is always\n * `error`. When an Error is provided, errorType/message/stack are derived from it.\n *\n * Only the log is emitted here — the client sends each event exactly once. Counts for alarming\n * (error/fatal volume) are derived downstream from the logs, not emitted by the client.\n *\n * @param input.message - Log message. Optional only when an Error is provided.\n * @param input.error - The caught value; normalized to an Error, from which errorType/message/stack\n *                      are derived. Accepts a non-Error throw so callers can pass what they caught.\n * @param input.adDetails - Ad context; logCxt becomes the log dimensions.\n * @param input.code - Error phase: 'client-setup' (during creative init) or 'client-error' (runtime).\n * @param input.source - Script URL or filename where the error occurred (from window.onerror).\n * @param input.lineno - Line number where the error occurred (from window.onerror).\n * @param input.colno - Column number where the error occurred (from window.onerror).\n */\nexport const emitErrorLog = ({ message, error, adDetails, code, source, lineno, colno }: EmitErrorLogParams): void => {\n    const err = toError(error);\n    emitCsaLog({\n        level: 'error',\n        errorType: err?.name,\n        message: message ?? err?.message ?? '',\n        stack: err?.stack,\n        code,\n        source,\n        lineno,\n        colno,\n        dimensions: { ...adDetails.logCxt },\n    });\n};\n\n/**\n * Normalizes a caught value into an Error. `undefined` stays `undefined`, so a message-only log emits\n * no errorType or stack. A non-Error object is JSON-serialized into the message so its properties\n * (e.g. a MashError's `code`) are not lost to `String()`'s \"[object Object]\"; anything else, and any\n * object JSON cannot serialize (circular refs), falls back to `String()`.\n */\nconst toError = (error: unknown): Error | undefined => {\n    if (error === undefined) return undefined;\n    if (error instanceof Error) return error;\n    if (typeof error === 'object') {\n        try {\n            return new Error(JSON.stringify(error));\n        } catch {\n            // Circular refs; fall through to String().\n        }\n    }\n    return new Error(String(error));\n};\n","/**\n * Type guard that checks whether `obj` is a non-null object with an own\n * property named `key`. Prevents accidental traversal into prototype\n * properties when walking dynamic paths.\n *\n * Note: `obj != null` is intentionally a loose equality check — it is\n * the idiomatic shorthand for `obj !== null && obj !== undefined`.\n */\nexport const hasOwn = (obj: unknown, key: string): obj is Record<string, unknown> =>\n    obj != null && typeof obj === 'object' && Object.prototype.hasOwnProperty.call(obj, key);\n","import type { BridgeMessage, BridgeRegistry, Context } from '@/components/bridge/core/bridge.js';\nimport { emitMetricOnce } from '@/components/metrics/csaMetrics.js';\nimport type { MetricName } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { hasOwn } from '@/components/utils/hasOwn.js';\nimport type { IsFunction } from '@/components/utils/isFunction.js';\n\n/** Namespaces that are metric/logging channels and should not emit bridge metrics. */\nconst METRIC_EXEMPT_NAMESPACES_LIST = ['Csa', 'Csm'] as const satisfies readonly (keyof BridgeRegistry)[];\nexport type MetricExemptNamespace = (typeof METRIC_EXEMPT_NAMESPACES_LIST)[number];\nconst METRIC_EXEMPT_NAMESPACES: ReadonlySet<keyof BridgeRegistry> = new Set(METRIC_EXEMPT_NAMESPACES_LIST);\n\n/**\n * Transforms a bridge interface into its host-side implementation by\n * prepending a {@link Context} parameter to every method. This gives\n * each handler access to the ad identity and timing metadata sent by\n * the client iframe.\n *\n * - Functions `(...args) => R` become `(ctx: Context, ...args) => R`.\n * - Plain object branches (e.g. `ue: { count }`) are recursed into.\n * - Non-function, non-object leaves become `never` (compile-time guard).\n *\n * @typeParam T - The bridge interface to transform (e.g. `CsmBridge`).\n *\n * @example\n * ```ts\n * // CsmBridge.ue.count(metric, n?) becomes:\n * // ReceiverImpl<CsmBridge>.ue.count(ctx, metric, n?)\n * ```\n */\nexport type ReceiverImpl<T> = {\n    [K in keyof T]: IsFunction<T[K]> extends true\n        ? T[K] extends (...args: infer A) => infer R\n            ? (ctx: Context, ...args: A) => R\n            : never\n        : T[K] extends object\n          ? ReceiverImpl<T[K]>\n          : never;\n};\n\n/** The shape of a resolved host handler after dot-path lookup. */\ntype Handler = (ctx: Context, ...args: unknown[]) => unknown;\n\n/**\n * Resolves a dot-notation path (e.g. `'ue.count'`) to the handler\n * function inside a {@link ReceiverImpl} tree. Returns `undefined` if any\n * segment is missing, so unknown methods are silently ignored.\n */\nconst resolveMethod = (root: unknown, path: string): unknown =>\n    path.split('.').reduce<unknown>((obj, key) => (hasOwn(obj, key) ? obj[key] : undefined), root);\n\n/**\n * Listens on a {@link MessagePort} shared with the SafeFrame client\n * iframe and routes incoming messages to the matching handler in\n * {@link impl}.\n *\n * Multiple bridges (CSM, Events, etc.) share the same port. The\n * namespace guard ensures each listener only processes messages\n * addressed to its bridge, while dot-notation resolution maps\n * paths like `'ue.count'` to nested handler functions.\n *\n * @typeParam Namespace - A key of {@link BridgeRegistry} identifying the bridge.\n * @param port      - The {@link MessagePort} connected to the client iframe.\n * @param namespace - Bridge namespace key (e.g. `'Csm'`).\n * @param impl - Host-side handler tree produced by {@link ReceiverImpl}.\n *\n * @example\n * ```ts\n * bindReceiver(port, 'Csm', createCsmBridgeReceiver());\n * ```\n */\nexport const bindReceiver = <Namespace extends keyof BridgeRegistry>(\n    port: MessagePort,\n    namespace: Namespace,\n    impl: ReceiverImpl<BridgeRegistry[Namespace]>,\n): void => {\n    port.addEventListener('message', async ({ data }: MessageEvent<BridgeMessage<BridgeRegistry[Namespace]>>) => {\n        if (data?.namespace !== namespace) return;\n        try {\n            const fn = resolveMethod(impl, data.method as string);\n            if (typeof fn === 'function') {\n                const ctx: Context = { ...data.context, messagePort: port };\n                if (!METRIC_EXEMPT_NAMESPACES.has(namespace)) {\n                    emitMetricOnce({\n                        metricName: `sf:bridge:${namespace}:${data.method}` as MetricName,\n                        metricValue: 1,\n                        adDetails: ctx.adDetails,\n                    });\n                }\n                await (fn as Handler)(ctx, ...data.args);\n            }\n        } catch (e) {\n            emitErrorLog({\n                message: `Bridge error in ${namespace}.${data.method}`,\n                error: e,\n                adDetails: data.context.adDetails,\n            });\n        }\n    });\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { WireContext } from '@/components/bridge/core/bridge.js';\n\n/** Builds the per-message context factory used by bridge senders. */\nexport const contextFactory =\n    (adDetails: AdDetails): (() => WireContext) =>\n    () => ({ adDetails, timestamp: new Date() });\n\n/** No-op callable target for the Proxy. Exported for test coverage (the Proxy's apply trap intercepts all calls). */\nexport const proxyTarget = (): void => {};\n\n/**\n * Recursively builds a {@link Proxy} that accumulates a dot-notation path.\n *\n * This enables nested bridge interfaces like `ue.count` — accessing\n * `proxy.ue` returns a deeper proxy, and calling `proxy.ue.count(...)`\n * sends method `'ue.count'` with the provided arguments.\n */\nexport const buildProxy = (send: (...args: any[]) => void, prefix: string): unknown =>\n    new Proxy(proxyTarget, {\n        apply(_target, _thisArg, args: unknown[]) {\n            send(prefix, ...args);\n        },\n        get(_target, prop: string | symbol) {\n            if (typeof prop === 'symbol' || prop === 'then') return undefined;\n            const path = prefix ? `${prefix}.${prop}` : prop;\n            return buildProxy(send, path);\n        },\n    });\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { BridgeRegistry } from '@/components/bridge/core/bridge.js';\nimport { buildProxy, contextFactory } from '@/components/bridge/core/wire.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport type { ArgsForPath } from '@/components/utils/argsForPath.js';\nimport type { NestedKeyOf } from '@/components/utils/nestedKeyOf.js';\n\n/**\n * Internal sender type that enforces compile-time checking on method\n * names and arguments before they cross the iframe→host boundary.\n */\ntype SendFn<T> = <M extends NestedKeyOf<T>>(method: M, ...args: ArgsForPath<T, M>) => void;\n\n/**\n * Creates a sender bound to a bridge on the given {@link MessagePort}.\n *\n * Each call captures a fresh {@link Context} (ad identity + timestamp)\n * and posts it to the host page. Errors are\n * logged rather than thrown so a failed metric or event never crashes\n * the ad creative.\n */\nconst sendMessage = <Namespace extends keyof BridgeRegistry>(\n    port: MessagePort,\n    namespace: Namespace,\n    adDetails: AdDetails,\n): SendFn<BridgeRegistry[Namespace]> => {\n    const getContext = contextFactory(adDetails);\n    return ((method: string, ...args: unknown[]): void => {\n        try {\n            port.postMessage({ namespace, method, args, context: getContext() });\n        } catch (e) {\n            emitErrorLog({ message: `Bridge send error in ${namespace}.${method}`, error: e, adDetails });\n        }\n    }) as SendFn<BridgeRegistry[Namespace]>;\n};\n\n/**\n * Creates a client-side proxy for a registered bridge that the SafeFrame\n * iframe uses to communicate with the host page.\n *\n * The proxy automatically builds dot-notation method paths (e.g.\n * `csm.ue.count(...)` becomes method `'ue.count'`), so adding methods\n * to a bridge interface requires zero client-side boilerplate.\n *\n * @typeParam Namespace - A key of {@link BridgeRegistry} identifying the bridge.\n * @param port      - The {@link MessagePort} connected to the host page.\n * @param namespace - Bridge namespace key (e.g. `'Csm'`).\n * @param adDetails - Full ad slot context embedded in every outgoing message.\n * @returns An object matching the bridge interface whose methods post\n *          messages over the port.\n *\n * @example\n * ```ts\n * const csm = createSender(port, 'Csm', adDetails);\n * csm.ueLogError(error, info);   // type-checked\n * csm.ue.count('myMetric', 1);   // nested path handled automatically\n * ```\n */\nexport const createSender = <Namespace extends keyof BridgeRegistry>(\n    port: MessagePort,\n    namespace: Namespace,\n    adDetails: AdDetails,\n): BridgeRegistry[Namespace] => {\n    const send = sendMessage(port, namespace, adDetails);\n    return buildProxy(send as (...args: any[]) => void, '') as BridgeRegistry[Namespace];\n};\n","import type { Context } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { CsaBridge, CsaNamespace, CsaOptions } from '@/components/bridge/csa/csaBridge.js';\n\nexport const createCsaBridgeReceiver = (): ReceiverImpl<CsaBridge> => ({\n    csa: (\n        _ctx: Context,\n        csaNamespace: CsaNamespace,\n        options: CsaOptions,\n        method: string,\n        data: Record<string, unknown>,\n    ) => window.csa?.(csaNamespace, options)?.(method, data),\n});\n","import type { Context } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { AdditionalInfo, CsmBridge } from '@/components/bridge/csm/csmBridge.js';\n\nexport const createCsmBridgeReceiver = (): ReceiverImpl<CsmBridge> => ({\n    ueLogError: (_ctx: Context, error: Error, additionalInfo: AdditionalInfo) =>\n        window.ueLogError?.(error, additionalInfo),\n    ue: {\n        count: (_ctx: Context, metric: string, count?: number) => window.ue?.count?.(metric, count),\n    },\n});\n","import type { CsaLatencyMarker } from './window.js';\n\n/**\n * Records a CSA Content Latency marker for a placement element.\n * Timestamps are epoch-based (`Date.now()`), not `performance.now()`.\n * No-ops if CSA is unavailable.\n *\n * @param element - The placement DOM element to record latency for.\n * @param marker - The well-known latency marker name to record.\n * @param timestamp - Optional absolute timestamp. Defaults to now if omitted.\n *\n * @see {@link https://w.amazon.com/bin/view/ClientSideMetrics/UserDocs/CSA/Plugins/ContentInstrumentation/ContentLatency/}\n */\nexport const sendCsaLatencyMetric = (element: HTMLElement, marker: CsaLatencyMarker, timestamp?: Date): void => {\n    window.csa?.('Content', { element })('mark', marker, timestamp?.getTime());\n};\n","type UetLatencyEvent = 'bb' | 'be' | 'af' | 'cf';\ntype UexLatencyEvent = 'ld';\n\n/**\n * CSM widget latency marker events.\n *\n * Markers are recorded via `uet()` (timing) or `uex()` (timing + send).\n * All markers require a scope name and `{wb: 1}` flag.\n * Timestamps are epoch-based (`Date.now()`), not `performance.now()`.\n *\n * @remarks\n * **Firing order:**\n *\n * There is no enforced ordering between `bb`, `be`, `af`, and `cf` —\n * they simply record timestamps. However, the conventional order\n * that aligns with their semantic meaning is:\n *\n *\n\n * bb → af → cf → be → ld\n * │    │    │    │    └─ Must be last. Triggers postback.\n * │    │    │    └────── Widget HTML finished rendering\n * │    │    └─────────── Critical/useful content ready\n * │    └──────────────── Visible portion rendered\n * └───────────────────── Widget starts rendering\n *\n\n *\n * Only `bb` and `ld` are needed for minimal instrumentation.\n * Use `af`, `cf`, `be` when you need finer-grained breakdown.\n *\n * **Hard rules:**\n * 1. `'ld'` must always be the last marker fired — it sends all\n *    collected timestamps to the server.\n * 2. Every scope that logs `'bb'` must also log `'ld'`, or metrics\n *    for **all** widgets on the page will be blocked.\n *\n * - `'bb'` — Body Begin: Fire when your widget starts rendering.\n * - `'af'` — Above The Fold: Fire when the visible portion of your widget has rendered.\n * - `'cf'` — Critical Feature: Fire when the main/useful content of your widget has rendered.\n * - `'be'` — Body End: Fire when your widget's HTML finishes rendering.\n * - `'ld'` — Loaded (required): Fire when your widget is fully loaded.\n *   Triggers the postback to send all widget metrics to the server.\n *\n * @see {@link https://w.amazon.com/bin/view/ClientSideMetrics/UserDocs/Instrumentation/InstrumentingWidgets}\n */\nexport type LatencyEvent = UetLatencyEvent | UexLatencyEvent;\n\ndeclare global {\n    // https://code.amazon.com/packages/ClickstreamBrowserDataJavaScript/blobs/mainline/--/javascript/head-open.js\n    interface Window {\n        /** Records a timing marker for a given scope. Timestamp is epoch-based (`Date.now()`). */\n        uet?(\n            eventName: UetLatencyEvent,\n            scope?: string,\n            scopeOptions?: Record<string, unknown>,\n            timeOverride?: number,\n        ): void;\n        /** Records a timing marker and sends the postback to the server. */\n        uex?(\n            eventName: UexLatencyEvent,\n            scope?: string,\n            scopeOptions?: Record<string, unknown>,\n            timeOverride?: number,\n        ): void;\n    }\n}\n\nexport interface Placement {\n    id: string;\n    name: string;\n}\n\n/** Parameters for emitting a CSM widget latency metric. */\nexport interface LatencyMetric {\n    /** The latency marker to record. */\n    latencyEvent: LatencyEvent;\n    /** Optional key to further qualify the metric scope (e.g. `'SafeFrame'` or `'LightAd'`). */\n    scope?: string;\n    /** The ad placement to emit metrics for. */\n    placement: Placement;\n    /** Absolute timestamp to record. Defaults to now. Must be epoch-compatible (`Date`). */\n    timestamp?: Date;\n}\n\nconst csmName = (name: string) => name.replace(/_/g, ':');\n\n/**\n * Emits a single CSM widget latency marker for a given scope.\n * Routes to `uet()` for timing markers or `uex()` for `'ld'` (which triggers the server postback).\n * No-ops if the required window function is unavailable.\n */\nconst emitLatency = (event: LatencyEvent, scope: string, time: number): void => {\n    if (event === 'ld') window.uex?.(event, scope, { wb: 1 }, time);\n    else window.uet?.(event, scope, { wb: 1 }, time);\n};\n\n/**\n * Emits CSM latency metrics for an ad placement, keyed by both placement ID and name.\n * Each call produces two scoped metrics to allow lookup by either identifier.\n * Uses a consistent timestamp across both scopes to ensure aligned measurements.\n *\n * Metrics are published to PMET under `scope:adplacements:<scope?>:<placement>:<metricName>`.\n *\n * @example\n * ```ts\n * sendCsmLatencyMetric({ latencyEvent: 'bb', placement, scope: 'SF' });\n * // ... ad renders ...\n * sendCsmLatencyMetric({ latencyEvent: 'ld', placement, scope: 'LA' });\n *\n */\nexport const sendCsmLatencyMetric = ({ latencyEvent, scope, placement, timestamp }: LatencyMetric): void => {\n    const prefix = `adplacements:${scope ? `${csmName(scope)}:` : ''}`;\n    const time = timestamp?.getTime() ?? Date.now();\n\n    emitLatency(latencyEvent, prefix + placement.id, time);\n    emitLatency(latencyEvent, prefix + csmName(placement.name), time);\n};\n","import type { AdDetails, App, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { sendCsaLatencyMetric } from './csa/latency.js';\nimport type { CsaLatencyMarker } from './csa/window.js';\nimport type { LatencyEvent, Placement } from './csm/latency.js';\nimport { sendCsmLatencyMetric } from './csm/latency.js';\n\nexport interface AdLatencyMetric {\n    adDetails: AdDetails | LightAdDetails;\n    latencyEvent: LatencyEvent;\n    scope: App;\n    timestamp?: Date;\n}\n\nconst csaEvents: Partial<Record<LatencyEvent, CsaLatencyMarker[]>> = {\n    bb: ['t0', 'bodyBegin'],\n    af: ['aboveTheFold'],\n    cf: ['criticalFeature', 'functional'],\n    ld: ['loaded', 'feat_vl100'],\n};\n\nexport const sendLatencyMetric = ({ adDetails, latencyEvent, scope, timestamp }: AdLatencyMetric): void => {\n    const element = document.getElementById(adDetails.adUnitPlacementId) as HTMLElement;\n    const placement: Placement = { id: adDetails.placementId, name: adDetails.placementName };\n\n    sendCsmLatencyMetric({ latencyEvent, placement, scope, timestamp });\n    csaEvents[latencyEvent]?.forEach((marker) => sendCsaLatencyMetric(element, marker, timestamp));\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { DETACHED_PLACEMENT_REUSE_WEBLAB } from '@/components/weblabs.js';\n\n/** Any ad identity accepted by these DOM utilities. */\ntype AnyAdDetails = AdDetails | LightAdDetails;\n\nexport type PlacementLookupSource =\n    | 'safe-frame-ready'\n    | 'pre-creative-write'\n    | 'creative-btr'\n    | 'creative-load'\n    | 'click'\n    | 'collapse'\n    | 'video'\n    | 'change-size'\n    | 'msf-page-event'\n    | 'light-ad';\n\ninterface PlacementLookupOptions {\n    lookupSource: PlacementLookupSource;\n    adUnitPlacementId?: string;\n}\n\nconst isSafeFrame = (adDetails: AnyAdDetails): adDetails is AdDetails => 'adUnitIframeId' in adDetails;\n\nconst getPageAgeBucket = (pageAgeMs: number): string => {\n    if (pageAgeMs < 1_000) return 'lt-1s';\n    if (pageAgeMs < 10_000) return '1s-10s';\n    if (pageAgeMs < 60_000) return '10s-1m';\n    if (pageAgeMs < 300_000) return '1m-5m';\n    return 'gte-5m';\n};\n\nexport const getWrapper = (adDetails: AnyAdDetails): HTMLElement | null => {\n    if (isSafeFrame(adDetails)) {\n        return adDetails.adUnitWrapperId ? document.getElementById(adDetails.adUnitWrapperId) : null;\n    }\n\n    return document.getElementById(adDetails.adUnitPlacementId)?.parentElement ?? null;\n};\n\n// The last node seen per id. A page can move the node out of the document and back (Events grid).\n// ponytail: holds removed nodes until page unload; bounded by the ads on one page.\nconst knownPlacements = new Map<string, HTMLDivElement>();\n\nexport const getPlacement = (\n    adDetails: AnyAdDetails,\n    { lookupSource, adUnitPlacementId = adDetails.adUnitPlacementId }: PlacementLookupOptions,\n): HTMLDivElement => {\n    const placement = document.getElementById(adUnitPlacementId) as HTMLDivElement | null;\n    if (placement) {\n        knownPlacements.set(adUnitPlacementId, placement);\n        return placement;\n    }\n\n    const known = knownPlacements.get(adUnitPlacementId);\n    emitMetric({\n        metricName: known ? 'html:element:detached:placement' : 'html:element:missing:placement',\n        adDetails,\n        additionalDimensions: {\n            abpAcceptable: adDetails.abpAcceptable,\n            abpStatus: adDetails.abpStatus ?? '-1',\n            lookupSource,\n            pageAgeBucket: getPageAgeBucket(performance.now()),\n        },\n        deduplicationKey: adDetails.placementId,\n    });\n\n    return (DETACHED_PLACEMENT_REUSE_WEBLAB().is('t1') ? known : null) as HTMLDivElement;\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { getPlacement } from '@/host/components/placement.js';\n\n/**\n * Dispatches a synthetic click event on the placement div so that CSA can attribute the click to this ad placement.\n * CSA relies on DOM click events bubbling through elements to record clicks. Since the real user click happens inside a cross-domain iframe, CSA cannot observe it. This bridged dispatch should make it visible on the host page.\n */\nexport const dispatchClickForCsaAttribution = (adDetails: AdDetails): void => {\n    getPlacement(adDetails, { lookupSource: 'click' })?.dispatchEvent(\n        new MouseEvent('click', {\n            bubbles: true,\n            cancelable: true,\n        }),\n    );\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\n/**\n * When a creative supports TTI (Time To Interactive) measurement, it calls\n * `SFClient.signalAdLoadedAndInteractive()` itself, which is the sole source of `cf` and `ld` metrics.\n * SafeFrame must not fire these metrics to avoid double-counting.\n */\nexport const shouldSafeFrameFireLoadedMetrics = (\n    adDetails: Pick<AdDetails, 'creativeSupportsTTIMeasurement'>,\n): boolean => !adDetails.creativeSupportsTTIMeasurement;\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { createSender } from '@/components/bridge/core/sender.js';\nimport type { SafeFrameExtBridge } from '@/components/bridge/safeFrameExt/safeFrameExtBridge.js';\n\n/** Host-side sender for the SafeFrameExt namespace (host → client geometry pushes). */\nexport const createSafeFrameExtBridgeSender = (mp: MessagePort, adDetails: AdDetails): SafeFrameExtBridge =>\n    createSender(mp, 'SafeFrameExt', adDetails);\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric, type CollapseMetricCode } from '@/components/metrics/csaMetrics.js';\nimport { collapsedPlacements } from '@/components/state/page/pageState.js';\nimport { getPlacement, getWrapper } from '@/host/components/placement.js';\n\ninterface CollapsePlacementParams {\n    adDetails: AdDetails | LightAdDetails;\n    code?: CollapseMetricCode;\n}\n\nconst hide = (element: HTMLElement | null): void => {\n    if (element) {\n        element.style.display = 'none';\n    }\n};\n\n/**\n * Hides a placement once per page. A placement can be asked to collapse from several directions, so\n * the first request wins and later ones are ignored rather than re-counted.\n */\nexport const collapsePlacement = ({ adDetails, code }: CollapsePlacementParams): void => {\n    if (collapsedPlacements.has(adDetails.adUnitPlacementId)) {\n        return;\n    }\n\n    hide(getWrapper(adDetails));\n    hide(getPlacement(adDetails, { lookupSource: 'collapse' }));\n\n    emitMetric({ metricName: 'placement:collapse', adDetails });\n    if (code) {\n        emitMetric({ metricName: `placement:collapse:${code}`, adDetails });\n    }\n\n    collapsedPlacements.mark(adDetails.adUnitPlacementId);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetricOnce } from '@/components/metrics/csaMetrics.js';\n\nconst ENTRY_NAME_REGEX = /AdPlacementStyleAssets|apePlacements/;\n\nexport const logAssetMetrics = (adDetails: AdDetails): void => {\n    const entries = performance.getEntriesByType('resource');\n    const entry = entries.find((entry) => entry.name.match(ENTRY_NAME_REGEX)?.[0]) as PerformanceResourceTiming;\n\n    if (entry) {\n        emitMetricOnce({\n            metricName: 'asset:load:timing',\n            adDetails,\n        });\n    }\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const logCoordinates = (adDetails: AdDetails | LightAdDetails) => {\n    const div = getPlacement(adDetails, { lookupSource: 'safe-frame-ready' });\n    if (!div) return;\n\n    const { x, y } = div.getBoundingClientRect();\n    emitMetric({ metricName: 'coordinate:x', metricValue: x, adDetails });\n    emitMetric({ metricName: 'coordinate:y', metricValue: y, adDetails });\n};\n","import type { PixelMetricName } from '@/components/metrics/csaMetrics.js';\n\nexport type PixelIdentifier = {\n    readonly testId: string;\n    readonly metricName: PixelMetricName;\n};\n\nexport const BTR_IDENTIFIER: PixelIdentifier = { testId: 'ape_btr_impression', metricName: 'pixel:imp:btr' } as const;\nexport const IMPRESSION_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_impression',\n    metricName: 'pixel:imp:cod',\n} as const;\nexport const MEASURABILITY_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_measurability',\n    metricName: 'pixel:imp:atf',\n} as const;\nexport const IAB_VIEWABILITY_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_viewability_iab',\n    metricName: 'pixel:view:iab',\n} as const;\n","/**\n * Generic WeakMap-based state per placement DOM element.\n * Entries are garbage-collected when the element is removed from the DOM.\n */\nconst placementState = new WeakMap<HTMLElement, Map<string, string>>();\n\nexport const getState = <K extends string = string, V extends string = string>(\n    placementDiv: HTMLElement,\n    key: K,\n): V | undefined => placementState.get(placementDiv)?.get(key) as V | undefined;\n\nexport const setState = <K extends string = string, V extends string = string>(\n    placementDiv: HTMLElement,\n    key: K,\n    value: V,\n): void => {\n    const state = placementState.get(placementDiv);\n    if (state) {\n        state.set(key, value);\n    } else {\n        placementState.set(placementDiv, new Map([[key, value]]));\n    }\n};\n","import type { PixelMetricName } from '@/components/metrics/csaMetrics.js';\nimport { getState, setState } from '@/components/state/placement/placementState.js';\n\n/** Short string values to minimize bundle size (string literals are not minified). */\nconst FIRED = '0';\nconst ERROR = '1';\n\ntype PixelState = typeof FIRED | typeof ERROR;\n\nconst setPixelState = (div: HTMLElement, key: PixelMetricName, value: PixelState) =>\n    setState<PixelMetricName, PixelState>(div, key, value);\n\nexport const hasPixelFired = (div: HTMLElement, key: PixelMetricName): boolean =>\n    getState<PixelMetricName, PixelState>(div, key) === FIRED;\n\nexport const markPixelFired = (div: HTMLElement, key: PixelMetricName): void => setPixelState(div, key, FIRED);\n\nexport const markPixelError = (div: HTMLElement, key: PixelMetricName): void => setPixelState(div, key, ERROR);\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric, emitMetric, type PixelMetricName } from '@/components/metrics/csaMetrics.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport { IMPRESSION_IDENTIFIER, type PixelIdentifier } from '@/components/pixels/pixelIdentifiers.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/state/placement/pixelState.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\n\nconst requestOptions: RequestInit = { keepalive: true, mode: 'no-cors' } as const;\nconst SINGLE_VIDEO_ADS_IMPRESSION_METRIC = 'pixel:imp:cod:single-video-ads';\nconst IMPRESSION_3P_METRIC = 'pixel:imp:3p';\n/** Pixels that also emit a media type counter, keyed by the pixel's own metric name. */\nconst MEDIA_TYPE_METRICS: Partial<Record<PixelMetricName, { video: PixelMetricName; display: PixelMetricName }>> = {\n    'pixel:imp:cod': { video: 'pixel:imp:cod:video', display: 'pixel:imp:cod:display' },\n    'pixel:view:iab': { video: 'pixel:view:iab:video', display: 'pixel:view:iab:display' },\n};\n\n/**\n * TODO: Update/Clean up the Placement type\n * SIM: https://sim.amazon.com/issues/CPP-40575\n */\nexport type Placement = {\n    readonly id: string;\n    readonly name: string;\n    readonly div: HTMLElement;\n    readonly deviceType: string;\n    readonly creative?: Creative;\n};\n\n/** The {@link Placement} for a SafeFrame ad whose pixels measure `div`. */\nexport const toPlacement = (adDetails: AdDetails, div: HTMLElement): Placement => ({\n    id: adDetails.placementId,\n    name: adDetails.placementName,\n    div,\n    deviceType: adDetails.deviceType,\n});\n\nexport class Pixel implements FirePixel {\n    constructor(\n        private readonly url: string,\n        private readonly generatePixelUrl: PixelUrlGenerator,\n        private readonly pixelIdentifier: PixelIdentifier,\n        private readonly adDetails: AdDetails | LightAdDetails,\n        private readonly urls3p: string[] = [],\n    ) {}\n\n    public async fire(placement: Placement): Promise<void> {\n        if (hasPixelFired(placement.div, this.pixelIdentifier.metricName)) return;\n        markPixelFired(placement.div, this.pixelIdentifier.metricName);\n        try {\n            const pixelUrl = this.generatePixelUrl(this.url, placement);\n            const firedAt = performance.now();\n            const request = fetch(pixelUrl, requestOptions);\n            emitLightAdTimingMetric({\n                metricName: `${this.pixelIdentifier.metricName}:timing`,\n                metricValue: firedAt,\n                adDetails: this.adDetails,\n            });\n            await request;\n        } catch (e) {\n            markPixelError(placement.div, this.pixelIdentifier.metricName);\n            emitMetric({ metricName: `${this.pixelIdentifier.metricName}:error`, adDetails: this.adDetails });\n            throw e;\n        }\n        placement.div.appendChild(this.pixel(placement));\n        emitMetric({ metricName: this.pixelIdentifier.metricName, adDetails: this.adDetails });\n        const mediaTypeMetrics = MEDIA_TYPE_METRICS[this.pixelIdentifier.metricName];\n        if (mediaTypeMetrics) {\n            emitMetric({\n                metricName: this.isVideo() ? mediaTypeMetrics.video : mediaTypeMetrics.display,\n                adDetails: this.adDetails,\n            });\n        }\n        if (this.isSingleVideoAdsImpression()) {\n            emitMetric({ metricName: SINGLE_VIDEO_ADS_IMPRESSION_METRIC, adDetails: this.adDetails });\n        }\n\n        // Do not await for 3P URLs as rendering the ad doesn't depend on successful firing\n        this.urls3p.forEach((url3p) =>\n            fetch(url3p, requestOptions).then(\n                () => emitMetric({ metricName: IMPRESSION_3P_METRIC, adDetails: this.adDetails }),\n                () => emitMetric({ metricName: `${IMPRESSION_3P_METRIC}:error`, adDetails: this.adDetails }),\n            ),\n        );\n    }\n\n    /** Light Ads carry a videoCreative when they are video; SafeFrame ads carry an explicit mediaType. */\n    private isVideo = (): boolean =>\n        this.adDetails.logCxt.app === 'LA'\n            ? Boolean((this.adDetails as LightAdDetails).videoCreative)\n            : (this.adDetails as AdDetails).mediaType === 'V';\n\n    /**\n     * Single Video Ads card flow: JRS renders native VAST through the card, which owns the player,\n     * so the Light Ad arrives as a cards-flow video with setupVideoPlayer false.\n     */\n    private isSingleVideoAdsImpression = (): boolean => {\n        if (this.adDetails.logCxt.app !== 'LA') return false;\n\n        const lightAdDetails = this.adDetails as LightAdDetails;\n        return (\n            this.pixelIdentifier.metricName === IMPRESSION_IDENTIFIER.metricName &&\n            lightAdDetails.isCardsFlow === true &&\n            lightAdDetails.videoCreative?.setupVideoPlayer === false\n        );\n    };\n\n    /**\n     * This pixel is used by the UI Tests\n     * No src is set, as the pixel is fired by a fetch\n     */\n    private pixel = (placement: Placement): HTMLImageElement => {\n        const pixel = document.createElement('img');\n        pixel.id = `${this.pixelIdentifier.testId}_${placement.name}`;\n        pixel.style.display = 'none';\n        pixel.setAttribute('pixel-url', this.generatePixelUrl(this.url, placement));\n        return pixel;\n    };\n}\n","/**\n * Measures the amount of the creative which is overlapped by a DOM element.\n * Any part of the creative which is offscreen is considered unobstructed.\n * @param placementElement - The placement HTML element\n * @param placementSafezoneDOMRect - The safezone DOMRect for the placement. Use {@link getPlacementSafezoneDOMRect} to get this value.\n * @returns The percentage of the creative that is obstructed by a DOM element\n */\nexport const getDOMObstructionPercentage = (\n    placementElement: HTMLElement,\n    placementSafezoneDOMRect: DOMRect,\n): number => {\n    const pointsToCheck: [number, number][] = getPointsToCheck(placementSafezoneDOMRect);\n    let obstructedPointsCount = 0;\n\n    // Check each point\n    for (const [x, y] of pointsToCheck) {\n        if (!isCoordinateInViewport(x, y)) continue;\n\n        const elementAtPoint = document.elementFromPoint(x, y);\n        if (elementAtPoint && isElementAtPointObstructing(elementAtPoint, placementElement)) {\n            obstructedPointsCount++;\n        }\n    }\n    return obstructedPointsCount / pointsToCheck.length;\n};\n\nexport const getPointsToCheck = (elementRect: DOMRect): [number, number][] => {\n    const rows = 10;\n    const pointsToCheck: [number, number][] = [];\n    for (let i = 0; i < rows; i++) {\n        pointsToCheck.push([\n            elementRect.left + elementRect.width / 2,\n            elementRect.top + (elementRect.height * (i + 0.5)) / rows,\n        ]);\n    }\n    return pointsToCheck;\n};\n\nexport const isCoordinateInViewport = (x: number, y: number): boolean => {\n    const viewportWidth: number = window.innerWidth || document.documentElement.clientWidth;\n    const viewportHeight: number = window.innerHeight || document.documentElement.clientHeight;\n    return x >= 0 && x <= viewportWidth && y >= 0 && y <= viewportHeight;\n};\n\nexport const isElementAtPointObstructing = (elementAtPoint: Element, creativeElement: HTMLElement): boolean => {\n    if (\n        !(elementAtPoint instanceof HTMLElement) ||\n        elementAtPoint === creativeElement ||\n        creativeElement.contains(elementAtPoint)\n    ) {\n        return false;\n    }\n\n    const computedStyle = window.getComputedStyle(elementAtPoint);\n    if (\n        computedStyle.display === 'none' ||\n        computedStyle.visibility === 'hidden' ||\n        computedStyle.pointerEvents === 'none' ||\n        parseFloat(computedStyle.opacity) < 0.7\n    ) {\n        return false;\n    }\n\n    const backgroundColor = computedStyle.backgroundColor;\n    const regexPattern = /,0\\)$/;\n    const isTransparentBackground =\n        backgroundColor === 'transparent' || regexPattern.test(backgroundColor) || backgroundColor === '';\n    if (isTransparentBackground && !computedStyle.backgroundImage.includes('url')) {\n        return false;\n    }\n    return true;\n};\n","export const calculateObstructionPercentage = (placementRect: DOMRect, overlapRect: DOMRect) => {\n    const xOverlap = Math.max(\n        0,\n        Math.min(placementRect.right, overlapRect.right) - Math.max(placementRect.left, overlapRect.left),\n    );\n\n    const yOverlap = Math.max(\n        0,\n        Math.min(placementRect.bottom, overlapRect.bottom) - Math.max(placementRect.top, overlapRect.top),\n    );\n\n    if (xOverlap === 0 || yOverlap === 0) {\n        return 0;\n    }\n\n    const intersectionArea = xOverlap * yOverlap;\n    const placementDivElementArea = placementRect.width * placementRect.height;\n    return intersectionArea / placementDivElementArea;\n};\n\nexport const convertNativeElementToDomRect = (options: {\n    height: number;\n    top: number;\n    left?: number;\n    width?: number;\n}) => {\n    const { height, top, left = 0, width = windowWidth() } = options;\n    return {\n        top,\n        bottom: top + height,\n        left,\n        right: left + width,\n        width,\n        height,\n    } as DOMRect;\n};\n\nexport const windowWidth = () => {\n    return window.innerWidth || document.documentElement.clientWidth;\n};\n","import { convertNativeElementToDomRect } from './nativeObstructionsUtils.js';\n\nexport const MASH_API_NAME = 'mash';\n\nexport interface BoundingBox {\n    top: number;\n    left: number;\n    height: number;\n    width: number;\n}\n\nexport interface ObstructionsResponse {\n    boundingBoxes: BoundingBox[];\n    isFullyObstructed: boolean;\n}\n\nexport interface getObstructionsResponse {\n    boundingBoxes: DOMRect[];\n    isFullyObstructed: boolean;\n    latencyMs: number;\n}\n\n/**\n * Gets obstructions from the native app using the new MASH API.\n * This API returns information about UI elements that might be obstructing the ad.\n * Docs: https://w.amazon.com/bin/view/MShop/mShopRadXCXTeam/projects/AppCX/Documentation/Obstructions\n * @returns An array with 0,1 or 2 bounding rectangles which indicate top or bottom overlap, and a boolean\n *     indicating if the entire screen is obstructed\n */\nexport const getObstructions = async (\n    timeoutMs: number,\n): Promise<{ boundingBoxes: DOMRect[]; isFullyObstructed: boolean; latencyMs: number }> => {\n    return new Promise((res, rej) => {\n        if (typeof P === 'undefined' || !P) {\n            rej(new Error('mash:getobstructions:missing'));\n            return;\n        }\n\n        const timeout = setTimeout(() => {\n            rej(new Error('mash:getobstructions:timeout'));\n        }, timeoutMs);\n\n        const startTime = performance.now();\n        P.when(MASH_API_NAME).execute((mash) => {\n            if (!mash?.appCX?.uiOrchestrator?.getObstructions) {\n                clearTimeout(timeout);\n                rej(new Error('mash:getobstructions:missing'));\n                return;\n            }\n\n            mash.appCX.uiOrchestrator.getObstructions({\n                successCallback: (result: ObstructionsResponse) => {\n                    clearTimeout(timeout);\n                    res({\n                        boundingBoxes: (result.boundingBoxes || []).map(convertNativeElementToDomRect),\n                        isFullyObstructed: result.isFullyObstructed,\n                        latencyMs: performance.now() - startTime,\n                    });\n                },\n                failCallback: () => {\n                    clearTimeout(timeout);\n                    rej(new Error('mash:getobstructions:failure'));\n                },\n            });\n        });\n    });\n};\n","import { MASH_API_NAME } from './getObstructions.js';\nimport { ObstructionsResponse } from './getObstructions.js';\n\nexport interface ObstructionsChangedEventResponse {\n    type: 'obstructionsChanged';\n    detail: ObstructionsResponse;\n}\n\n/**\n * Docs: https://w.amazon.com/bin/view/MShop/mShopRadXCXTeam/projects/AppCX/Documentation/Obstructions\n * @param handler\n */\nexport const addNativeObstructionsChangedListener = (\n    handler: (response: ObstructionsChangedEventResponse) => void,\n): void => {\n    if (typeof P === 'undefined' || !P) {\n        return;\n    }\n    P.when(MASH_API_NAME).execute((mash) => {\n        mash?.addEventListener('obstructionsChanged', handler);\n    });\n};\n\n/**\n * Docs: https://w.amazon.com/bin/view/MShop/mShopRadXCXTeam/projects/AppCX/Documentation/Obstructions\n * @param handler\n */\nexport const removeNativeObstructionsChangedListener = (\n    handler: (response: ObstructionsChangedEventResponse) => void,\n): void => {\n    if (typeof P === 'undefined' || !P) {\n        return;\n    }\n    P.when(MASH_API_NAME).execute((mash) => {\n        mash?.removeEventListener('obstructionsChanged', handler);\n    });\n};\n","import { getObstructions, getObstructionsResponse } from './getObstructions.js';\nimport { calculateObstructionPercentage, convertNativeElementToDomRect } from './nativeObstructionsUtils.js';\nimport {\n    addNativeObstructionsChangedListener,\n    ObstructionsChangedEventResponse,\n    removeNativeObstructionsChangedListener,\n} from './obstructionsEventListeners.js';\n\nexport interface NativeObstructionState {\n    listenerHandler?: (response: ObstructionsChangedEventResponse) => void;\n    setObstructingRectangles: (rects: DOMRect[]) => void;\n    getObstructingRectangles: () => DOMRect[];\n}\n\n/**\n * Measures the amount of the creative which is overlapped by native obstructions.\n * @param placementSafezoneDOMRect - The safezone DOMRect for the placement\n * @returns The percentage of the creative that is obstructed by native elements\n */\nexport const getNativeObstructionPercentage = (\n    placementSafezoneDOMRect: DOMRect,\n    nativeObstructionState: NativeObstructionState,\n): number => {\n    const obstructingRectangles = nativeObstructionState.getObstructingRectangles();\n    if (obstructingRectangles.length === 0) {\n        return 0;\n    }\n    const totalNativeObstruction = obstructingRectangles.reduce((total, rect) => {\n        return total + calculateObstructionPercentage(placementSafezoneDOMRect, rect);\n    }, 0);\n    return totalNativeObstruction;\n};\n\nexport const fetchNativeObstructions = async (nativeObstructionState: NativeObstructionState): Promise<void> => {\n    const aBitLessThan1Second = 950;\n    try {\n        nativeObstructionState.setObstructingRectangles([]);\n        if (!nativeObstructionState.listenerHandler) {\n            nativeObstructionState.listenerHandler = (response: ObstructionsChangedEventResponse) =>\n                nativeObstructionsChangedHandler(response, nativeObstructionState);\n            addNativeObstructionsChangedListener(nativeObstructionState.listenerHandler);\n        }\n        const obstructionsOutput = await getObstructions(aBitLessThan1Second);\n        nativeObstructionState.setObstructingRectangles(getObstructionsRects(obstructionsOutput));\n    } catch (err) {\n        console.debug('Error during native obstruction fetch', err);\n    }\n};\n\nconst nativeObstructionsChangedHandler = (\n    obstructionsChangedEventResponse: ObstructionsChangedEventResponse,\n    nativeObstructionState: NativeObstructionState,\n) => {\n    nativeObstructionState.setObstructingRectangles(\n        (obstructionsChangedEventResponse?.detail?.boundingBoxes || []).map(convertNativeElementToDomRect),\n    );\n};\n\nconst getObstructionsRects = (response: getObstructionsResponse): DOMRect[] => {\n    if (response.isFullyObstructed) {\n        return [convertNativeElementToDomRect({ height: window.innerHeight, top: 0 })];\n    }\n    return response.boundingBoxes.map(convertNativeElementToDomRect);\n};\n\nexport const cleanupNativeObstructionsChangedListener = (nativeObstructionState: NativeObstructionState): void => {\n    if (nativeObstructionState.listenerHandler) {\n        try {\n            removeNativeObstructionsChangedListener(nativeObstructionState.listenerHandler);\n        } catch {\n            // Ignore errors specifically for when P is not defined (e.g., in browser test environments)\n        }\n        nativeObstructionState.listenerHandler = undefined;\n    }\n};\n","import { getDOMObstructionPercentage } from './domObstructions/getDOMObstructionPercentage.js';\nimport type { NativeObstructionState } from './nativeObstructions/getNativeObstructionPercentage.js';\nimport {\n    cleanupNativeObstructionsChangedListener,\n    fetchNativeObstructions,\n    getNativeObstructionPercentage,\n} from './nativeObstructions/getNativeObstructionPercentage.js';\nimport type { ObstructionDetectionService, ObstructionPercentageParams } from './obstructionDetectionService.js';\n\nexport const createObstructionDetectionService = (): ObstructionDetectionService => {\n    let obstructingRectangles: DOMRect[] = [];\n\n    const nativeObstructionState: NativeObstructionState = {\n        listenerHandler: undefined,\n        setObstructingRectangles: (rects: DOMRect[]) => {\n            obstructingRectangles = rects;\n        },\n        getObstructingRectangles: () => obstructingRectangles,\n    };\n\n    fetchNativeObstructions(nativeObstructionState);\n\n    return {\n        getObstructionPercentage({\n            element,\n            elementDOMRectOverride = element.getBoundingClientRect(),\n        }: ObstructionPercentageParams): number {\n            const domObstructionPercentage = getDOMObstructionPercentage(element, elementDOMRectOverride);\n            const nativeObstructionPercentage = getNativeObstructionPercentage(\n                elementDOMRectOverride,\n                nativeObstructionState,\n            );\n            return Math.max(domObstructionPercentage, nativeObstructionPercentage);\n        },\n        cleanup(): void {\n            cleanupNativeObstructionsChangedListener(nativeObstructionState);\n        },\n    };\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\n\ntype SetupIntersectionObserverParams = {\n    target: Element;\n    onIntersection: (observer: IntersectionObserver, entry: IntersectionObserverEntry) => void;\n    onExit: (observer: IntersectionObserver, entry: IntersectionObserverEntry) => void;\n    options?: IntersectionObserverInit;\n    adDetails?: AdDetails | LightAdDetails;\n};\n\nexport const setupIntersectionObserver = ({\n    target,\n    onIntersection,\n    onExit,\n    options,\n    adDetails,\n}: SetupIntersectionObserverParams): IntersectionObserver => {\n    const observer = new IntersectionObserver((entries, observer) => {\n        entries.forEach((entry) => {\n            if (entry.isIntersecting) {\n                onIntersection(observer, entry);\n            } else {\n                onExit(observer, entry);\n            }\n        });\n    }, options);\n\n    // A detached placement (e.g. a slot removed by an infinite-scroll page) is not observable; observe() would throw\n    if (!(target instanceof Element)) {\n        if (adDetails) {\n            emitMetric({\n                metricName: 'intersection:observer:invalid:target',\n                adDetails,\n            });\n        }\n        return observer;\n    }\n\n    observer.observe(target);\n    return observer;\n};\n\nexport const observeUntilIntersection = async (\n    target: Element,\n    options?: IntersectionObserverInit,\n    adDetails?: AdDetails | LightAdDetails,\n): Promise<IntersectionObserverEntry> => {\n    return new Promise<IntersectionObserverEntry>((resolve) => {\n        return setupIntersectionObserver({\n            target,\n            onIntersection: (observer, entry) => {\n                resolve(entry);\n                observer.unobserve(entry.target);\n            },\n            onExit: () => {},\n            options,\n            adDetails,\n        });\n    });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { setupIntersectionObserver } from '@/components/intersectionObserver.js';\nimport { emitMetric, type ObstructionMetricName } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport type { VisibilityChangeService } from '@/components/pixels/services/visibilityChangeService.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\n\nexport class MRCObstructionViewPixel implements ViewPixel, FirePixel {\n    private viewTimerTimeoutId?: NodeJS.Timeout;\n    private obstructionCheckIntervalId?: NodeJS.Timeout;\n    private shouldFirePixelIntervalId?: NodeJS.Timeout;\n    private metricsLogged: Set<string> = new Set();\n    private wasObstructed: boolean = false;\n\n    constructor(\n        private readonly pixel: FirePixel,\n        readonly viewabilityStandard: ViewabilityStandard,\n        readonly visibilityChangeService: VisibilityChangeService,\n        private readonly viewabilityService: ViewabilityService,\n        private readonly videoPixelValidator: FirePixelValidator | undefined,\n        private readonly adDetails: AdDetails | LightAdDetails,\n    ) {}\n\n    postPixelFireCleanup(observer: IntersectionObserver, placement: Placement) {\n        observer.unobserve(placement.div);\n        clearTimeout(this.viewTimerTimeoutId);\n        clearInterval(this.obstructionCheckIntervalId);\n        this.visibilityChangeService.removeVisibilityChangeDetection();\n        this.emitObstructionRecoveryMetrics();\n        this.viewabilityService.cleanup();\n    }\n\n    postPlacementExitsViewportCleanup() {\n        clearTimeout(this.viewTimerTimeoutId);\n        clearInterval(this.obstructionCheckIntervalId);\n        clearInterval(this.shouldFirePixelIntervalId);\n        this.visibilityChangeService.removeVisibilityChangeDetection();\n    }\n\n    fireInObserver(observer: IntersectionObserver, placement: Placement): void {\n        this.fire(placement);\n        this.postPixelFireCleanup(observer, placement);\n    }\n\n    startInViewTimer(observer: IntersectionObserver, placement: Placement) {\n        // set view timer for threshold time\n        this.viewTimerTimeoutId = setTimeout(\n            () => this.fireInObserver(observer, placement),\n            this.viewabilityStandard.thresholdTimeVisibleMs,\n        );\n\n        this.performContinuousObstructionCheck(observer, placement);\n        this.visibilityChangeService.setupVisibilityChangeDetection(this.viewTimerTimeoutId, observer, placement);\n    }\n\n    // Start continously checking for obstruction every 100ms. Resets timeouts and intervals if viewability obstruction occurs\n    performContinuousObstructionCheck(observer: IntersectionObserver, placement: Placement) {\n        const intervalMs: number = 100;\n        this.obstructionCheckIntervalId = setInterval(() => {\n            try {\n                const isViewabilityObstructed = this.viewabilityService.isViewabilityObstructed(\n                    placement,\n                    this.viewabilityStandard.thresholdPercentage,\n                );\n                if (isViewabilityObstructed) {\n                    this.wasObstructed = true;\n                    clearTimeout(this.viewTimerTimeoutId);\n                    clearInterval(this.obstructionCheckIntervalId);\n                    this.startInViewTimer(observer, placement);\n                }\n            } catch (error: any) {\n                emitErrorLog({ message: error?.message, error, adDetails: this.adDetails });\n                clearInterval(this.obstructionCheckIntervalId);\n            }\n        }, intervalMs);\n    }\n\n    track(placement: Placement): void {\n        setupIntersectionObserver({\n            target: placement.div,\n            onIntersection: (observer) => this.startInViewTimer(observer, placement),\n            onExit: () => this.postPlacementExitsViewportCleanup(),\n            options: { threshold: this.viewabilityStandard.thresholdPercentage },\n            adDetails: this.adDetails,\n        });\n    }\n\n    async fire(placement: Placement): Promise<void> {\n        if (this.videoPixelValidator && !this.videoPixelValidator.shouldFirePixel()) {\n            await this.waitUntilShouldFirePixel();\n        }\n\n        this.pixel.fire(placement);\n    }\n\n    private waitUntilShouldFirePixel(): Promise<void> {\n        return new Promise((resolve) => {\n            this.shouldFirePixelIntervalId = setInterval(() => {\n                if (this.videoPixelValidator && this.videoPixelValidator.shouldFirePixel()) {\n                    clearInterval(this.shouldFirePixelIntervalId);\n                    resolve();\n                }\n            }, 100);\n        });\n    }\n\n    emitObstructionRecoveryMetrics = (): void => {\n        if (this.wasObstructed) {\n            this.logMetrics('viewpixel:iab:obstruction:recovered');\n        }\n    };\n\n    logMetrics = (metricName: ObstructionMetricName): void => {\n        if (!this.metricsLogged.has(metricName)) {\n            emitMetric({ metricName, adDetails: this.adDetails });\n            this.metricsLogged.add(metricName);\n        }\n    };\n}\n","/**\n * Calculates what percentage of the element is within the viewport\n * @param elementDOMRect - The element's bounding rectangle\n * @returns a number between 0 and 1\n */\nexport const getVisiblePercentageInViewport = (elementDOMRect: DOMRect): number => {\n    const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n    const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n\n    const visibleRect = {\n        top: Math.max(0, elementDOMRect.top),\n        left: Math.max(0, elementDOMRect.left),\n        bottom: Math.min(windowHeight, elementDOMRect.bottom),\n        right: Math.min(windowWidth, elementDOMRect.right),\n    };\n\n    if (\n        elementDOMRect.top >= windowHeight ||\n        elementDOMRect.left >= windowWidth ||\n        elementDOMRect.bottom <= 0 ||\n        elementDOMRect.right <= 0 ||\n        elementDOMRect.width <= 0 ||\n        elementDOMRect.height <= 0\n    ) {\n        return 0;\n    }\n\n    const visibleArea = (visibleRect.right - visibleRect.left) * (visibleRect.bottom - visibleRect.top);\n    const totalArea = elementDOMRect.width * elementDOMRect.height;\n    const visiblePercentage = visibleArea / totalArea;\n    return visiblePercentage;\n};\n","import type { ObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionService.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric, type ObstructionMetricName } from '@/components/metrics/csaMetrics.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport { getVisiblePercentageInViewport } from '@/components/pixels/viewPixelUtil.js';\n\nexport const createViewabilityService = (\n    obstructionDetectionService: ObstructionDetectionService,\n    adDetails: AdDetails | LightAdDetails,\n): ViewabilityService => {\n    const metricsLogged: Set<string> = new Set();\n\n    const logMetrics = (metricName: ObstructionMetricName): void => {\n        if (!metricsLogged.has(metricName)) {\n            emitMetric({ metricName, adDetails });\n            metricsLogged.add(metricName);\n        }\n    };\n\n    const isViewabilityObstructed = (placement: Placement, threshold: number): boolean => {\n        const placementDOMRect = placement.div.getBoundingClientRect();\n        const visiblePercentageInViewport = getVisiblePercentageInViewport(placementDOMRect);\n        const obstructionPercentage = obstructionDetectionService.getObstructionPercentage({\n            element: placement.div,\n            elementDOMRectOverride: placementDOMRect,\n        });\n\n        const isViewabilityObstructed = visiblePercentageInViewport - obstructionPercentage < threshold;\n        if (isViewabilityObstructed) {\n            logMetrics('viewpixel:iab:obstruction');\n        }\n        return isViewabilityObstructed;\n    };\n\n    return {\n        isViewabilityObstructed(placement: Placement, threshold: number): boolean {\n            return isViewabilityObstructed(placement, threshold);\n        },\n        cleanup(): void {\n            obstructionDetectionService.cleanup();\n        },\n    };\n};\n","import type { Placement } from '@/components/pixels/pixel.js';\n\nexport interface VisibilityChangeService {\n    activeVisChangeHandler?: EventListenerOrEventListenerObject;\n    removeVisibilityChangeDetection(): void;\n    setupVisibilityChangeDetection: (\n        timeoutId: NodeJS.Timeout,\n        observer: IntersectionObserver,\n        placement: Placement,\n    ) => void;\n}\n\nexport const createVisibiltyChangeService = (): VisibilityChangeService => {\n    const visibilityChangeEventHandler = (\n        timeoutId: NodeJS.Timeout,\n        observer: IntersectionObserver,\n        placement: Placement,\n    ) => {\n        if (document.hidden) {\n            clearTimeout(timeoutId);\n            observer.unobserve(placement.div);\n        } else {\n            observer.observe(placement.div);\n        }\n    };\n\n    return {\n        removeVisibilityChangeDetection(): void {\n            if (this.activeVisChangeHandler) {\n                document.removeEventListener('visibilitychange', this.activeVisChangeHandler);\n                this.activeVisChangeHandler = undefined;\n            }\n        },\n\n        setupVisibilityChangeDetection(\n            timeoutId: NodeJS.Timeout,\n            observer: IntersectionObserver,\n            placement: Placement,\n        ): void {\n            this.removeVisibilityChangeDetection();\n            this.activeVisChangeHandler = () => visibilityChangeEventHandler(timeoutId, observer, placement);\n            document.addEventListener('visibilitychange', this.activeVisChangeHandler);\n        },\n    };\n};\n","import type { SKAdNetwork } from '@amzn/safeframe-model';\n\n/**\n * Wrapper functions for MASH Extension API - SKAN App Ads Plugin\n * https://tiny.amazon.com/rrn9ljkr\n */\ntype SkanAttributePluginCommand = {\n    skAdNetwork: SKAdNetwork;\n};\n\ntype SkanAttributeClickCommand = {\n    skAdNetwork: SKAdNetwork;\n    fallbackUrl: string;\n};\n\nexport type SkanAttributePlugin = {\n    startAttributeViewThroughAppAds: (command: SkanAttributePluginCommand) => void;\n    endAttributeViewThroughAppAds: (command: SkanAttributePluginCommand) => void;\n    renderClickThroughAppAds: (command: SkanAttributeClickCommand) => void;\n};\n\nexport const skanAttributePluginName = 'AppAdsMshopIOSPlugin';\n\n/**\n * @func startAttributeViewThroughAppAds\n * @desc Wrapper function for MASH Extension API - SKAN App Ads Plugin, handles startImpression attribution for App Ads with SKAdNetwork.\n *       This function is called when the ad is rendered.\n * @param skAdNetwork object is using  call SKAN API.\n */\nexport const startAttributeViewThroughAppAds = (skAdNetwork: SKAdNetwork): void => {\n    window.P?.when(skanAttributePluginName).execute((skanAttributePlugin: SkanAttributePlugin) => {\n        skanAttributePlugin.startAttributeViewThroughAppAds({ skAdNetwork: skAdNetwork });\n    });\n};\n\n/**\n * @func endAttributeViewThroughAppAds\n * @desc Wrapper function for MASH Extension API - SKAN App Ads Plugin, handles endImpression attribution for App Ads with SKAdNetwork.\n *       This function is called when the ad is viewed continuously for 2 secs\n *       (https://developer.apple.com/documentation/storekit/skadnetwork/endimpression(_:completionhandler:)?language=objc).\n * @param skAdNetwork {object} SKAdNetwork object pass to MASH API for app ads\n */\nexport const endAttributeViewThroughAppAds = (skAdNetwork: SKAdNetwork): void => {\n    window.P?.when(skanAttributePluginName).execute((skanAttributePlugin: SkanAttributePlugin) => {\n        skanAttributePlugin.endAttributeViewThroughAppAds({ skAdNetwork: skAdNetwork });\n    });\n};\n\n/**\n * @func renderClickThroughAppAds\n * @desc Wrapper function for MASH Extension API - SKAN App Ads Plugin, handles click-through attribution for App Ads with SKAdNetwork\n * @param skAdNetwork {?object} SK Ad Network object pass to MASH API for app ads click-through store-kit render\n * @param url {string} The fallback url used to pass to MASH API\n */\nexport const renderClickThroughAppAds = (skAdNetwork: SKAdNetwork, url: string): void => {\n    window.P?.when(skanAttributePluginName).execute((skanAttributePlugin: SkanAttributePlugin) => {\n        skanAttributePlugin.renderClickThroughAppAds({ skAdNetwork: skAdNetwork, fallbackUrl: url });\n    });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric, emitMetric } from '@/components/metrics/csaMetrics.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { startAttributeViewThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.js';\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/state/placement/pixelState.js';\n\nconst METRIC_NAME = 'pixel:imp:skan' as const;\n\nexport class SkanImpressionPixel implements FirePixel {\n    constructor(private readonly adDetails: AdDetails | LightAdDetails) {}\n\n    async fire(placement: Placement): Promise<void> {\n        if (hasPixelFired(placement.div, METRIC_NAME)) {\n            return;\n        }\n        markPixelFired(placement.div, METRIC_NAME);\n        const firedAt = performance.now();\n        try {\n            startAttributeViewThroughAppAds(this.adDetails.skAdNetwork!);\n        } catch (e) {\n            markPixelError(placement.div, METRIC_NAME);\n            throw e;\n        }\n        emitLightAdTimingMetric({\n            metricName: `${METRIC_NAME}:timing`,\n            metricValue: firedAt,\n            adDetails: this.adDetails,\n        });\n        emitMetric({ metricName: METRIC_NAME, adDetails: this.adDetails });\n    }\n}\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric, emitMetric } from '@/components/metrics/csaMetrics.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { endAttributeViewThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.js';\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/state/placement/pixelState.js';\n\nconst METRIC_NAME = 'pixel:view:skan' as const;\n\nexport class SkanViewPixel implements FirePixel {\n    constructor(private readonly adDetails: AdDetails | LightAdDetails) {}\n\n    async fire(placement: Placement): Promise<void> {\n        if (hasPixelFired(placement.div, METRIC_NAME)) {\n            return;\n        }\n        markPixelFired(placement.div, METRIC_NAME);\n        const firedAt = performance.now();\n        try {\n            endAttributeViewThroughAppAds(this.adDetails.skAdNetwork!);\n        } catch (e) {\n            markPixelError(placement.div, METRIC_NAME);\n            throw e;\n        }\n        emitLightAdTimingMetric({\n            metricName: `${METRIC_NAME}:timing`,\n            metricValue: firedAt,\n            adDetails: this.adDetails,\n        });\n        emitMetric({ metricName: METRIC_NAME, adDetails: this.adDetails });\n    }\n}\n","export const ATF_URL_KEY = 'atf' as const;\nexport const VIEW_PIXEL_URL_KEY = 'v' as const;\nexport const BTR_JSON_KEY = 'c' as const;\nexport const aaxTypeMacro = /\\${AAX_TYPE}/;\nexport const aaxPayloadMacro = /\\${AAX_PAYLOAD}/;\n","const EMPTY_OBJECT_STRINGIFIED = '{}' as const;\nconst EMPTY_STRING = '' as const;\n\n/**\n * This function adds a query parameter to the given URL where the value is a JSON.\n * The most common use-case is addition of `publisherJSON` to AAX URLs. eg: https://evergreen.corp.amazon.com/aax-hub/apis/bid-api/xsp/#impression\n * If the existing URL already contains this parameter key, the two JSONs are merged based on the top-level keys.\n * In case of a conflict, priority is given to the new JSON.\n *\n * eg:\n * 1. If url contains json {\"key1\": \"value1\"}, and queryParamValueObject contains {\"key1\":\"value2\"}, priority is given to queryParamValueObject.\n *    Final json is {\"key1\":\"value2\"}\n * 2. If url contains json {\"key1\": \"value1\"}, and queryParamValueObject contains {\"key2\":\"value2\"}, JSONs are merged.\n *    Final json is {\"key1\":\"value1\", \"key2\":\"value2\"}\n *\n * @param {string} url - URL where query param needs to be added.\n * @param {string} queryParamKey - key of query param that needs to be added.\n * @param {Object} queryParamValueObject - value of query param that needs to be added.\n * @returns {string} URL with query param added.\n * @throws Error if invalid inputs are provided.\n **/\nexport const addJSONQueryParamToURL = (\n    url: string,\n    queryParamKey: string,\n    queryParamValueObject: { [key: string]: any },\n): string => {\n    if (queryParamKey === EMPTY_STRING) {\n        throw new Error(\n            'Invalid queryParamKey input to addJSONQueryParamToURL: ' +\n                JSON.stringify({ queryParamKey: queryParamKey }),\n        );\n    }\n    const urlObject = new URL(url);\n    const pk = urlObject.searchParams.get(queryParamKey);\n    const existingJSONString = pk ? pk : EMPTY_OBJECT_STRINGIFIED;\n    const existingJSONObject = JSON.parse(existingJSONString);\n    const mergedJSONObject = Object.assign(existingJSONObject, queryParamValueObject);\n    urlObject.searchParams.set(queryParamKey, JSON.stringify(mergedJSONObject));\n    return urlObject.toString();\n};\n","export const safeFunctionWrapper = (\n    handler: (...safeArgs: any[]) => void,\n    errorHandler?: (msg: string, ex?: any) => void,\n    errorMessage?: string,\n): any => {\n    return (...args: any[]) => {\n        try {\n            handler(...args);\n        } catch (ex) {\n            errorHandler?.(errorMessage ? errorMessage : 'Error in handler', ex);\n        }\n    };\n};\n\n// Below code is for utf_8 compliant versions of atob/btoa\n//M DN https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8\n\nexport const utf_8_atob = (base64: string): string => b64_to_utf8(base64);\nexport const utf_8_btoa = (js_text: string): string => utf8_to_b64(js_text);\n\n// We use unescape even though not recommended due to performance and code size\nconst utf8_to_b64 = (utf8: string): string => {\n    return btoa(unescape(encodeURIComponent(utf8)));\n};\n\nconst b64_to_utf8 = (base64: string): string => {\n    return decodeURIComponent(escape(atob(base64)));\n};\n\n// Remove when https://issues.amazon.com/issues/V1533734779 is resolved.\nexport const removeAAXPayloadFromUrl = (url: string): string => {\n    if (!url) {\n        return url;\n    }\n    // oxlint-disable-next-line no-template-curly-in-string\n    return url.split('&c=${AAX_PAYLOAD}').join('');\n};\n","import { BTR_JSON_KEY } from '@/components/aax/aax.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { addJSONQueryParamToURL } from '@/components/urlQueryParams/addJSONQueryParamToURL.js';\nimport { removeAAXPayloadFromUrl } from '@/components/util.js';\n\n/** btr = Begin to render: Creative assets are loaded and begin to render */\nexport const BEGIN_TO_RENDER_CLIENT = 'btr_client' as const;\n\nexport const generateBtrPixelUrl: PixelUrlGenerator = (url: string): string =>\n    // Remove removeAAXPayloadFromUrl when https://issues.amazon.com/issues/V1533734779 is resolved.\n    addJSONQueryParamToURL(removeAAXPayloadFromUrl(url), BTR_JSON_KEY, {\n        measurementMethod: BEGIN_TO_RENDER_CLIENT,\n    });\n","import type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\n\nexport const generateImpressionPixelUrl: PixelUrlGenerator = (url: string): string => url;\n","interface Location {\n    readonly t: number;\n    readonly l: number;\n    readonly r: number;\n    readonly b: number;\n    readonly w: number;\n    readonly h: number;\n    readonly z: number;\n}\n\n/*\n    Method for returning the parent window's height\n*/\nexport const windowHeight = () => {\n    return window.innerHeight || document.documentElement.clientHeight;\n};\n\n/*\n    Method for returning the parent window's width\n*/\nexport const windowWidth = () => {\n    return window.innerWidth || document.documentElement.clientWidth;\n};\n\n/*\n    Method for determining the distance of the top of the ad from the viewport.\n    Positive if ad is below the viewport, Negative if ad is in / above the viewport.\n*/\nexport const findDistanceFromViewport = (elem: HTMLElement) => {\n    const boundingRect = elem.getBoundingClientRect();\n    return boundingRect.top - windowHeight();\n};\n\nexport const convertBoundingClientRectToLocation = (boundingRect: DOMRect, z: number): Location => {\n    return {\n        t: boundingRect.top,\n        l: boundingRect.left,\n        r: boundingRect.right,\n        b: boundingRect.bottom,\n        w: boundingRect.width,\n        h: boundingRect.height,\n        z: z,\n    };\n};\n\n/*\n    Computes the location attributes of the element.\n*/\nexport const getElementLocation = (elem: HTMLElement): Location => {\n    const boundingRect = elem.getBoundingClientRect();\n    return convertBoundingClientRectToLocation(boundingRect, Number(window.getComputedStyle(elem, null).zIndex));\n};\n\n/*\n    Computes whether an element is in view without user scrolling.\n        Returns true when >= 50% of the element is in view without user scrolling.\n        Returns false when < 50% of the element is in view without user scrolling.\n        Returns undefined if viewability is not measurable.\n    This ATF/measurability information is added per sim: https://sim.amazon.com/issues/CAP-8767\n    This atf definition is different from atf information stored in XSP config.\n*/\nexport const getAtfInfo = (elem: HTMLElement): boolean | 'unknown' => {\n    const piv = getElementViewPercentageWithoutScrolling(elem);\n    if (piv == null) {\n        return 'unknown';\n    } else if (piv >= 0.5) {\n        return true;\n    }\n    return false;\n};\n\n// https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect\nconst invalidOrMissingOrHiddenBoundingBox = (bodyLoc: DOMRect) => {\n    return bodyLoc.width === 0 && bodyLoc.height === 0;\n};\n\n/*\n    Computes the percentage of element that is in view without scrolling.\n    @returns null means can't compute due to invalid document bounding box\n    Export for testing only\n*/\nexport function getElementViewPercentageWithoutScrolling(elem: HTMLElement): number | null {\n    const bodyLoc = document.body.getBoundingClientRect();\n    if (invalidOrMissingOrHiddenBoundingBox(bodyLoc)) return null;\n    const elemLoc = getElementLocation(elem);\n    const wh = windowHeight();\n    const ww = windowWidth();\n\n    const viewableWidth = Math.max(0, Math.min(bodyLoc.left + ww, elemLoc.r) - elemLoc.l);\n    const viewableHeight = Math.max(0, Math.min(bodyLoc.top + wh, elemLoc.b) - elemLoc.t);\n    const viewableRatio = (viewableWidth * viewableHeight) / (elemLoc.h * Math.min(elemLoc.w, ww));\n    const viewPercentageWithoutScrolling = Number(Math.min(1, Math.max(0, viewableRatio)).toFixed(2));\n    return viewPercentageWithoutScrolling;\n}\n\nexport const canBeInSameViewport = (elemA: HTMLElement, elemB: HTMLElement): boolean | null => {\n    const locationA = getElementLocation(elemA);\n    const locationB = getElementLocation(elemB);\n    const ww = windowWidth();\n    const wh = windowHeight();\n    return (\n        locationA &&\n        locationB &&\n        (Math.abs(locationA.t - locationB.b) < wh || Math.abs(locationA.b - locationB.t) < wh) &&\n        (Math.abs(locationA.l - locationB.r) < ww || Math.abs(locationA.r - locationB.l) < ww)\n    );\n};\n","import { aaxPayloadMacro, aaxTypeMacro, ATF_URL_KEY } from '@/components/aax/aax.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { getAtfInfo } from '@/components/viewability.js';\n\nexport const generateMeasurabilityPixelUrl: PixelUrlGenerator = (url: string, params: Placement): string => {\n    const payloadObj = { atf: getAtfInfo(params.div) };\n    const encodedUrlPayload = encodeURIComponent(JSON.stringify(payloadObj));\n    return url.replace(aaxTypeMacro, ATF_URL_KEY).replace(aaxPayloadMacro, encodedUrlPayload);\n};\n","import type { Placement } from '@/components/pixels/pixel.js';\n\nexport const btr = {\n    set: (placement: Placement, value: boolean): void => {\n        placement.div.dataset.isBtr = String(value);\n    },\n    get: (placement: Placement): boolean => {\n        return placement.div.dataset.isBtr === String(true);\n    },\n};\n","import type { ViewableInfo } from '@amzn/safe-frame-client-amzn';\n\nimport { aaxPayloadMacro, aaxTypeMacro, VIEW_PIXEL_URL_KEY } from '@/components/aax/aax.js';\nimport '@/components/pixels/pageTimings.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\n\nexport interface PixelUrlParams {\n    placement: Placement;\n    definition: string;\n    thresholdPercentage: number;\n    thresholdTimeVisibleMs: number;\n    isBtr: boolean;\n    adStartTime: number;\n}\n\n// https://w.amazon.com/bin/view/AdPT/ACS/SupplyQuality/VUE/CSM/PixelPayloadFormat/\nexport const pixelUrlParameters = (pixelUrlParams: PixelUrlParams): ViewableInfo => {\n    const placementDivRect = pixelUrlParams.placement.div.getBoundingClientRect();\n    return {\n        v: {\n            def: pixelUrlParams.definition,\n            p: pixelUrlParams.thresholdPercentage,\n            t: pixelUrlParams.thresholdTimeVisibleMs,\n            ib: pixelUrlParams.isBtr,\n        },\n        wh: window.innerHeight || document.documentElement.clientHeight,\n        ww: window.innerWidth || document.documentElement.clientWidth,\n        sx: window.scrollX,\n        sy: window.scrollY,\n        ah: placementDivRect.height,\n        aw: placementDivRect.width,\n        top: placementDivRect.top,\n        left: placementDivRect.left,\n        ptv: (new Date().getTime() - (window.aPageStart ?? 0)) / 1000,\n        ttv: (new Date().getTime() - pixelUrlParams.adStartTime) / 1000,\n    };\n};\n\nexport const generateMrcObstructionViewPixelUrl = (viewabilityStandard: ViewabilityStandard): PixelUrlGenerator => {\n    const adStartTime = new Date().getTime();\n    return (url: string, placement: Placement): string => {\n        const pixelUrlParams: PixelUrlParams = {\n            placement: placement,\n            definition: viewabilityStandard.definition,\n            thresholdPercentage: viewabilityStandard.thresholdPercentage,\n            thresholdTimeVisibleMs: viewabilityStandard.thresholdTimeVisibleMs,\n            isBtr: btr.get(placement),\n            adStartTime,\n        };\n\n        const encodedUrlPayload = encodeURIComponent(JSON.stringify(pixelUrlParameters(pixelUrlParams)));\n\n        return url.replace(aaxTypeMacro, VIEW_PIXEL_URL_KEY).replace(aaxPayloadMacro, encodedUrlPayload);\n    };\n};\n","export type ViewabilityStandard = {\n    definition: string;\n    thresholdPercentage: number;\n    thresholdTimeVisibleMs: number;\n};\n\nconst IAB_VIDEO: ViewabilityStandard = {\n    definition: 'iab',\n    thresholdPercentage: 0.5,\n    thresholdTimeVisibleMs: 2000,\n} as const;\n\nconst IAB_LARGE_DISPLAY: ViewabilityStandard = {\n    definition: 'iab',\n    thresholdPercentage: 0.3,\n    thresholdTimeVisibleMs: 1000,\n} as const;\n\nconst IAB_DISPLAY: ViewabilityStandard = {\n    definition: 'iab',\n    thresholdPercentage: 0.5,\n    thresholdTimeVisibleMs: 1000,\n} as const;\n\nconst SKAN: ViewabilityStandard = {\n    definition: 'skan',\n    thresholdPercentage: 0.5,\n    thresholdTimeVisibleMs: 2000,\n} as const;\n\nexport const VIEWABILITY_STANDARDS = {\n    IAB_VIDEO,\n    IAB_LARGE_DISPLAY,\n    IAB_DISPLAY,\n    SKAN,\n} as const satisfies Record<string, ViewabilityStandard>;\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { setupIntersectionObserver } from '@/components/intersectionObserver.js';\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport type { Pixel, Placement } from '@/components/pixels/pixel.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\n\ntype Cleanup = () => void;\ntype State = { wasObstructed: boolean };\n\n/**\n * Creates a MRC-compliant viewability tracker that fires pixels when viewability thresholds are met.\n * Monitors viewport intersection, obstruction, and document visibility to ensure accurate viewability measurement.\n */\nexport const createViewabilityTracker = (\n    pixels: Pixel[],\n    viewabilityStandard: ViewabilityStandard,\n    viewabilityService: ViewabilityService,\n    firePixelValidators: FirePixelValidator[],\n    adDetails: AdDetails | LightAdDetails,\n): ViewPixel => {\n    /**\n     * Starts tracking viewability for the given placement.\n     * Sets up an intersection observer to monitor when the placement meets the visibility threshold.\n     * This ensures we only poll when the placement is relevant (meets threshold visibility).\n     */\n    const track = (placement: Placement): void => {\n        let cleanup: Cleanup | undefined;\n        // State must be an object to persist across multiple startViewTimer calls (viewport exit/re-entry)\n        const state: State = { wasObstructed: false };\n\n        setupIntersectionObserver({\n            target: placement.div,\n            onIntersection: (observer) => (cleanup = startViewTimer(placement, observer, state)),\n            onExit: () => cleanup?.(), // May be undefined on initial callback if placement starts below threshold\n            options: { threshold: viewabilityStandard.thresholdPercentage },\n            adDetails,\n        });\n    };\n\n    /**\n     * Starts the viewability timer when placement enters viewport.\n     * Checks every 100ms if the placement is viewable and fires pixel when threshold is met.\n     *\n     * The timer operates in three states:\n     * 1. If obstructed or hidden: marks for reset on next check (defers reset to avoid counting obstructed time)\n     * 2. If needs reset: resets the visible start time to current time (starts fresh count when unobstructed)\n     * 3. If visible and threshold met: fires pixel and cleans up\n     *\n     * The two-step reset ensures we don't count time while obstructed, and only start counting\n     * from the first unobstructed check after obstruction ends.\n     *\n     * @returns cleanup function to clear the interval and remove listeners\n     */\n    const startViewTimer = (placement: Placement, observer: IntersectionObserver, state: State): Cleanup => {\n        let visibleStartTime = performance.now();\n        let needsReset = false;\n\n        const intervalId = setInterval(() => {\n            // State 1: Obstruction detected - mark for reset to avoid counting obstructed time.\n            // isHidden() (a cheap document.hidden read) is checked first so it short-circuits the\n            // expensive obstruction hit-test (~10 elementFromPoint + getComputedStyle) on hidden tabs.\n            if (isHidden() || isObstructed(placement)) {\n                state.wasObstructed = true;\n                needsReset = true;\n            }\n            // State 2: Reset timer after obstruction cleared - start fresh count\n            else if (needsReset) {\n                visibleStartTime = performance.now();\n                needsReset = false;\n            }\n            // State 3: Threshold met and validators pass - fire pixel and cleanup\n            else if (\n                hasMetThreshold(visibleStartTime, viewabilityStandard.thresholdTimeVisibleMs) &&\n                shouldFirePixel(firePixelValidators)\n            ) {\n                pixels.forEach((pixel) => pixel.fire(placement));\n                cleanup(state.wasObstructed);\n                observer.unobserve(placement.div);\n            }\n        }, IAB_WAIT_INTERVAL_MS);\n\n        const cleanup = (wasObstructed = false): void => {\n            if (wasObstructed) {\n                logObstructionRecovery(adDetails);\n            }\n            clearInterval(intervalId);\n            viewabilityService.cleanup();\n        };\n\n        return cleanup;\n    };\n\n    /**\n     * Checks if the placement is obstructed by other elements.\n     * @returns true if obstructed, false otherwise or on error\n     */\n    const isObstructed = (placement: Placement): boolean => {\n        try {\n            return viewabilityService.isViewabilityObstructed(placement, viewabilityStandard.thresholdPercentage);\n        } catch (error: any) {\n            emitErrorLog({ message: error?.message, error, adDetails });\n            return false; // Treat errors as unobstructed to continue tracking\n        }\n    };\n\n    return { track, viewabilityStandard };\n};\n\n/**\n * Maximum allowed interval for checking viewability status per IAB standard.\n * Checks must occur at least every 100ms to accurately measure continuous viewable time.\n */\nconst IAB_WAIT_INTERVAL_MS = 100 as const;\n\n/**\n * Checks if the document is hidden (tab is not visible).\n * @returns true if document is hidden\n */\nconst isHidden = (): boolean => document.hidden;\n\n/**\n * Checks if the placement has been continuously visible for the required threshold time.\n * @param visibleStartTime - The timestamp when visibility started\n * @param thresholdTimeVisibleMs - The required threshold time in milliseconds\n * @returns true if threshold time has been met\n */\nconst hasMetThreshold = (visibleStartTime: number, thresholdTimeVisibleMs: number): boolean =>\n    performance.now() - visibleStartTime >= thresholdTimeVisibleMs;\n\n/**\n * Checks if all pixel validators allow firing the pixel.\n * @param validators - Array of validators to check\n * @returns true if all validators pass\n */\nconst shouldFirePixel = (validators: FirePixelValidator[]): boolean => validators.every((v) => v.shouldFirePixel());\n\n/**\n * Logs metrics when pixel fires after recovering from obstruction.\n */\nconst logObstructionRecovery = (adDetails: AdDetails | LightAdDetails): void => {\n    emitMetric({ metricName: 'viewpixel:iab:obstruction:recovered', adDetails });\n};\n","import { createObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.js';\nimport type { AdDetails, DeviceType, LightAdDetails, MediaType } from '@amzn/safeframe-model';\n\nimport { MRCObstructionViewPixel } from '@/components/pixels/mrcObstructionViewPixel.js';\nimport { Pixel } from '@/components/pixels/pixel.js';\nimport {\n    BTR_IDENTIFIER,\n    IAB_VIEWABILITY_IDENTIFIER,\n    IMPRESSION_IDENTIFIER,\n    MEASURABILITY_IDENTIFIER,\n} from '@/components/pixels/pixelIdentifiers.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.ts';\nimport { createViewabilityService } from '@/components/pixels/services/viewabilityServiceImpl.js';\nimport { createVisibiltyChangeService } from '@/components/pixels/services/visibilityChangeService.js';\nimport { SkanImpressionPixel } from '@/components/pixels/skanImpressionPixel.js';\nimport { SkanViewPixel } from '@/components/pixels/skanViewPixel.js';\nimport { generateBtrPixelUrl } from '@/components/pixels/urlGenerators/btrPixelUrlGenerator.js';\nimport { generateImpressionPixelUrl } from '@/components/pixels/urlGenerators/impressionPixelUrlGenerator.js';\nimport { generateMeasurabilityPixelUrl } from '@/components/pixels/urlGenerators/measurabilityPixelUrlGenerator.js';\nimport { generateMrcObstructionViewPixelUrl } from '@/components/pixels/urlGenerators/mrcObstructionViewPixelUrlGenerator.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\nimport { VIEWABILITY_STANDARDS } from '@/components/pixels/viewabilityStandards.js';\nimport { createViewabilityTracker } from '@/components/pixels/viewabilityTrackerImpl.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\nimport { NEW_VIEWABILITY_TRACKER_WEBLAB } from '@/components/weblabs.js';\n\nexport const mapToBtrPixel = (adDetails: AdDetails | LightAdDetails): Pixel | undefined => {\n    return adDetails.btrPixelUrl\n        ? new Pixel(adDetails.btrPixelUrl, generateBtrPixelUrl, BTR_IDENTIFIER, adDetails)\n        : undefined;\n};\n\nexport const mapToImpressionPixel = (adDetails: AdDetails | LightAdDetails, imp3pUrls: string[] = []): Pixel =>\n    new Pixel(adDetails.aaxImpPixelUrl, generateImpressionPixelUrl, IMPRESSION_IDENTIFIER, adDetails, imp3pUrls);\n\nexport const mapToMeasurabilityPixel = (adDetails: AdDetails | LightAdDetails): Pixel =>\n    new Pixel(adDetails.aaxInstrPixelUrl, generateMeasurabilityPixelUrl, MEASURABILITY_IDENTIFIER, adDetails);\n\nexport const createIabViewPixel = async (\n    mediaType: MediaType,\n    htmlElement: HTMLElement,\n    adDetails: AdDetails | LightAdDetails,\n    firePixelValidator: () => Promise<FirePixelValidator>,\n): Promise<ViewPixel> => {\n    if (mediaType === 'V') {\n        return createMrcViewPixel(adDetails, VIEWABILITY_STANDARDS.IAB_VIDEO, await firePixelValidator());\n    } else if (isDesktop(adDetails.deviceType) && isLargeAd(htmlElement)) {\n        return createMrcViewPixel(adDetails, VIEWABILITY_STANDARDS.IAB_LARGE_DISPLAY);\n    } else {\n        return createMrcViewPixel(adDetails, VIEWABILITY_STANDARDS.IAB_DISPLAY);\n    }\n};\n\nconst isDesktop = (deviceType: DeviceType): boolean => deviceType === 'DESKTOP';\n\n/**\n * Large IAB view pixel is used to measure the time the ad is visible on the screen.\n * An ad can be considered a large ad if it is of 242,500 pixels are larger\n * @link https://www.iab.com/wp-content/uploads/2015/06/MRC-Viewable-Ad-Impression-Measurement-Guideline.pdf\n */\nconst isLargeAd = (htmlElement: HTMLElement): boolean => getSizeOfElementInTotalPixels(htmlElement) >= 242500;\n\nconst getSizeOfElementInTotalPixels = (htmlElement: HTMLElement): number =>\n    htmlElement.getBoundingClientRect().height * htmlElement.getBoundingClientRect().width;\n\nconst createMrcViewPixel = (\n    adDetails: AdDetails | LightAdDetails,\n    standard: ViewabilityStandard,\n    validator?: FirePixelValidator,\n): ViewPixel => {\n    const pixel = new Pixel(\n        adDetails.aaxInstrPixelUrl,\n        generateMrcObstructionViewPixelUrl(standard),\n        IAB_VIEWABILITY_IDENTIFIER,\n        adDetails,\n    );\n\n    if (NEW_VIEWABILITY_TRACKER_WEBLAB().is('t1')) {\n        return createViewabilityTracker(\n            [pixel],\n            standard,\n            createViewabilityService(createObstructionDetectionService(), adDetails),\n            validator ? [validator] : [],\n            adDetails,\n        );\n    } else {\n        return new MRCObstructionViewPixel(\n            pixel,\n            standard,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService(), adDetails),\n            validator,\n            adDetails,\n        );\n    }\n};\n\nexport const mapToSkanImpressionPixel = (adDetails: AdDetails | LightAdDetails): SkanImpressionPixel | undefined => {\n    return adDetails.skAdNetwork ? new SkanImpressionPixel(adDetails) : undefined;\n};\n\nexport const mapToSkanViewPixel = (adDetails: AdDetails | LightAdDetails): ViewPixel | undefined => {\n    if (adDetails.skAdNetwork) {\n        const skanPixel = new SkanViewPixel(adDetails);\n        return new MRCObstructionViewPixel(\n            skanPixel,\n            VIEWABILITY_STANDARDS.SKAN,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService(), adDetails),\n            undefined,\n            adDetails,\n        );\n    }\n    return undefined;\n};\n","const ATTRIBUTION = 'APE-safeframe';\n\n/**\n * Reports an error to RTLA via the CSM `ueLogError` global, and to the console.\n * No-ops the RTLA leg when the host has not installed `ueLogError`.\n *\n * `additionalInfo.message` is deliberately omitted: CSM prepends it to\n * `exception.message`, so passing both would log the text twice.\n */\nexport const logError = (error: Error | string): void => {\n    const exception = typeof error === 'string' ? new Error(error) : error;\n    console.error(exception);\n    window.ueLogError?.(exception, {\n        logLevel: 'ERROR',\n        attribution: ATTRIBUTION,\n        message: exception.message,\n    });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { logError } from './logging.js';\n\nexport const CLICK_FAILURE_METRIC_CSM = 'adplacements:retailClickTracking:failure';\nexport const CLICK_MISSING_URL_METRIC_CSM = 'adplacements:retailClickTracking:missingUrl';\nexport const CLICK_INVALID_URL_METRIC_CSM = 'adplacements:retailClickTracking:invalidUrl';\nexport const CLICK_QUEUED_METRIC_CSM = 'adplacements:retailClickTracking:clickQueued';\n\nconst AMAZON_REDIRECT_PATH = '/r';\nconst AMAZON_HOST_PATTERN =\n    /^www\\.amazon\\.(com|co\\.uk|co\\.jp|co\\.za|de|fr|it|es|ca|cl|in|nl|sg|sa|ae|se|pl|eg|com\\.au|com\\.br|com\\.mx|com\\.tr|com\\.be|com\\.co)$/;\nconst EXPECTED_AID = 'rIyS0EtzRoiVXV9tijDCfw';\nconst REQUIRED_PARAMS = ['pd_rd_wg', 'pd_rd_w', 'pd_rd_i', 'pf_rd_p'] as const;\n\nconst firedClickTrackingUrls = new Set<string>();\n\n/** Counts a metric both in aggregate and per slot (`<metric>:<pageType>:<placementName>`). */\nconst count = (metricName: string, { pageType, placementName }: AdDetails | LightAdDetails): void => {\n    window.ue.count(metricName, 1);\n    window.ue.count(`${metricName}:${pageType}:${placementName}`, 1);\n};\n\nexport const isValidClickTrackingUrl = (url: string): boolean => {\n    try {\n        const parsed = new URL(url);\n        if (parsed.protocol !== 'https:') return false;\n        if (!AMAZON_HOST_PATTERN.test(parsed.hostname)) return false;\n        if (parsed.pathname !== AMAZON_REDIRECT_PATH) return false;\n        if (parsed.searchParams.get('aid') !== EXPECTED_AID) return false;\n\n        const dest = parsed.searchParams.get('dest');\n        if (!dest) return false;\n\n        const destUrl = new URL(dest);\n        if (destUrl.protocol !== 'https:' && destUrl.protocol !== 'http:') return false;\n        if (!parsed.searchParams.has('pd_rd_r') && !parsed.searchParams.has('pf_rd_r')) return false;\n\n        return REQUIRED_PARAMS.every((param) => parsed.searchParams.has(param));\n    } catch {\n        return false;\n    }\n};\n\nexport const fireRetailClickTracking = async (\n    retailClickTrackingUrl: string,\n    adDetails: AdDetails | LightAdDetails,\n): Promise<void> => {\n    if (!retailClickTrackingUrl) {\n        count(CLICK_MISSING_URL_METRIC_CSM, adDetails);\n        return;\n    }\n\n    if (!isValidClickTrackingUrl(retailClickTrackingUrl)) {\n        count(CLICK_INVALID_URL_METRIC_CSM, adDetails);\n        logError(`Invalid retail click tracking URL: ${retailClickTrackingUrl}`);\n        return;\n    }\n\n    if (firedClickTrackingUrls.has(retailClickTrackingUrl)) {\n        return;\n    }\n    firedClickTrackingUrls.add(retailClickTrackingUrl);\n\n    try {\n        const queued = navigator.sendBeacon(retailClickTrackingUrl);\n        count(queued ? CLICK_QUEUED_METRIC_CSM : CLICK_FAILURE_METRIC_CSM, adDetails);\n    } catch (_ex) {\n        count(CLICK_FAILURE_METRIC_CSM, adDetails);\n    }\n};\n","import { fireRetailClickTracking } from '@amzn/grandprix-runtime/src/retail-click-tracking.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const getClickTrackingUrl = (adDetails: AdDetails): string | undefined =>\n    getPlacement(adDetails, { lookupSource: 'creative-load' })?.getAttribute('data-click-addr') || undefined;\n\nexport const fireRetailClickTrackingFromCache = (adDetails: AdDetails, url: string | undefined): void => {\n    getPlacement(adDetails, { lookupSource: 'click' })?.removeAttribute('onclick');\n    fireRetailClickTracking(url ?? '', adDetails);\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport type { Pixel } from '@/components/pixels/pixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport { createViewabilityTracker } from '@/components/pixels/viewabilityTrackerImpl.js';\nimport { VIEW_RATE_EXPERIMENT, VIEW_RATE_EXPERIMENT_TIMEOUT } from '@/components/weblabs.js';\n\n/**\n * TODO: Clean up View Rate Experiment\n * https://sim.amazon.com/issues/ASPEN-9994\n */\nexport interface ViewRateExperimentPixels {\n    impressionPixel: Pixel;\n    btrPixel?: Pixel;\n    measurabilityPixel: Pixel;\n}\n\nconst weblabTreatmentToThreshold: Record<string, number> = {\n    c: 0,\n    t1: 0.1,\n    t2: 0.2,\n    t3: 0.3,\n    t4: 0.4,\n    t5: 0.5,\n};\n\nconst weblabTreatmentToTimeout: Record<string, number> = {\n    c: 0,\n    t1: 100,\n    t2: 200,\n    t3: 300,\n    t4: 400,\n    t5: 500,\n    t6: 600,\n    t7: 700,\n    t8: 800,\n    t9: 900,\n};\n\nexport const isViewRateExperimentEnabled = (aaxProgramId: number): boolean => {\n    return aaxProgramId !== 1004 && VIEW_RATE_EXPERIMENT().isInTreatment();\n};\n\nconst btrFirePixelValidator = (placement: Placement): FirePixelValidator => {\n    return {\n        shouldFirePixel(): boolean {\n            return btr.get(placement);\n        },\n    };\n};\n\nexport const trackViewRateExperiment = (\n    placement: Placement,\n    pixels: ViewRateExperimentPixels,\n    viewabilityService: ViewabilityService,\n    adDetails: AdDetails | LightAdDetails,\n): void => {\n    const viewabilityStandard = {\n        definition: '',\n        thresholdPercentage: weblabTreatmentToThreshold[VIEW_RATE_EXPERIMENT().getTreatment()],\n        thresholdTimeVisibleMs: weblabTreatmentToTimeout[VIEW_RATE_EXPERIMENT_TIMEOUT().getTreatment()],\n    };\n    // ViewabilityTracker for impression and measurability pixels\n    const impViewabilityTracker = createViewabilityTracker(\n        [pixels.impressionPixel, pixels.measurabilityPixel],\n        viewabilityStandard,\n        viewabilityService,\n        [],\n        adDetails,\n    );\n    impViewabilityTracker.track(placement);\n\n    // ViewabilityTracker for btrPixel\n    if (pixels.btrPixel) {\n        const btrViewabilityTracker = createViewabilityTracker(\n            [pixels.btrPixel],\n            viewabilityStandard,\n            viewabilityService,\n            [btrFirePixelValidator(placement)],\n            adDetails,\n        );\n        btrViewabilityTracker.track(placement);\n    }\n};\n","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {number} delay -                  A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)\n *                                            are most useful.\n * @param {Function} callback -               A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,\n *                                            as-is, to `callback` when the throttled-function is executed.\n * @param {object} [options] -              An object to configure options.\n * @param {boolean} [options.noTrailing] -   Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds\n *                                            while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed\n *                                            one final time after the last throttled-function call. (After the throttled-function has not been called for\n *                                            `delay` milliseconds, the internal counter is reset).\n * @param {boolean} [options.noLeading] -   Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback\n *                                            immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that\n *                                            callback will never executed if both noLeading = true and noTrailing = true.\n * @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is\n *                                            false (at end), schedule `callback` to execute after `delay` ms.\n *\n * @returns {Function} A new, throttled, function.\n */\nfunction throttle (delay, callback, options) {\n  var _ref = options || {},\n      _ref$noTrailing = _ref.noTrailing,\n      noTrailing = _ref$noTrailing === void 0 ? false : _ref$noTrailing,\n      _ref$noLeading = _ref.noLeading,\n      noLeading = _ref$noLeading === void 0 ? false : _ref$noLeading,\n      _ref$debounceMode = _ref.debounceMode,\n      debounceMode = _ref$debounceMode === void 0 ? undefined : _ref$debounceMode;\n  /*\n   * After wrapper has stopped being called, this timeout ensures that\n   * `callback` is executed at the proper times in `throttle` and `end`\n   * debounce modes.\n   */\n\n\n  var timeoutID;\n  var cancelled = false; // Keep track of the last time `callback` was executed.\n\n  var lastExec = 0; // Function to clear existing timeout\n\n  function clearExistingTimeout() {\n    if (timeoutID) {\n      clearTimeout(timeoutID);\n    }\n  } // Function to cancel next exec\n\n\n  function cancel(options) {\n    var _ref2 = options || {},\n        _ref2$upcomingOnly = _ref2.upcomingOnly,\n        upcomingOnly = _ref2$upcomingOnly === void 0 ? false : _ref2$upcomingOnly;\n\n    clearExistingTimeout();\n    cancelled = !upcomingOnly;\n  }\n  /*\n   * The `wrapper` function encapsulates all of the throttling / debouncing\n   * functionality and when executed will limit the rate at which `callback`\n   * is executed.\n   */\n\n\n  function wrapper() {\n    for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) {\n      arguments_[_key] = arguments[_key];\n    }\n\n    var self = this;\n    var elapsed = Date.now() - lastExec;\n\n    if (cancelled) {\n      return;\n    } // Execute `callback` and update the `lastExec` timestamp.\n\n\n    function exec() {\n      lastExec = Date.now();\n      callback.apply(self, arguments_);\n    }\n    /*\n     * If `debounceMode` is true (at begin) this is used to clear the flag\n     * to allow future `callback` executions.\n     */\n\n\n    function clear() {\n      timeoutID = undefined;\n    }\n\n    if (!noLeading && debounceMode && !timeoutID) {\n      /*\n       * Since `wrapper` is being called for the first time and\n       * `debounceMode` is true (at begin), execute `callback`\n       * and noLeading != true.\n       */\n      exec();\n    }\n\n    clearExistingTimeout();\n\n    if (debounceMode === undefined && elapsed > delay) {\n      if (noLeading) {\n        /*\n         * In throttle mode with noLeading, if `delay` time has\n         * been exceeded, update `lastExec` and schedule `callback`\n         * to execute after `delay` ms.\n         */\n        lastExec = Date.now();\n\n        if (!noTrailing) {\n          timeoutID = setTimeout(debounceMode ? clear : exec, delay);\n        }\n      } else {\n        /*\n         * In throttle mode without noLeading, if `delay` time has been exceeded, execute\n         * `callback`.\n         */\n        exec();\n      }\n    } else if (noTrailing !== true) {\n      /*\n       * In trailing throttle mode, since `delay` time has not been\n       * exceeded, schedule `callback` to execute `delay` ms after most\n       * recent execution.\n       *\n       * If `debounceMode` is true (at begin), schedule `clear` to execute\n       * after `delay` ms.\n       *\n       * If `debounceMode` is false (at end), schedule `callback` to\n       * execute after `delay` ms.\n       */\n      timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);\n    }\n  }\n\n  wrapper.cancel = cancel; // Return the wrapper function.\n\n  return wrapper;\n}\n\n/* eslint-disable no-undefined */\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {number} delay -               A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Function} callback -          A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n *                                        to `callback` when the debounced-function is executed.\n * @param {object} [options] -           An object to configure options.\n * @param {boolean} [options.atBegin] -  Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n *                                        after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n *                                        (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n *\n * @returns {Function} A new, debounced function.\n */\n\nfunction debounce (delay, callback, options) {\n  var _ref = options || {},\n      _ref$atBegin = _ref.atBegin,\n      atBegin = _ref$atBegin === void 0 ? false : _ref$atBegin;\n\n  return throttle(delay, callback, {\n    debounceMode: atBegin !== false\n  });\n}\n\nexport { debounce, throttle };\n//# sourceMappingURL=index.js.map\n","import { throttle } from 'throttle-debounce';\n\nimport { safeFunctionWrapper } from '@/components/util.js';\nimport { findDistanceFromViewport } from '@/components/viewability.js';\n\n// Pure javascript version of the delayLoad function from GPAT\nexport const delayUntil = async (firePixelAfter: string | undefined, slotElem: HTMLElement) => {\n    if (!firePixelAfter?.trim().match(/^\\d{1,4}px$/g)) {\n        return;\n    }\n    /* Implement JIT loading, render the ads when the slot that is X pixels above the Encore is viewable.\n     * X will be an adjustable variable based on the regex above.\n     */\n    return await loadJustInTime(\n        parseInt(firePixelAfter, 10),\n        slotElem,\n        (elem: HTMLElement, offset: number): boolean => {\n            const distance = findDistanceFromViewport(elem);\n            return elem && distance <= offset;\n        },\n    );\n};\n\n/*\n    Helper method to implement JIT loading\n    It will execute callback after satisfyConditionToLoadAd(slotElem, offset) return true\n*/\nconst loadJustInTime = async (\n    offset: number,\n    slotElem: HTMLElement,\n    satisfyConditionToLoadAd: (slotElem: HTMLElement, offset: number) => boolean,\n) => {\n    return new Promise<void>((r) => {\n        const positionTracker = () => {\n            if (satisfyConditionToLoadAd(slotElem, offset)) {\n                r();\n                window.removeEventListener('scroll', throttledPositionTracker);\n                window.removeEventListener('resize', throttledPositionTracker);\n            }\n        };\n\n        const throttledPositionTracker = safeFunctionWrapper(\n            throttle(20, () => {\n                positionTracker();\n            }),\n            console.error,\n        );\n        window.addEventListener('scroll', throttledPositionTracker);\n        window.addEventListener('resize', throttledPositionTracker);\n        // An initial fire is needed because certain cases the browser\n        // returns to the page to the same vertical position without calling\n        // scroll or resize\n        positionTracker();\n    });\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { observeUntilIntersection } from '@/components/intersectionObserver.js';\nimport { delayUntil } from '@/host/components/loading.js';\nimport { getPlacement, type PlacementLookupSource } from '@/host/components/placement.js';\n\n/**\n * Waits for any configured pixel delay, then waits until the ad is in the DOM and visible.\n */\nexport const waitUntilReadyForTracking = async (adDetails: AdDetails, lookupSource: PlacementLookupSource) => {\n    const placement = getPlacement(adDetails, { lookupSource });\n\n    if (adDetails.firePixelsAfter) {\n        await delayUntil(adDetails.firePixelsAfter, placement);\n    }\n\n    // We used to need to check for prerender but no longer\n    // https://groups.google.com/a/chromium.org/g/blink-reviews/c/hddZM1HibrY\n    // https://udn.realityripple.com/docs/Web/API/Document/visibilityState\n    // Once we have a either a hidden or visible document then we can begin to check for the intersection\n    // Never resolves for a detached placement; a re-attached slot reloads the creative and tracks again\n    await observeUntilIntersection(\n        placement,\n        { root: hasFixedPositionAncestor(placement) ? VIEWPORT_ROOT : document.documentElement },\n        adDetails,\n    );\n};\n\n/** Null root tells IntersectionObserver to use the viewport as the root */\nconst VIEWPORT_ROOT = null;\n\n/**\n * Function for returning if an element has an ancestor with css set to position:fixed.\n * @param element to check ancestors for\n * @return returns a boolean on if the given element has a fixed position ancestor or not\n */\nconst hasFixedPositionAncestor = (element: HTMLElement): boolean => {\n    let currentParent: HTMLElement | null = element;\n    while (currentParent) {\n        // we need to use computed style because fixed position may be inherited/computed and not set inline\n        const parentStyle = window.getComputedStyle(currentParent, null);\n        if (parentStyle.getPropertyValue('position') === 'fixed') {\n            return true;\n        }\n        currentParent = currentParent.parentElement;\n    }\n\n    return false;\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { toPlacement } from '@/components/pixels/pixel.js';\nimport { mapToBtrPixel } from '@/components/pixels/pixelMapper.js';\nimport { isViewRateExperimentEnabled } from '@/components/viewRateExperimentUtil.js';\nimport { getPlacement } from '@/host/components/placement.js';\nimport { waitUntilReadyForTracking } from '@/host/components/waitUntilReadyForTracking.js';\n\nexport const sendEventCreativeBeginToRenderHandler = async (adDetails: AdDetails) => {\n    // Do nothing: use view rate IO to fire BTR pixel\n    if (isViewRateExperimentEnabled(Number(adDetails.adCreativeMetaData.adProgramId))) return;\n\n    await waitUntilReadyForTracking(adDetails, 'creative-btr');\n\n    mapToBtrPixel(adDetails)?.fire(toPlacement(adDetails, getPlacement(adDetails, { lookupSource: 'creative-btr' })));\n};\n","export function addCustomEventListener<T>(target: EventTarget, type: string, handler: (event: CustomEvent<T>) => void) {\n    target.addEventListener(type, ((e: Event) => {\n        handler(e as CustomEvent<T>);\n    }) as EventListener);\n}\n","import { addCustomEventListener } from '@/components/events/customEvents.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport { getVideo } from '@/light-ad/domain/helpers/getVideo.js';\n\nexport const SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT = 'sfVideoContinuousPlaytimeSeconds';\n\nexport type SfVideoContinuousPlaytimeEventDetail = {\n    sfVideoContinuousPlaytimeSeconds: number;\n};\n\nexport const createSafeFrameVideoFirePixelValidator = (placement: Placement): FirePixelValidator => {\n    let sfVideoContinuousPlaytimeSeconds = 0;\n\n    addCustomEventListener<SfVideoContinuousPlaytimeEventDetail>(\n        placement.div,\n        SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT,\n        (event) => {\n            sfVideoContinuousPlaytimeSeconds = event.detail.sfVideoContinuousPlaytimeSeconds;\n        },\n    );\n\n    return {\n        shouldFirePixel(): boolean {\n            return sfVideoContinuousPlaytimeSeconds >= 2;\n        },\n    };\n};\n\nexport const createLightAdVideoFirePixelValidator = async (element: HTMLElement): Promise<FirePixelValidator> => {\n    const video = await getVideo(element);\n\n    let playbackStartTime = 0;\n    let continuousPlaytime = 0;\n\n    video.addEventListener('play', () => {\n        continuousPlaytime = 0;\n        playbackStartTime = performance.now();\n    });\n\n    video.addEventListener('pause', () => (continuousPlaytime = 0));\n\n    video.addEventListener('ended', () => (continuousPlaytime = 0));\n\n    video.addEventListener('timeupdate', () => {\n        if (!video.paused) {\n            continuousPlaytime = performance.now() - playbackStartTime;\n        }\n    });\n\n    return {\n        shouldFirePixel(): boolean {\n            return continuousPlaytime >= 2000;\n        },\n    };\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { mapToSkanImpressionPixel, mapToSkanViewPixel } from '@/components/pixels/pixelMapper.js';\n\n/**\n * Takes the placement resolved at creative load; re-looking it up here would return null if the slot was detached meanwhile.\n */\nexport const enableSkanViewabilityTracker = async (adDetails: AdDetails, placement: Placement) => {\n    await mapToSkanImpressionPixel(adDetails)?.fire(placement);\n    mapToSkanViewPixel(adDetails)?.track(placement);\n};\n","import { createObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { ViewPixelOptionsData } from '@/components/commands.js';\nimport { toPlacement, type Placement } from '@/components/pixels/pixel.js';\nimport {\n    createIabViewPixel,\n    mapToBtrPixel,\n    mapToImpressionPixel,\n    mapToMeasurabilityPixel,\n} from '@/components/pixels/pixelMapper.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport { createSafeFrameVideoFirePixelValidator } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport { createViewabilityService } from '@/components/pixels/services/viewabilityServiceImpl.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\nimport { isViewRateExperimentEnabled, trackViewRateExperiment } from '@/components/viewRateExperimentUtil.js';\nimport { getPlacement } from '@/host/components/placement.js';\nimport { enableSkanViewabilityTracker } from '@/host/components/skanViewabilityTracker.js';\nimport { waitUntilReadyForTracking } from '@/host/components/waitUntilReadyForTracking.js';\n\nexport const sendEventCreativeLoadedHandler = async (adDetails: AdDetails, data: ViewPixelOptionsData) => {\n    const placementDiv = getPlacement(adDetails, { lookupSource: 'creative-load' });\n    await waitUntilReadyForTracking(adDetails, 'creative-load');\n    const placement = toPlacement(adDetails, placementDiv);\n\n    btr.set(placement, data.isBtr);\n\n    if (isViewRateExperimentEnabled(Number(adDetails.adCreativeMetaData.adProgramId))) {\n        const obstructionDetectionService = createObstructionDetectionService();\n        trackViewRateExperiment(\n            placement,\n            {\n                impressionPixel: mapToImpressionPixel(adDetails),\n                btrPixel: mapToBtrPixel(adDetails),\n                measurabilityPixel: mapToMeasurabilityPixel(adDetails),\n            },\n            createViewabilityService(obstructionDetectionService, adDetails),\n            adDetails,\n        );\n    } else {\n        mapToMeasurabilityPixel(adDetails).fire(placement);\n    }\n\n    enableSkanViewabilityTracker(adDetails, placement);\n\n    (await getIabViewPixel(adDetails, placement)).track(placement);\n};\n\nconst getIabViewPixel = async (adDetails: AdDetails, placement: Placement): Promise<ViewPixel> => {\n    const videoFirePixelValidator = () => Promise.resolve(createSafeFrameVideoFirePixelValidator(placement));\n    return createIabViewPixel(adDetails.mediaType, placement.div, adDetails, videoFirePixelValidator);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { DETACHED_PLACEMENT_REUSE_WEBLAB } from '@/components/weblabs.js';\n\n// ponytail: holds removed nodes until page unload; bounded by the ads on one page.\nconst knownIFrames = new Map<string, HTMLIFrameElement>();\n\nexport const getIFrame = (adDetails: AdDetails): HTMLIFrameElement => {\n    const { adUnitIframeId } = adDetails;\n    const iframe = document.getElementById(adUnitIframeId) as HTMLIFrameElement | null;\n    if (iframe) {\n        knownIFrames.set(adUnitIframeId, iframe);\n        return iframe;\n    }\n\n    const known = knownIFrames.get(adUnitIframeId);\n    emitMetric({\n        metricName: known ? 'html:element:detached:iframe' : 'html:element:missing:iframe',\n        adDetails,\n        deduplicationKey: adDetails.placementId,\n    });\n\n    return (DETACHED_PLACEMENT_REUSE_WEBLAB().is('t1') ? known : null) as HTMLIFrameElement;\n};\n","import type {\n    GeometricInformation,\n    SelfRelativeAndInView,\n} from '@amzn/safe-frame-client/dist/types/src/IABSafeFrameClient.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { SafeFrameExtBridge } from '@/components/bridge/safeFrameExt/safeFrameExtBridge.js';\nimport { getIFrame } from '@/host/components/iframe.js';\n\nconst ALL_WHOLE_PERCENT_NUMBERS = Array.from({ length: 100 }, (_, i) => (i + 1) / 100);\n\n/** Creates an observer that transmits geometry at every whole-percent visibility threshold. */\nexport const sendSafeFrameExtOnIntersection = (adDetails: AdDetails, bridge: SafeFrameExtBridge) => {\n    const iframe = getIFrame(adDetails);\n    if (!iframe) return;\n\n    new IntersectionObserver((entries) => entries.forEach((entry) => sendSafeFrameExt(bridge, entry)), {\n        threshold: ALL_WHOLE_PERCENT_NUMBERS,\n    }).observe(iframe);\n};\n\n/**\n * The `geom.self` position fields shared by both messages. `w`/`h` come from the iframe's offset size\n * rather than the rect, so a CSS transform does not change them.\n */\nconst toSelfPosition = (rect: DOMRectReadOnly, iframe: HTMLIFrameElement) => ({\n    t: rect.top,\n    l: rect.left,\n    r: rect.right,\n    b: rect.bottom,\n    z: 1,\n    w: iframe.offsetWidth,\n    h: iframe.offsetHeight,\n});\n\n/**\n * Sends one `$sf.ext` snapshot for an observer entry: `geom.self` position, per-axis visible\n * fractions, the intersection ratio and the rounded `inViewPercentage`.\n */\nconst sendSafeFrameExt = (\n    bridge: SafeFrameExtBridge,\n    { target, intersectionRect, boundingClientRect, intersectionRatio }: IntersectionObserverEntry,\n): void => {\n    const iframe = target as HTMLIFrameElement;\n    const percentVisibleOnX = intersectionRect.width / boundingClientRect.width;\n    const percentVisibleOnY = intersectionRect.height / boundingClientRect.height;\n\n    bridge.populateSafeFrameExt({\n        geom: {\n            self: {\n                ...toSelfPosition(boundingClientRect, iframe),\n                xiv: percentVisibleOnX,\n                yiv: percentVisibleOnY,\n                iv: intersectionRatio,\n            },\n        } as Partial<GeometricInformation> as GeometricInformation,\n        inViewPercentage: Math.round(intersectionRatio * 100),\n    });\n};\n\n/** Measures the iframe and sends its current position as a `populateGeom` message. */\nconst sendGeom = (iframe: HTMLIFrameElement, bridge: SafeFrameExtBridge): void => {\n    bridge.populateGeom({\n        geom: {\n            self: toSelfPosition(\n                iframe.getBoundingClientRect(),\n                iframe,\n            ) as Partial<SelfRelativeAndInView> as SelfRelativeAndInView,\n        } as Partial<GeometricInformation> as GeometricInformation,\n    });\n};\n\n/** Starts an unconditional 250ms geom poll that runs for the ad's whole page lifetime. */\nexport const sendGeomOnInterval = (adDetails: AdDetails, bridge: SafeFrameExtBridge): void => {\n    const iframe = getIFrame(adDetails);\n\n    if (!iframe) return;\n\n    setInterval(() => sendGeom(iframe, bridge), 250);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { getIFrame } from '@/host/components/iframe.js';\n\n/**\n * Observe-only instrumentation: emit a metric every time the SafeFrame iframe\n * sends a postMessage to its parent. Listens host-side and filters by the\n * iframe's contentWindow so the client stays untouched.\n *\n * @see https://t.corp.amazon.com/V1876292536\n * @see https://shepherd.a2z.com/issues/b313f2d5-12a7-4d99-bf40-c0ced6822379\n */\nexport const logIframePostMessage = (adDetails: AdDetails): void => {\n    const iframe = getIFrame(adDetails);\n    if (!iframe) return;\n\n    window.addEventListener('message', (event: MessageEvent) => {\n        if (event.source !== iframe.contentWindow) return;\n        emitMetric({ metricName: 'shepherd:postmessage:parent', metricValue: 1, adDetails });\n    });\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const EWC_EXIST_CLASS_NAME = 'nav-ewc-persistent-hover';\nexport const EWC_SELECTOR = 'div#nav-flyout-ewc';\nconst NAV_CART_TOGGLE_CLASS = 'nav-cart';\nexport const NAV_CART_FULL_WIDTH_VAR = '--nav-cart-full-width';\nexport const NAV_CART_HALF_WIDTH_VAR = '--nav-cart-half-width';\n\nexport const toggleNavCartClassOnMutation = (adDetails: AdDetails): void => {\n    const target = document.documentElement;\n    const placementDiv = getPlacement(adDetails, { lookupSource: 'safe-frame-ready' });\n    if (!placementDiv) return;\n\n    toggleNavCartClass(target, placementDiv);\n\n    new MutationObserver((mutations) => {\n        for (const mutation of mutations) {\n            if (mutation.type === 'attributes' && mutation.attributeName === 'class') {\n                const targetElement = mutation.target as HTMLElement;\n                toggleNavCartClass(targetElement, placementDiv);\n            }\n        }\n    }).observe(target, {\n        attributes: true,\n        attributeFilter: ['class'],\n    });\n};\n\nconst toggleNavCartClass = (targetElement: Element, placementDiv: HTMLElement) => {\n    if (targetElement.classList.contains(EWC_EXIST_CLASS_NAME)) {\n        placementDiv.classList.add(NAV_CART_TOGGLE_CLASS);\n        const ewcWidth = getEwcWidth();\n        placementDiv.style.setProperty(NAV_CART_FULL_WIDTH_VAR, `${ewcWidth}px`);\n        placementDiv.style.setProperty(NAV_CART_HALF_WIDTH_VAR, `${ewcWidth / 2}px`);\n    } else {\n        placementDiv.classList.remove(NAV_CART_TOGGLE_CLASS);\n    }\n};\n\nconst getEwcWidth = (): number => {\n    const ewc = document.querySelector(EWC_SELECTOR);\n    return ewc instanceof HTMLElement ? ewc.offsetWidth : 0;\n};\n","import { sendLatencyMetric } from '@amzn/grandprix-runtime/src/instrumentation/latency.js';\n\nimport type { Context } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { CustomMessageBridge } from '@/components/bridge/customMessage/customMessageBridge.js';\nimport { dispatchClickForCsaAttribution } from '@/components/bridge/events/dispatchClickForCsaAttribution.js';\nimport type { EventsBridge, OnCreativeLoadPayload, OnErrorPayload } from '@/components/bridge/events/eventsBridge.js';\nimport { shouldSafeFrameFireLoadedMetrics } from '@/components/bridge/events/shouldSafeFrameFireLoadedMetrics.js';\nimport { createSafeFrameExtBridgeSender } from '@/components/bridge/safeFrameExt/safeFrameExtBridgeSender.js';\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport { logAssetMetrics } from '@/components/metrics/assetMetricLogger.js';\nimport { logCoordinates } from '@/components/metrics/coordinate-logger.js';\nimport { emitMetric, emitWeblabMetric } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { mark, PERF_SF_HOST } from '@/components/perf.js';\nimport { toPlacement } from '@/components/pixels/pixel.js';\nimport { mapToImpressionPixel } from '@/components/pixels/pixelMapper.js';\nimport {\n    fireRetailClickTrackingFromCache,\n    getClickTrackingUrl,\n} from '@/host/api-client/handlers/retailClickTrackingHandler.js';\nimport { sendEventCreativeBeginToRenderHandler } from '@/host/api-client/handlers/sendEventCreativeBeginToRenderHandler.js';\nimport { sendEventCreativeLoadedHandler } from '@/host/api-client/handlers/sendEventCreativeLoadedHandler.js';\nimport { sendGeomOnInterval, sendSafeFrameExtOnIntersection } from '@/host/api-client/handlers/sendSafeFrameExt.js';\nimport { logIframePostMessage } from '@/host/components/logIframePostMessage.js';\nimport { getPlacement } from '@/host/components/placement.js';\nimport { waitUntilReadyForTracking } from '@/host/components/waitUntilReadyForTracking.js';\nimport { toggleNavCartClassOnMutation } from '@/host/slotSpecific/navCartClassToggle.js';\n\nexport const createEventsBridgeReceiver = (customMessage: CustomMessageBridge): ReceiverImpl<EventsBridge> => {\n    // One receiver per iframe, so one URL per receiver\n    let clickTrackingUrl: string | undefined;\n\n    return {\n        onSafeFrameReady({ adDetails, timestamp, messagePort }: Context, startTime: number): void {\n            emitMetric({\n                metricName: 'event:start',\n                adDetails,\n                timestamp,\n                metricValue: startTime,\n            });\n            emitWeblabMetric(adDetails);\n            sendLatencyMetric({ adDetails, latencyEvent: 'bb', scope: 'SF', timestamp });\n\n            mark(PERF_SF_HOST, 'safeFrameReady', adDetails);\n\n            //Exposed the resize event to SafeFrame window\n            window.addEventListener('resize', () => {\n                customMessage.dispatch('resize', {\n                    height: window.innerHeight,\n                    width: window.innerWidth,\n                });\n            });\n\n            toggleNavCartClassOnMutation(adDetails);\n            const safeFrameExtBridge = createSafeFrameExtBridgeSender(messagePort, adDetails);\n            sendSafeFrameExtOnIntersection(adDetails, safeFrameExtBridge);\n            sendGeomOnInterval(adDetails, safeFrameExtBridge);\n            logCoordinates(adDetails);\n            logAssetMetrics(adDetails);\n            logIframePostMessage(adDetails);\n        },\n\n        async onPreCreativeWrite(\n            { adDetails, timestamp }: Context,\n            latency: number,\n            fireImpressionInHost: boolean,\n        ): Promise<void> {\n            emitMetric({\n                metricName: 'event:prewrite',\n                adDetails,\n                timestamp,\n                metricValue: latency,\n            });\n\n            if (fireImpressionInHost) {\n                await waitUntilReadyForTracking(adDetails, 'pre-creative-write');\n                await mapToImpressionPixel(adDetails).fire(\n                    toPlacement(adDetails, getPlacement(adDetails, { lookupSource: 'pre-creative-write' })),\n                );\n            }\n        },\n\n        onPostCreativeWrite({ adDetails, timestamp }: Context, latency: number): void {\n            emitMetric({\n                metricName: 'event:postwrite',\n                adDetails,\n                timestamp,\n                metricValue: latency,\n            });\n            sendLatencyMetric({ adDetails, latencyEvent: 'af', scope: 'SF', timestamp });\n        },\n\n        onCreativeBeginToRender({ adDetails, timestamp }: Context, latency: number): void {\n            emitMetric({\n                metricName: 'event:btr',\n                adDetails,\n                timestamp,\n                metricValue: latency,\n            });\n            if (shouldSafeFrameFireLoadedMetrics(adDetails)) {\n                sendLatencyMetric({ adDetails, latencyEvent: 'cf', scope: 'SF', timestamp });\n            }\n            sendEventCreativeBeginToRenderHandler(adDetails);\n        },\n\n        onCreativeLoad(\n            { adDetails, timestamp }: Context,\n            { isImageOnlyTemplate, isBtr, isBtrUnknown, latency }: OnCreativeLoadPayload,\n        ): void {\n            emitMetric({\n                metricName: 'event:load',\n                adDetails,\n                timestamp,\n                metricValue: latency,\n            });\n            if (isBtrUnknown && !isBtr) {\n                emitMetric({ metricName: 'pixel:imp:btr:unknown', adDetails });\n            } else if (!isBtr) {\n                emitMetric({ metricName: 'pixel:imp:btr:missing', adDetails });\n            }\n            if (shouldSafeFrameFireLoadedMetrics(adDetails)) {\n                if (!isBtr) {\n                    sendLatencyMetric({ adDetails, latencyEvent: 'cf', scope: 'SF', timestamp });\n                }\n                sendLatencyMetric({ adDetails, latencyEvent: 'ld', scope: 'SF', timestamp });\n            }\n\n            clickTrackingUrl = getClickTrackingUrl(adDetails) ?? clickTrackingUrl;\n\n            if (isImageOnlyTemplate) {\n                getPlacement(adDetails, { lookupSource: 'creative-load' }).classList.add('is-image-oo');\n            }\n\n            sendEventCreativeLoadedHandler(adDetails, { isBtr });\n        },\n\n        onError({ adDetails }: Context, { code, isBTR, error, source, lineno, colno }: OnErrorPayload): void {\n            if (error) {\n                emitErrorLog({ error, adDetails, code, source, lineno, colno });\n            }\n            if (code === 'client-setup') {\n                emitErrorLog({ message: 'Failed to setup creative', error, adDetails, code });\n            }\n            if (!isBTR && (code === 'client-error' || code === 'client-setup')) {\n                collapsePlacement({ adDetails, code });\n            }\n        },\n\n        onClick({ adDetails }: Context): void {\n            fireRetailClickTrackingFromCache(adDetails, clickTrackingUrl);\n            dispatchClickForCsaAttribution(adDetails);\n        },\n    };\n};\n","import type { SFClientVideoAPI } from '@amzn/safe-frame-client-amzn';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { CsaBridge } from '@/components/bridge/csa/csaBridge.js';\nimport type { CsmBridge } from '@/components/bridge/csm/csmBridge.js';\nimport type { CustomMessageBridge } from '@/components/bridge/customMessage/customMessageBridge.js';\nimport type { EventsBridge } from '@/components/bridge/events/eventsBridge.js';\nimport type { MashBridge } from '@/components/bridge/mash/mashBridge.js';\nimport type { MSFClientBridge } from '@/components/bridge/msfclient/msfClientBridge.js';\nimport type { SafeFrameExtBridge } from '@/components/bridge/safeFrameExt/safeFrameExtBridge.js';\nimport type { SFClientBridge } from '@/components/bridge/sfclient/sfClientBridge.js';\nimport type { NestedKeyOf } from '@/components/utils/nestedKeyOf.js';\n\n/**\n * Central registry of all bridge interfaces.\n *\n * Each entry maps a namespace key to the bridge interface that defines\n * the methods the SafeFrame client iframe can invoke on the host page.\n * Add new bridges here as they are created.\n *\n * If you add a method to a bridge interface, you MUST add the corresponding\n * 'sf:bridge:<Namespace>:<method>' entry to BRIDGE_METRIC_NAMES in csaMetrics.ts.\n * This is enforced by a unit test in bridgeMetricNames.test.ts.\n */\nexport interface BridgeRegistry {\n    Csa: CsaBridge;\n    Csm: CsmBridge;\n    CustomMessage: CustomMessageBridge;\n    Events: EventsBridge;\n    SFClient: SFClientBridge;\n    SafeFrameExt: SafeFrameExtBridge;\n    Video: SFClientVideoAPI;\n    Mash: MashBridge;\n    MSFClient: MSFClientBridge;\n}\n\n/**\n * A bridge interface method that only exists to satisfy the type on the side that never receives\n * it (e.g. a request method the client sends but never handles itself, or a reply method only the\n * client answers) throws this. `bindReceiver` catches the throw and logs it as a bridge error\n * rather than crashing, so this is a safe no-op if the method is ever invoked in error.\n *\n * A factory, not a shared `Error` instance: constructing at each throw site keeps the stack trace\n * pointing at the actual call, and (unlike a top-level `new Error(...)`) has no side effect the\n * bundler must retain, so bridge.ts's runtime module stays out of a bundle that never calls this.\n */\nexport const bridgeOnlyError = (): Error => new Error('wrong side');\n\n/**\n * The subset of {@link Context} that travels over the wire inside a\n * {@link BridgeMessage}. The host bridge adds the {@link MessagePort}\n * after receipt to produce a full {@link Context}.\n */\nexport interface WireContext {\n    /** Identity of the ad slot that originated the message. */\n    adDetails: AdDetails;\n    /** Wall-clock time captured at the moment the message is sent (`new Date()`). */\n    timestamp: Date;\n}\n\n/**\n * Metadata attached to every message dispatched to bridge receivers.\n *\n * Carries the ad slot identity, a wall-clock timestamp for\n * cross-system correlation, and the {@link MessagePort} connected to\n * the client iframe so handlers can route messages back.\n *\n * The sender puts {@link adDetails} and {@link timestamp} on the wire\n * ({@link WireContext}); {@link bindReceiver} injects {@link messagePort} before dispatching.\n */\nexport interface Context extends WireContext {\n    /** Port connected to the client iframe for routing messages back. */\n    messagePort: MessagePort;\n}\n\n/**\n * Wire format for messages sent over the {@link MessagePort} between the\n * SafeFrame client iframe and the host page.\n *\n * Multiple bridges (CSM metrics, lifecycle events, etc.) share a single\n * port. The {@link namespace} field discriminates which bridge a message belongs\n * to, so each {@link bindReceiver} listener only processes its own traffic.\n *\n * @typeParam T - The bridge interface (e.g. `CsmBridge`). Constrains\n *               {@link method} to valid dot-notation paths via {@link NestedKeyOf}.\n */\nexport interface BridgeMessage<T = Record<string, unknown>> {\n    /** Bridge discriminator. Only listeners registered with the same string will process this message. */\n    namespace: string;\n    /** Dot-notation path to the target function inside the host implementation tree (e.g. `'ue.count'`). */\n    method: NestedKeyOf<T>;\n    /** Positional arguments forwarded to the resolved handler after the {@link Context} parameter. */\n    args: unknown[];\n    /** Contextual metadata captured at the call site. */\n    context: WireContext;\n}\n","import type { MashError, MshopMashAPI } from '@amzn/safe-frame-client-mobilesfclient';\n\nimport type { Context } from '@/components/bridge/core/bridge.js';\nimport { bridgeOnlyError } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { MashBridge } from '@/components/bridge/mash/mashBridge.js';\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\n\n/**\n * MASH's own NOT_SUPPORTED code: \"The requested method is not supported by the current\n * implementation.\" Used when the navigation cannot be attempted at all, so the creative settles on a\n * code MASH defines rather than one invented here.\n *\n * @see MASHError in SMASHAndroidCore, src/main/java/com/amazon/mobile/mash/error/MASHError.java\n * @see https://w.amazon.com/bin/view/AppWebRendering/Projects/InApp3pBrowser/APIs/\n */\nconst NOT_SUPPORTED: MashError = { code: 1003 };\n\nconst METRIC_BASE = 'sf:mash:openInApp3pBrowser';\n\n/**\n * Host-side MashBridge receiver. Built per ad rather than once per page: replies go back over the\n * client port of the iframe that asked, so the receiver builds its reply sender from that port.\n */\nexport const createMashBridgeHostReceiver = (reply: MashBridge): ReceiverImpl<MashBridge> => {\n    return {\n        /**\n         * Opens targetURL in MASH's in-app 3p browser: CCT on Android, SafariViewController on iOS,\n         * with the external browser as fallback. All three creative-facing mash browser flows funnel\n         * here.\n         *\n         * The host injects the trust-sensitive params (callerIdentifier, navigationStartTime) so\n         * creatives cannot spoof them, and owns the callbacks so MASH's outcome is counted on the host\n         * side.\n         *\n         * When MASH cannot be reached at all — no AUI P, or a mash module without ThirdPartyNavigation —\n         * the creative's failCallback is settled with {@link NOT_SUPPORTED} so it is not left waiting,\n         * and the error is rethrown for the bridge to log. The inner guard lives inside the execute\n         * callback because AUI may run it asynchronously (module registered after this call), where a\n         * throw escapes the outer try; a duplicate settle in the synchronous case is ignored by the\n         * client. A page where P exists but the mash module never registers is the one case still left\n         * unsettled, since AUI queues the callback rather than reporting that the module is absent.\n         */\n        openInApp3pBrowser: ({ adDetails }: Context, targetURL: string, replyKey: string): void => {\n            const settleUnreachable = () => reply.openInApp3pBrowserReply(replyKey, NOT_SUPPORTED);\n\n            if (!window.P) {\n                settleUnreachable();\n                throw new Error('no AUI P');\n            }\n\n            try {\n                window.P.when('mash').execute(({ ThirdPartyNavigation }: MshopMashAPI) => {\n                    try {\n                        ThirdPartyNavigation.openInApp3pBrowser({\n                            targetURL,\n                            callerIdentifier: 'ad-safeframe',\n                            navigationStartTime: Date.now(),\n                            fallbackBrowser: ThirdPartyNavigation.Browser.EXTERNAL,\n                            dismissButtonStyle: ThirdPartyNavigation.DismissButtonStyle.CLOSE,\n                            successCallback: () => {\n                                emitMetric({ metricName: `${METRIC_BASE}:success`, adDetails });\n                                reply.openInApp3pBrowserReply(replyKey);\n                            },\n                            failCallback: (error) => {\n                                emitMetric({ metricName: `${METRIC_BASE}:fail`, adDetails });\n                                reply.openInApp3pBrowserReply(replyKey, error);\n                            },\n                        });\n                    } catch (err) {\n                        settleUnreachable();\n                        throw err;\n                    }\n                });\n            } catch (err) {\n                settleUnreachable();\n                throw err;\n            }\n        },\n\n        openInApp3pBrowserReply: (): void => {\n            throw bridgeOnlyError();\n        },\n    };\n};\n","import type { Context } from '@/components/bridge/core/bridge.js';\nimport { bridgeOnlyError } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { MSFClientBridge } from '@/components/bridge/msfclient/msfClientBridge.js';\nimport { renderClickThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.js';\nimport { delayUntil } from '@/host/components/loading.js';\nimport { getPlacement } from '@/host/components/placement.js';\n\n/**\n * Host-side MSFClientBridge receiver. Built per ad rather than once per page: the onPageEvent\n * reply goes back over the client port of the iframe that asked, so the receiver builds its reply\n * sender from that port.\n */\nexport const createMSFClientBridgeHostReceiver = (reply: MSFClientBridge): ReceiverImpl<MSFClientBridge> => {\n    return {\n        onPageEvent: async ({ adDetails }: Context, eventName: string, replyKey: string): Promise<void> => {\n            await delayUntil(eventName, getPlacement(adDetails, { lookupSource: 'msf-page-event' }));\n            reply.onPageEventReply(replyKey);\n        },\n\n        onPageEventReply: (): void => {\n            throw bridgeOnlyError();\n        },\n\n        renderClickThroughAppAds: ({ adDetails }: Context, url: string): void => {\n            if (!adDetails.skAdNetwork) {\n                throw new Error('no skAdNetwork');\n            }\n            renderClickThroughAppAds(adDetails.skAdNetwork, url);\n        },\n    };\n};\n","export const isPercentage = (value: string): boolean => {\n    return value?.length > 1 && value.charAt(value.length - 1) === '%';\n};\n\nexport const makeSizeExplicitPercentOrPx = (value: string): string =>\n    isPercentage(value) ? value : `${parseInt(value)}px`;\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { isPercentage, makeSizeExplicitPercentOrPx } from '@/host/components/css.js';\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport type PlacementSize = {\n    width: string;\n    height: string;\n};\n\nexport const changeSizeHandler = (adDetails: AdDetails, size: PlacementSize) => {\n    console.debug('ChangeSize API has been deprecated');\n    if (!isChangeSizeSupported(adDetails)) return;\n\n    resizePlacement(adDetails, size);\n};\n\nconst resizePlacement = (adDetails: AdDetails, size: PlacementSize): void => {\n    if (!isAllowedSize(size)) {\n        emitErrorLog({\n            message: `Size w:'${size.width}', h:'${size.height}' is not allow-listed`,\n            adDetails,\n        });\n        return;\n    }\n\n    const div = getPlacement(adDetails, { lookupSource: 'change-size' });\n\n    if (isPercentage(size.width)) {\n        div.style.maxHeight = makeSizeExplicitPercentOrPx(size.height);\n        div.style.width = makeSizeExplicitPercentOrPx(size.width);\n        div.style.height = makeSizeExplicitPercentOrPx(size.height);\n    } else {\n        div.removeAttribute('style');\n        div.style.aspectRatio = `${parseInt(size.width)} / ${parseInt(size.height)}`;\n    }\n};\n\nconst isAllowedSize = (size: PlacementSize): boolean => {\n    const height = makeSizeExplicitPercentOrPx(size.height);\n    const width = makeSizeExplicitPercentOrPx(size.width);\n\n    const allowedSizes = [\n        { width: '100%', height: '169px' },\n        { width: '300px', height: '250px' },\n    ];\n\n    return allowedSizes.some((allowedSize) => height === allowedSize.height && width === allowedSize.width);\n};\n\nconst isChangeSizeSupported = (adDetails: AdDetails): boolean =>\n    adDetails.slotName === 'hero-quick-promo' &&\n    (adDetails.adCreativeMetaData?.adCreativeTemplateName === 'Personalized Responsive eCommerce' ||\n        !adDetails.adCreativeMetaData?.adCreativeTemplateName) &&\n    adDetails.mediaType === 'D';\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { feedbackState } from '@/components/state/page/pageState.js';\n\nexport const openModal = (parentHtmlId: string): void => {\n    for (const child of getFeedbackDiv(parentHtmlId)?.children || []) {\n        if (isFeedbackLink(child)) {\n            (child as HTMLElement).click();\n            return;\n        }\n    }\n};\n\nexport const labelRendered = (adDetails: AdDetails | LightAdDetails): void => {\n    if (feedbackState.has(adDetails.adUnitPlacementId)) return;\n    feedbackState.mark(adDetails.adUnitPlacementId);\n    emitMetric({ metricName: 'gpat:sponsored:label:rendered', adDetails });\n};\n\nconst getFeedbackDiv = (parentHtmlId: string): HTMLElement | null =>\n    document.getElementById(parentHtmlId + '_Feedback');\nconst isFeedbackLink = (childElement: Element): boolean =>\n    childElement.tagName === 'A' || childElement.tagName === 'DIV';\n","import { sendLatencyMetric } from '@amzn/grandprix-runtime/src/instrumentation/latency.js';\n\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport { changeSizeHandler } from '@/components/bridge/sfclient/changeSizeHandler.js';\nimport type { SFClientBridge } from '@/components/bridge/sfclient/sfClientBridge.js';\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport { labelRendered, openModal } from '@/components/feedback.js';\n\nexport const createSFClientBridgeReceiver = (): ReceiverImpl<SFClientBridge> => ({\n    changeSize({ adDetails }, width, height) {\n        changeSizeHandler(adDetails, { width, height });\n    },\n    collapseSlot({ adDetails }) {\n        collapsePlacement({ adDetails, code: 'creative' });\n    },\n    /**\n     * Called when the client signals the creative is fully loaded and interactive.\n     * Fires the 'cf' (critical feature) and 'ld' (loaded) latency metrics on the host side.\n     */\n    signalAdLoadedAndInteractive({ adDetails, timestamp }) {\n        sendLatencyMetric({ adDetails, latencyEvent: 'cf', scope: 'SF', timestamp });\n        sendLatencyMetric({ adDetails, latencyEvent: 'ld', scope: 'SF', timestamp });\n    },\n    feedbackLabelRendered({ adDetails }) {\n        labelRendered(adDetails);\n    },\n    feedbackOpenModal({ adDetails }) {\n        openModal(adDetails.adUnitWrapperId ?? adDetails.adUnitPlacementId);\n    },\n    isOnAmazon() {\n        throw new Error('isOnAmazon must not be called over the bridge');\n    },\n});\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\n/**\n * Wrapper functions for Homepage Video Orchestrator\n * https://quip-amazon.com/A20AAkbGNjbX/Video-Orchestrator\n * https://code.amazon.com/packages/AmazonHomepageCardAssets/blobs/mainline/--/src/gw-video-orchestrator.js\n */\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\n\ntype GwVideoOrchestrator = {\n    subscribe: (element: HTMLElement, callback: SubscribeCallback, options?: GwVideoOrchestratorOptions) => void;\n    elect: (element?: HTMLElement) => void;\n};\n\ntype SubscribeCallback = (isLeader: boolean) => void;\n\nexport type GwVideoOrchestratorOptions = {\n    minVisiblePercentForLeader?: number; // number 0 to 1. The percentage of an element in the view which is bigger than this threshold is considered onScreen. Default is 0.5.\n    priority?: number; // number 0 to 100. Highest priority wins. HERO should subscribe with 100. Default is 50.\n};\n\nconst gwVideoOrchestratorPName = 'gw-video-orchestrator';\n\nexport const subscribe = (\n    element: HTMLElement,\n    callback: SubscribeCallback,\n    adDetails: AdDetails | LightAdDetails,\n    options?: GwVideoOrchestratorOptions,\n): void => {\n    window.P?.when(gwVideoOrchestratorPName).execute((gwVideoOrchestrator: GwVideoOrchestrator) => {\n        try {\n            gwVideoOrchestrator.subscribe(element, callback, options);\n        } catch (error) {\n            emitErrorLog({\n                error,\n                message: 'Failed to subscribe to video orchestrator',\n                adDetails,\n            });\n        }\n    });\n};\n\nexport const elect = (element: HTMLElement): void => homepageElect(element);\n\nexport const unelect = (): void => homepageElect();\n\nconst homepageElect = (element?: HTMLElement): void => {\n    window.P?.when(gwVideoOrchestratorPName).execute((gwVideoOrchestrator: GwVideoOrchestrator) => {\n        gwVideoOrchestrator.elect(element);\n    });\n};\n","import type { VideoAutoplayOptions } from '@amzn/safe-frame-client-amzn';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { CustomMessageBridge } from '@/components/bridge/customMessage/customMessageBridge.js';\nimport { elect, subscribe, unelect } from '@/components/homepage/homepageVideoOrchestrator.js';\nimport { canBeInSameViewport } from '@/components/viewability.js';\nimport { getIFrame } from '@/host/components/iframe.js';\n\nlet autoplayLock: string | null = null;\n\nexport const requestVideoAutoplayHandler = (\n    adDetails: AdDetails,\n    options: VideoAutoplayOptions,\n    customMessage: CustomMessageBridge,\n) => {\n    const sendCanAutoPlayMessage = (canAutoplay: boolean) =>\n        customMessage.dispatch('videoAutoplayResponse', canAutoplay);\n\n    if (isHomepage(adDetails.pageType)) {\n        subscribe(getIFrame(adDetails), sendCanAutoPlayMessage, adDetails, options);\n    } else {\n        if (autoplayLock === adDetails.arid) {\n            sendCanAutoPlayMessage(true);\n        } else if (autoplayLock === null && noPlayingVideoNearby(getIFrame(adDetails))) {\n            autoplayLock = adDetails.arid;\n            sendCanAutoPlayMessage(true);\n        } else {\n            sendCanAutoPlayMessage(false);\n        }\n    }\n};\n\nexport const releaseVideoAutoplayHandler = () => {\n    unelect();\n    autoplayLock = null;\n};\n\nexport const haveVideoAutoplayPermissionHandler = (adDetails: AdDetails) => {\n    elect(getIFrame(adDetails));\n    autoplayLock = adDetails.arid;\n};\n\nconst isHomepage = (pageType?: string): boolean => pageType?.toLowerCase() === 'gateway';\n\nconst noPlayingVideoNearby = (element: HTMLElement): boolean => {\n    return ![...document.getElementsByTagName('video')].some(\n        (video) => !video.paused && canBeInSameViewport(element, video),\n    );\n};\n","import type { SFClientVideoAPI, VideoAutoplayOptions } from '@amzn/safe-frame-client-amzn';\n\nimport type { Context } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { CustomMessageBridge } from '@/components/bridge/customMessage/customMessageBridge.js';\nimport {\n    haveVideoAutoplayPermissionHandler,\n    releaseVideoAutoplayHandler,\n    requestVideoAutoplayHandler,\n} from '@/components/bridge/video/videoHandlers.js';\nimport { SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport type { SfVideoContinuousPlaytimeEventDetail } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const createVideoBridgeReceiver = (customMessage: CustomMessageBridge): ReceiverImpl<SFClientVideoAPI> => ({\n    updatePlayingTimeForVideo: ({ adDetails }: Context, continuousPlaybackSeconds: number): void => {\n        const placement = getPlacement(adDetails, { lookupSource: 'video' });\n        const event = new CustomEvent<SfVideoContinuousPlaytimeEventDetail>(\n            SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT,\n            {\n                detail: { sfVideoContinuousPlaytimeSeconds: continuousPlaybackSeconds },\n            },\n        );\n        placement.dispatchEvent(event);\n    },\n\n    requestVideoAutoplay: ({ adDetails }: Context, options?: VideoAutoplayOptions): void => {\n        requestVideoAutoplayHandler(adDetails, options ?? {}, customMessage);\n    },\n\n    releaseVideoAutoplay: (): void => {\n        releaseVideoAutoplayHandler();\n    },\n\n    haveVideoAutoplayPermission: ({ adDetails }: Context): void => {\n        haveVideoAutoplayPermissionHandler(adDetails);\n    },\n});\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nexport const resolveAdDetailsFromIframe = (iframeId: string): AdDetails => {\n    const name = document.getElementById(iframeId)?.getAttribute('name');\n    if (!name) throw new Error(`No iframe name for \"${iframeId}\"`);\n    return JSON.parse(name) as AdDetails;\n};\n","import type { HostBootstrapApi } from '@amzn/grandprix-runtime/src/host-contract.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { bindReceiver } from '@/components/bridge/core/receiver.js';\nimport { createSender } from '@/components/bridge/core/sender.js';\nimport { createCsaBridgeReceiver } from '@/components/bridge/csa/csaBridgeReceiver.js';\nimport { createCsmBridgeReceiver } from '@/components/bridge/csm/csmBridgeReceiver.js';\nimport { createEventsBridgeReceiver } from '@/components/bridge/events/eventsBridgeReceiver.js';\nimport { createMashBridgeHostReceiver } from '@/components/bridge/mash/mashBridgeHost.js';\nimport { createMSFClientBridgeHostReceiver } from '@/components/bridge/msfclient/msfClientBridgeHost.js';\nimport { createSFClientBridgeReceiver } from '@/components/bridge/sfclient/sfClientBridgeReceiver.js';\nimport { createVideoBridgeReceiver } from '@/components/bridge/video/videoBridgeReceiver.js';\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { mark, PERF_SF_HOST } from '@/components/perf.js';\nimport { resolveAdDetailsFromIframe } from '@/host/app/resolveAdDetailsFromIframe.js';\n\nexport const createSafeFrameHost = (): HostBootstrapApi => {\n    /**\n     * Ports this host has already bound. A page that re-renders a slot can hand the same port to\n     * setupMessageChannel more than once (each render leaves another sfReady listener behind), and\n     * binding again would run every receiver once per call, multiplying host metrics such as COD.\n     */\n    const boundPorts = new WeakSet<MessagePort>();\n\n    return {\n        setupMessageChannel: async (\n            messagePortFromClient: MessagePort,\n            adDetailsOrIframeId: AdDetails | string,\n        ): Promise<void> => {\n            const adDetails: AdDetails =\n                typeof adDetailsOrIframeId === 'string'\n                    ? resolveAdDetailsFromIframe(adDetailsOrIframeId)\n                    : adDetailsOrIframeId;\n\n            if (boundPorts.has(messagePortFromClient)) {\n                emitMetric({ metricName: 'sf:host:port:rebind', adDetails });\n                return;\n            }\n\n            try {\n                mark(PERF_SF_HOST, 'Start setupMessagePort', adDetails);\n\n                const customMessage = createSender(messagePortFromClient, 'CustomMessage', adDetails);\n\n                bindReceiver(messagePortFromClient, 'Events', createEventsBridgeReceiver(customMessage));\n                bindReceiver(messagePortFromClient, 'Csm', createCsmBridgeReceiver());\n                bindReceiver(messagePortFromClient, 'Csa', createCsaBridgeReceiver());\n                bindReceiver(messagePortFromClient, 'SFClient', createSFClientBridgeReceiver());\n                bindReceiver(messagePortFromClient, 'Video', createVideoBridgeReceiver(customMessage));\n                bindReceiver(\n                    messagePortFromClient,\n                    'Mash',\n                    createMashBridgeHostReceiver(createSender(messagePortFromClient, 'Mash', adDetails)),\n                );\n                bindReceiver(\n                    messagePortFromClient,\n                    'MSFClient',\n                    createMSFClientBridgeHostReceiver(createSender(messagePortFromClient, 'MSFClient', adDetails)),\n                );\n\n                messagePortFromClient.start();\n                // Only a completed bind counts, so a port whose setup threw can still be set up again.\n                boundPorts.add(messagePortFromClient);\n            } catch (e) {\n                collapsePlacement({ adDetails, code: 'host-setup' });\n                emitErrorLog({ message: 'setupMessageChannel failed', error: e, adDetails });\n            }\n        },\n    };\n};\n","import { mark, PERF_SF_HOST } from '@/components/perf.js';\nimport { createSafeFrameHost } from '@/host/app/safeFrameHost.js';\n\nexport const initSafeFrameHost = (name: string): void => {\n    mark(PERF_SF_HOST, name);\n    if (window.APE_SF) return;\n\n    mark(PERF_SF_HOST, `${name} init`);\n    window.APE_SF = createSafeFrameHost();\n};\n","import { initSafeFrameHost } from '@/host/app/initSafeFrameHost.js';\n\ninitSafeFrameHost('DAsf');\n"],"x_google_ignoreList":[1,2,6,14,15,16,28,29,30,31,32,33,54,55,58],"mappings":"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"}