{"version":3,"file":"DAsf-1.50.ivzzhe4y.js","names":[],"sources":["../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/logging.ts","../../../../src/js/components/util.ts","../../../../src/js/components/perf.ts","../../../../src/js/components/bridge/csa/csaBridgeReceiver.ts","../../../../src/js/components/bridge/csm/csmBridgeReceiver.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/browseNode.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csm/util.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csm/counter.ts","../../../../src/js/components/bridge/core/sender.ts","../../../../src/js/components/bridge/safeFrameExt/safeFrameExtBridgeSender.ts","../../../../src/js/components/cache.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csa/events.ts","../../../../src/js/components/pageState/pageState.ts","../../../../src/js/components/weblabs.ts","../../../../src/js/components/metrics/csaMetrics.ts","../../../../src/js/components/metrics/assetMetricLogger.ts","../../../../src/js/host/components/placement.ts","../../../../src/js/components/metrics/coordinate-logger.ts","../../../../src/js/components/collapsePlacement.ts","../../../../src/js/host/api-client/handlers/collapseSlotHandler.ts","../../../../src/js/host/api-client/handlers/retailClickTrackingHandler.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/placement/placementState.ts","../../../../src/js/components/pixels/firePixel.ts","../../../../src/js/components/pixels/services/pixelLogger.ts","../../../../src/js/components/pixels/pixel.ts","../../../../src/js/components/pixels/pixelIdentifiers.ts","../../../../src/js/components/pixels/viewPixelUtil.ts","../../../../src/js/host/slotSpecific/placementSafezone.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/client/api/client/measurementMethods.ts","../../../../src/js/components/aax/aax.ts","../../../../src/js/components/urlQueryParams/addJSONQueryParamToURL.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","../../../../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/executeWhenConditionMet.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","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csa/latency.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csm/latency.ts","../../../../src/js/host/components/latency.ts","../../../../src/js/host/slotSpecific/navCartClassToggle.ts","../../../../src/js/components/bridge/events/eventsBridgeReceiver.ts","../../../../src/js/components/homepage/homepageVideoOrchestrator.ts","../../../../src/js/components/bridge/video/videoHandlers.ts","../../../../src/js/components/bridge/video/videoBridgeReceiver.ts","../../../../src/js/components/feedback.ts","../../../../src/js/host/components/css.ts","../../../../src/js/host/api-client/handlers/changeSizeHandler.ts","../../../../src/js/host/api-client/CommonSupportedCommands.ts","../../../../src/js/host/api-client/hostMessageReceiver.ts","../../../../src/js/host/api-client/hostMessageSender.ts","../../../../src/js/components/utils/hasOwn.ts","../../../../src/js/components/bridge/core/receiver.ts","../../../../src/js/host/api-page/safeframe-api.ts","../../../../src/js/host/context/HostContext.ts","../../../../src/js/host/api-page/safeframe-api-factory.ts","../../../../src/js/host/initSafeframeHost.ts","../../../../src/js/host/DAsf.ts"],"sourcesContent":["import { LogLevel } from './csmGlobal.js';\n\n/*\n * All Error logging should go through these 2 functions.\n * Issues which degrade customer experience should call {@link logFatal}\n * Log level descriptions: https://w.amazon.com/bin/view/ClientSideMetrics/UserDocs/JavascriptErrors/#Error_levels\n * This will send messages/errors to RTLA, which can be analyzed to provide more information.\n */\n\n/**\n * Logs a message to the console, with console.debug(message)\n * @param message text send to console\n */\nexport const logDebug = (message: string): void => {\n    console.debug(message);\n};\n\n/**\n * Sends a warn message to RTLA.\n * @param message the text string of the warn\n * @param err the error object to log, if omitted, an error object will be created using message\n */\nexport const logWarn = (message: string, err?: Error | any): void => {\n    console.warn(message, JSON.stringify(err));\n    emitToRTLA('WARN', message, toError(message, err));\n};\n\n/**\n * Send an error message to RTLA. Use {@link logFatal} instead for issues which degrade customer experience.\n * @param message the text string of the error\n * @param err the error object to log, if omitted, an error object will be created using message\n */\nexport const logError = (message: string, err?: Error | any): void => {\n    console.error(message, JSON.stringify(err));\n    emitToRTLA('ERROR', message, toError(message, err));\n};\n\n/**\n * Send a fatal error message to RTLA. Use {@link logError} instead for non-critical errors.\n * @param message the text string of the error\n * @param err the error object to log, if omitted, an error object will be created using message\n */\nexport const logFatal = (message: string, err?: Error | any): void => {\n    console.error(message, JSON.stringify(err));\n    emitToRTLA('FATAL', message, toError(message, err));\n};\n\nconst emitToRTLA = (level: LogLevel, message: string, err: Error): void => {\n    window.ueLogError?.(err, {\n        logLevel: level,\n        attribution: 'APE-safeframe',\n        message: message + ' | '\n    });\n};\n\nconst toError = (message: string, err: any): Error =>\n    err instanceof Error ? err : err ? new Error(err) : new Error(message);\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\nconst base64TestRegexp = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/;\n/**\n * @deprecated Remove once GPAT changes that only send text have been rolled out\n */\nconst isBase64 = (stringToTest: string) => base64TestRegexp.test(stringToTest);\n/**\n * @deprecated Remove once GPAT changes that only send text have been rolled out\n */\nexport const convertToStringIfBase64 = (stringToTest: string) =>\n    isBase64(stringToTest) ? utf_8_atob(stringToTest) : stringToTest;\n\nexport const convertToBase64IfString = (stringToTest: string) =>\n    isBase64(stringToTest) ? stringToTest : utf8_to_b64(stringToTest);\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 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_GRANDPRIX = 'perf:sf:grandprix';\nexport const PERF_SF_SETUP = 'perf:sf:setup';\nexport const PERF_LA = 'perf:la';\n\nexport const getMarkName = (scope: string, message: string, adDetails?: AdDetails): string =>\n    `${scope}${adDetails ? `:${adDetails.placementName}` : ''} - ${message}`;\n\nexport const mark = (scope: string, message: string, adDetails?: AdDetails): 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","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","/*\n    The regex pattern used in Javelin for getting browseNode in the URL\n    https://code.amazon.com/packages/JavelinPrimingServiceCDK/blobs/mainline/--/configuration/appconfig/pageContextConfig-prod.json#L97\n*/\nconst regex = /(\\/b|\\/s|\\/l).*(node=)(\\d{1,12})/;\nconst cache = new Map();\n\nconst getBrowseNode = (): string | null => {\n    if (!cache.has(window.location.href)) {\n        const match = regex.exec(window.location.href);\n        const browseNode = match && match[3] ? match[3] : null;\n        cache.set(window.location.href, browseNode);\n    }\n    return cache.get(window.location.href);\n};\n\nexport const getSlotWithBrowseNode = (slot: string): string | null => {\n    const browseNode = getBrowseNode();\n    if (!slot || !browseNode) {\n        return null;\n    }\n    const slotItems = slot.split(':');\n    slotItems.splice(slotItems.length - 1, 0, browseNode);\n    return slotItems.join(':');\n};\n\nexport const getPlacementWithBrowseNode = (placementId: string): string | null => {\n    const browseNode = getBrowseNode();\n    if (!browseNode) {\n        return null;\n    }\n\n    return `${placementId}:${browseNode}`;\n};\n","export const csmName = (name: string) => name.replace(/_/g, ':');\n","// https://w.amazon.com/index.php/ClientSideMetrics/UserDocs/Instrumentation/ClientSideCounters\nimport { getPlacementWithBrowseNode, getSlotWithBrowseNode } from '../browseNode.js';\nimport { csmName } from './util.js';\nimport type { Placement } from '../placement.js';\n\n/**\n * @description CSM - Increment placement level counter for a CSM metric.\n * @param metric The actual metrics name, without Placement information\n * @param placement The Placement you want to log metrics for\n * @param count The number to increment the count by (default 1)\n * @example incrementPlacementCounter('adfeedback:request', {id: '597b923a-8c7e-4665-9541-de88160dd0ba', name: 'Gateway_right-2_desktop'})\n * @example incrementPlacementCounter('adfeedback:request', {id: '597b923a-8c7e-4665-9541-de88160dd0ba', name: 'Gateway_right-2_desktop'}, 2)\n */\nexport const incrementCsmPlacementCounter = (metric: string, placement: Placement, count = 1) => {\n    if (!isUeCountAvailable()) return;\n\n    const countMetric = (metric: string, metricType: string | null, count: number) => {\n        if (!metricType) return;\n        ueCount(`${adPlacementMetric(metric)}:${metricType}`, count);\n    };\n\n    countMetric(metric, placement.id, count);\n    countMetric(metric, getPlacementWithBrowseNode(placement.id), count);\n\n    countMetric(metric, csmName(placement.name), count);\n    countMetric(metric, getSlotWithBrowseNode(csmName(placement.name)), count);\n};\n\n/**\n * @description CSM - Increment market level counter for a CSM metric.\n * @param metric The actual metrics name\n * @param count The number to increment the count by (default 1)\n * @example incrementCounter('adfeedback:request')\n * @example incrementCounter('adfeedback:request', 2)\n */\nexport const incrementCsmCounter = (metric: string, count = 1) => {\n    if (!isUeCountAvailable()) return;\n\n    ueCount(adPlacementMetric(metric), count);\n};\n\nconst isUeCountAvailable = () => typeof window?.ue?.count === 'function';\nconst ueCount = (metric: string, count: number) => window?.ue?.count(metric, count);\n\nconst adPlacementPrefix = 'adplacements';\nconst adPlacementMetric = (metric: string): string =>\n    metric.startsWith(adPlacementPrefix) ? metric : `${adPlacementPrefix}:${metric}`;\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { BridgeRegistry, WireContext } from '@/components/bridge/core/bridge.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 = (): WireContext => ({ adDetails, timestamp: new Date() });\n    return ((method: string, ...args: unknown[]): void => {\n        try {\n            port.postMessage({ namespace, method, args, context: getContext() });\n        } catch (e) {\n            logError(`Bridge send error in ${namespace}.${method}`, e);\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 - Ad slot identity 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\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 */\nconst buildProxy = (send: (...args: any[]) => void, prefix: string): unknown =>\n    new Proxy(() => {}, {\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 { createSender } from '@/components/bridge/core/sender.js';\nimport type { SafeFrameExtBridge } from '@/components/bridge/safeFrameExt/safeFrameExtBridge.js';\n\nexport const createSafeFrameExtBridgeSender = (mp: MessagePort, adDetails: AdDetails): SafeFrameExtBridge =>\n    createSender(mp, 'SafeFrameExt', adDetails);\n","export interface Cache<T> {\n    set(value: T): void;\n    get(): T;\n}\n\nexport interface MapCache<K, V> {\n    set(key: K, value: V): void;\n    get(key: K): V | undefined;\n}\n\nexport const createMapCache = <K, V>(): MapCache<K, V> => {\n    const map = new Map<K, V>();\n\n    return {\n        set(key: K, value: V): void {\n            map.set(key, value);\n        },\n        get(key: K): V | undefined {\n            return map.get(key);\n        },\n    };\n};\n","const PRODUCER_ID = 'apm-stores';\nconst METRICS_SOURCE_GROUP = 'com.amazon.apm.stores.csa.metrics.prod';\nconst LOGS_SOURCE_GROUP = 'com.amazon.apm.stores.csa.logs.prod';\n\nconst logCsaEvent = (sushiSourceGroup: string, data: Record<string, unknown>): void =>\n    window.csa?.('Events', { producerId: PRODUCER_ID, sushiSourceGroup })?.('log', data);\n\nexport const emitCsaLog = (data: Record<string, unknown>): void => logCsaEvent(LOGS_SOURCE_GROUP, data);\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.\n *\n * @param input.metricName - Name of the metric to emit.\n * @param input.metricValue - Numeric value of the metric.\n * @param input.timestamp - When the metric was recorded. Defaults to now.\n * @param input.dimensions - Key-value pairs for metric dimensions.\n * @param input.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    logCsaEvent(METRICS_SOURCE_GROUP, {\n        metricName,\n        metricValue,\n        timestamp: timestamp.getTime(),\n        dimensions,\n        ...(weblabs && { weblabs })\n    });\n","declare global {\n    interface Window {\n        AD_PLACEMENT: { loggedMetricNames: Set<string> };\n    }\n}\n\nconst getPageState = (): { loggedMetricNames: Set<string> } =>\n    (window.AD_PLACEMENT ??= { loggedMetricNames: new Set() });\n\nexport const hasEmittedMetric = (name: string): boolean => getPageState().loggedMetricNames.has(name);\n\nexport const markEmittedMetric = (name: string): void => {\n    getPageState().loggedMetricNames.add(name);\n};\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    isInTreatment(): boolean;\n    getTreatment(): AllWeblabTreatment;\n}\n\nexport const createWeblab = (weblabsWindow: WeblabsWindow, prefix: string): Weblab => {\n    const weblabTreatment = (): AllWeblabTreatment =>\n        weblabsWindow?.renderingWeblabs?.[prefix]?.toLowerCase() as AllWeblabTreatment;\n\n    return {\n        is(treatment: WeblabTreatment): boolean {\n            return weblabTreatment() === treatment;\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 enable iframe ready retry mechanism for host message receiver\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_IFRAME_READY_RETRY_1374491\n */\nexport const IFRAME_READY_RETRY_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_IFRAME_READY_RETRY_1374491');\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 * Used to enable CSA metrics for safeframe\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_CSA_METRICS_1390278\n */\nexport const CSA_METRICS_WEBLAB = () => createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_CSA_METRICS_1390278');\n","import { emitCsaMetric } from '@amzn/apejs-instrumentation/src/metrics/csa/events.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { hasEmittedMetric, markEmittedMetric } from '@/components/pageState/pageState.js';\nimport { CSA_METRICS_WEBLAB } 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:btr'\n    | 'pixel:imp:atf'\n    | 'pixel:view:iab'\n    | 'pixel:imp:skan'\n    | 'pixel:view:skan';\ntype MobileApiMetricName =\n    | 'sf:mobileapi:onPageEvent:callback'\n    | 'sf:mobileapi:onPageEvent:execute'\n    | 'sf:mobileapi:onPageEvent:update'\n    | 'sf:mobileapi:renderClickThroughAppAds'\n    | 'sf:mobileapi:getPlacementInfo'\n    | 'sf:mobileapi:getUserAgentInfo'\n    | 'sf:mobileapi:getDocumentCookie'\n    | 'sf:mobileapi:getUserConnectionInfo';\ntype CommonApiMetricName =\n    | 'sf:commonapi:changeSize'\n    | 'sf:commonapi:registerCustomMessageListener'\n    | 'sf:commonapi:feedbackLabelRendered'\n    | 'sf:commonapi:feedbackOpenModal'\n    | 'sf:commonapi:updatePlayingTimeForVideo'\n    | 'sf:commonapi:requestVideoAutoplay'\n    | 'sf:commonapi:releaseVideoAutoplay'\n    | 'sf:commonapi:haveVideoAutoplayPermission'\n    | 'sf:commonapi:isOnAmazon'\n    | 'sf:commonapi:collapseSlot'\n    | 'sf:commonapi:triggerEventInIframe'\n    | 'sf:commonapi:setupComputedAdDetails'\n    | 'sf:commonapi:signalAdLoadedAndInteractive';\nexport type CollapseMetricCode = 'creative' | 'client-setup' | 'host-setup' | 'client-error';\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:SafeFrameExt:populateSafeFrameExt',\n    'sf:bridge:SafeFrameExt:populateGeom',\n] as const;\nexport type BridgeMetricName = (typeof BRIDGE_METRIC_NAMES)[number];\n\ntype BlankAdMetricName = 'blank:ad:validation' | 'blank:ad:validation:error';\ntype DiagnosticMetricName =\n    | 'html:element:missing:placement'\n    | 'html:element:missing:iframe'\n    | 'asset:load:timing'\n    | 'intersection:observer:invalid:target'\n    | 'reporting-observer:heavy-ad-intervention';\nexport type MetricName =\n    | LifecycleMetricName\n    | CoordinateMetricName\n    | PixelMetricName\n    | MobileApiMetricName\n    | CommonApiMetricName\n    | CollapseMetricName\n    | BridgeMetricName\n    | BlankAdMetricName\n    | DiagnosticMetricName;\n\ninterface EmitPlacementMetricParams {\n    metricName: MetricName;\n    metricValue?: number;\n    adDetails: AdDetails | LightAdDetails;\n    timestamp?: Date;\n}\n\nexport const emitMetric = ({\n    metricName,\n    metricValue = 1,\n    adDetails: { logCxt },\n    timestamp,\n}: EmitPlacementMetricParams): void => {\n    if (!CSA_METRICS_WEBLAB().is('t1')) return;\n\n    emitCsaMetric({\n        metricName,\n        metricValue,\n        timestamp,\n        dimensions: { ...logCxt },\n    });\n};\n\nexport const emitMetricOnce = (params: EmitPlacementMetricParams): void => {\n    if (hasEmittedMetric(params.metricName)) return;\n    markEmittedMetric(params.metricName);\n    emitMetric(params);\n};\n\nconst WEBLAB_METRIC_NAME = 'session:weblabs';\n\nexport const emitWeblabMetric = (adDetails: AdDetails | LightAdDetails): void => {\n    if (!CSA_METRICS_WEBLAB().is('t1')) return;\n    if (hasEmittedMetric(WEBLAB_METRIC_NAME)) return;\n    markEmittedMetric(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","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';\n\nconst isSafeFrame = (adDetails: AdDetails | LightAdDetails): adDetails is AdDetails => 'adUnitIframeId' in adDetails;\n\nexport const getWrapper = (adDetails: AdDetails | LightAdDetails): 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\nexport const getPlacement = (adDetails: AdDetails | LightAdDetails): HTMLDivElement => {\n    const { adUnitPlacementId } = adDetails;\n    const placement = document.getElementById(adUnitPlacementId);\n\n    if (!placement) {\n        emitMetric({\n            metricName: 'html:element:missing:placement',\n            adDetails,\n        });\n    }\n\n    return placement as HTMLDivElement;\n};\n","import { incrementCsmPlacementCounter } from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport 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    try {\n        const div = getPlacement(adDetails);\n        const { x, y } = div.getBoundingClientRect();\n        const placement = { id: adDetails.placementId, name: adDetails.placementName };\n        incrementCsmPlacementCounter('coordinate:x', placement, x);\n        incrementCsmPlacementCounter('coordinate:y', placement, y);\n        emitMetric({ metricName: 'coordinate:x', metricValue: x, adDetails });\n        emitMetric({ metricName: 'coordinate:y', metricValue: y, adDetails });\n    } catch (_e) {\n        // We don't want to log this error because it's not a critical error\n        // We just use this to log the coordinates of the placement\n        // If it fails once in a while, it's not a big deal\n        return;\n    }\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric, type CollapseMetricCode } from '@/components/metrics/csaMetrics.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\nexport const collapsePlacement = ({ adDetails, code }: CollapsePlacementParams): void => {\n    hide(getWrapper(adDetails));\n    hide(getPlacement(adDetails));\n\n    emitMetric({ metricName: 'placement:collapse', adDetails });\n    if (code) {\n        emitMetric({ metricName: `placement:collapse:${code}`, adDetails });\n    }\n};\n","import {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport { logDebug } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport type { CollapseMetricCode } from '@/components/metrics/csaMetrics.js';\n\nexport const collapseSlotHandler = (adDetails: AdDetails, code: CollapseMetricCode): void => {\n    if (window.APE_SF?.collapsedPlacements.has(adDetails.adUnitPlacementId)) {\n        logDebug('Slot already collapsed');\n        return;\n    }\n\n    const placement = { id: adDetails.placementId, name: adDetails.placementName };\n    incrementCsmCounter('messenger:collapseSlot');\n    incrementCsmPlacementCounter('messenger:collapseSlot', placement);\n    incrementCsmCounter(`messenger:collapseSlot${code}`);\n    incrementCsmPlacementCounter(`messenger:collapseSlot${code}`, placement);\n    incrementCsmCounter(`collapse:${code.toLowerCase()}`);\n    incrementCsmPlacementCounter(`collapse:${code.toLowerCase()}`, placement);\n\n    collapsePlacement({ adDetails, code });\n\n    window.APE_SF?.collapsedPlacements.add(adDetails.adUnitPlacementId);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { MapCache } from '@/components/cache.js';\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const CLICK_FAILURE_METRIC_CSM = 'adplacements:retailClickTracking:failure';\nexport const CLICK_MISSING_URL_METRIC_CSM = 'adplacements:retailClickTracking:missingUrl';\nexport const CLICK_SUCCESS_METRIC_CSM = 'adplacements:retailClickTracking:clickSuccess';\n\nexport const cacheClickTrackingUrl = (adDetails: AdDetails, urlCache: MapCache<string, string>): void => {\n    const url = getPlacement(adDetails)?.getAttribute('data-click-addr');\n    if (url) {\n        urlCache.set(adDetails.adUnitPlacementId, url);\n    }\n};\n\nexport const fireRetailClickTrackingFromCache = (adDetails: AdDetails, url: string | undefined): void => {\n    if (url) {\n        getPlacement(adDetails)?.removeAttribute('onclick');\n        fireRetailClickTracking(url);\n    } else {\n        window.ue.count(CLICK_MISSING_URL_METRIC_CSM, 1);\n    }\n};\n\nexport const fireRetailClickTracking = async (retailClickTrackingUrl: string) => {\n    try {\n        const response = await fetch(retailClickTrackingUrl, { keepalive: true, redirect: 'manual' });\n        if (response.ok || response.type === 'opaqueredirect') {\n            window.ue.count(CLICK_SUCCESS_METRIC_CSM, 1);\n        } else {\n            window.ue.count(CLICK_FAILURE_METRIC_CSM, 1);\n        }\n    } catch (_ex) {\n        window.ue.count(CLICK_FAILURE_METRIC_CSM, 1);\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    if (!(target instanceof Element) && adDetails) {\n        emitMetric({\n            metricName: 'intersection:observer:invalid:target',\n            adDetails,\n        });\n    }\n\n    observer.observe(target);\n    return observer;\n};\n\nexport const observeUntilIntersection = async (\n    target: Element,\n    options?: IntersectionObserverInit,\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        });\n    });\n};\n","import {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport { logFatal } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { setupIntersectionObserver } from '@/components/intersectionObserver.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(placement);\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                logFatal(error?.message, error);\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 = (placement: Placement): void => {\n        if (this.wasObstructed) {\n            this.logMetrics('viewpixel:iab:obstruction:recovered', 1, placement);\n        }\n    };\n\n    logMetrics = (metricName: string, count = 1, placement?: Placement): void => {\n        if (!this.metricsLogged.has(metricName)) {\n            incrementCsmCounter(metricName, count);\n            if (placement) {\n                incrementCsmPlacementCounter(metricName, placement, count);\n            }\n            this.metricsLogged.add(metricName);\n        }\n    };\n}\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 type { Placement } from '@/components/pixels/pixel.js';\nimport { getState, setState } from '@/components/placement/placementState.js';\n\nexport interface FirePixel {\n    fire(placement: Placement): Promise<void>;\n}\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 {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport type { PixelMetricName } from '@/components/metrics/csaMetrics.js';\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\n\nexport const logPixelFired = (metricName: PixelMetricName, adDetails: AdDetails | LightAdDetails): void => {\n    incrementCsmCounter(metricName);\n    incrementCsmPlacementCounter(metricName, { id: adDetails.placementId, name: adDetails.placementName });\n    incrementCsmCounter(`${metricName}:${adDetails.adCreativeMetaData.adProgramId}`);\n    incrementCsmCounter(`${metricName}:device:${adDetails.deviceType.toLowerCase()}`);\n    emitMetric({ metricName, adDetails });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/pixels/firePixel.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { PixelIdentifier } from '@/components/pixels/pixelIdentifiers.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { logPixelFired } from '@/components/pixels/services/pixelLogger.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\n\nconst requestOptions: RequestInit = { keepalive: true, mode: 'no-cors' } as const;\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\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            await fetch(this.generatePixelUrl(this.url, placement), requestOptions);\n        } catch (e) {\n            markPixelError(placement.div, this.pixelIdentifier.metricName);\n            throw e;\n        }\n        placement.div.appendChild(this.pixel(placement));\n        logPixelFired(this.pixelIdentifier.metricName, this.adDetails);\n\n        // Do not await for 3P URLs as rendering the ad doesn't depend on successful firing\n        this.urls3p.forEach((url3p) => fetch(url3p, requestOptions));\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","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 * Calculates what percentage of the element is within the viewport\n * @param safezoneDOMRect - The safezone DOMRect. Use {@link getPlacementSafezoneDOMRect} to get this value.\n * @returns a number between 0 and 1\n */\nexport const getVisiblePercentageInViewport = (safezoneDOMRect: 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, safezoneDOMRect.top),\n        left: Math.max(0, safezoneDOMRect.left),\n        bottom: Math.min(windowHeight, safezoneDOMRect.bottom),\n        right: Math.min(windowWidth, safezoneDOMRect.right),\n    };\n\n    if (\n        safezoneDOMRect.top >= windowHeight ||\n        safezoneDOMRect.left >= windowWidth ||\n        safezoneDOMRect.bottom <= 0 ||\n        safezoneDOMRect.right <= 0 ||\n        safezoneDOMRect.width <= 0 ||\n        safezoneDOMRect.height <= 0\n    ) {\n        return 0;\n    }\n\n    const visibleArea = (visibleRect.right - visibleRect.left) * (visibleRect.bottom - visibleRect.top);\n    const totalArea = safezoneDOMRect.width * safezoneDOMRect.height;\n    const visiblePercentage = visibleArea / totalArea;\n    return visiblePercentage;\n};\n","import type { Placement } from '@/components/pixels/pixel.js';\n\n/**\n * H1's Safezone height and width with pixel count on Slide 15 of 27: @see https://amazon.awsapps.com/workdocs-amazon/index.html#/document/46972fcf864af9e6705e7469a0eec0082c54309b3f9af0c70c29af043352593d\n * @see https://design.amazon.com/styleguide/724BA9F0B089/homepage-design-guidelines/desktop-guidelines/desktop-tall-hero/#J83rKGvredLMM7\n */\nexport const SAFEZONE = {\n    H1_DESKTOP_HEIGHT: 240,\n    H1_DESKTOP_WIDTH: 940,\n} as const;\n\ntype Dimensions = {\n    height: number;\n    width: number;\n};\n\n/**\n * Returns the placement's safezone DOMRect.\n * @param placement\n * @returns The placement's safezone DOMRect to use for viewability and obstruction check\n */\nexport const getPlacementSafezoneDOMRect = (placement: Placement): DOMRect => {\n    if (isH1SafezoneEdgeCase(placement)) {\n        const dimensions: Dimensions = {\n            height: SAFEZONE.H1_DESKTOP_HEIGHT,\n            width: SAFEZONE.H1_DESKTOP_WIDTH,\n        };\n        return getUpdatedDOMRect(placement.div, dimensions);\n    }\n    return placement.div.getBoundingClientRect();\n};\n\n/**\n * Check if the placement is H1 Desktop, which is currently known to need special safe zone handling\n * @param placement\n * @returns True if the placement is an edgecase to require a special safezone.\n */\nexport const isH1SafezoneEdgeCase = (placement: Placement): boolean => {\n    const placementName = placement.name.toLowerCase();\n    const H1_DESKTOP_PLACEMENT_NAME = 'gateway_desktop-h1_desktop';\n    return placementName === H1_DESKTOP_PLACEMENT_NAME;\n};\n\n/**\n * Calculates a new DOMRect with updated dimensions while maintaining the vertical position\n * and horizontal center of the original element.\n * @param element - The HTML element to base the calculation on\n * @param newDimensions - The desired Dimensions (width and height) for the new DOMRect\n * @returns A new DOMRect with the specified Dimensions\n */\nexport const getUpdatedDOMRect = (element: HTMLElement, newDimensions: Dimensions): DOMRect => {\n    const originalDOMRect = element.getBoundingClientRect();\n    const center = (originalDOMRect.left + originalDOMRect.right) / 2;\n    const newX = center - newDimensions.width / 2;\n    return new DOMRect(newX, originalDOMRect.y, newDimensions.width, newDimensions.height);\n};\n","import {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport type { ObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionService.js';\n\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport { getVisiblePercentageInViewport } from '@/components/pixels/viewPixelUtil.js';\nimport { getPlacementSafezoneDOMRect } from '@/host/slotSpecific/placementSafezone.js';\n\nexport const createViewabilityService = (\n    obstructionDetectionService: ObstructionDetectionService,\n): ViewabilityService => {\n    const metricsLogged: Set<string> = new Set();\n\n    const logMetrics = (metricName: string, count = 1, placement?: Placement): void => {\n        if (!metricsLogged.has(metricName)) {\n            incrementCsmCounter(metricName, count);\n            if (placement) {\n                incrementCsmPlacementCounter(metricName, placement, count);\n            }\n            metricsLogged.add(metricName);\n        }\n    };\n\n    const isViewabilityObstructed = (placement: Placement, threshold: number): boolean => {\n        const placementSafezoneDOMRect = getPlacementSafezoneDOMRect(placement);\n        const visiblePercentageInViewport = getVisiblePercentageInViewport(placementSafezoneDOMRect);\n        const obstructionPercentage = obstructionDetectionService.getObstructionPercentage({\n            element: placement.div,\n            elementDOMRectOverride: placementSafezoneDOMRect,\n        });\n\n        const isViewabilityObstructed = visiblePercentageInViewport - obstructionPercentage < threshold;\n        if (isViewabilityObstructed) {\n            logMetrics('viewpixel:iab:obstruction', 1, placement);\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 { hasPixelFired, markPixelError, markPixelFired } from '@/components/pixels/firePixel.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { logPixelFired } from '@/components/pixels/services/pixelLogger.js';\nimport { startAttributeViewThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.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        try {\n            startAttributeViewThroughAppAds(this.adDetails.skAdNetwork!);\n        } catch (e) {\n            markPixelError(placement.div, METRIC_NAME);\n            throw e;\n        }\n        logPixelFired(METRIC_NAME, this.adDetails);\n    }\n}\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/pixels/firePixel.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { logPixelFired } from '@/components/pixels/services/pixelLogger.js';\nimport { endAttributeViewThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.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        try {\n            endAttributeViewThroughAppAds(this.adDetails.skAdNetwork!);\n        } catch (e) {\n            markPixelError(placement.div, METRIC_NAME);\n            throw e;\n        }\n        logPixelFired(METRIC_NAME, this.adDetails);\n    }\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","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","import { BEGIN_TO_RENDER_CLIENT } from '@/client/api/client/measurementMethods.js';\nimport { 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\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 aaxTypeMacro.test(url)\n        ? url.replace(aaxTypeMacro, ATF_URL_KEY).replace(aaxPayloadMacro, encodedUrlPayload)\n        : `${url.replace(/\\/$/, '')}/${ATF_URL_KEY}/${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 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 aaxTypeMacro.test(url)\n            ? url.replace(aaxTypeMacro, VIEW_PIXEL_URL_KEY).replace(aaxPayloadMacro, encodedUrlPayload)\n            : `${url.replace(/\\/+$/, '')}/${VIEW_PIXEL_URL_KEY}/${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 {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport { logFatal } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { setupIntersectionObserver } from '@/components/intersectionObserver.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            if (isObstructed(placement) || isHidden()) {\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(placement);\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            logFatal(error?.message, error);\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 * @param placement - The placement that recovered from obstruction\n */\nconst logObstructionRecovery = (placement: Placement): void => {\n    const metricName = 'viewpixel:iab:obstruction:recovered';\n    incrementCsmCounter(metricName);\n    incrementCsmPlacementCounter(metricName, placement);\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()),\n            validator ? [validator] : [],\n            adDetails,\n        );\n    } else {\n        return new MRCObstructionViewPixel(\n            pixel,\n            standard,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService()),\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()),\n            undefined,\n            adDetails,\n        );\n    }\n    return undefined;\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 { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport { 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            logError,\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 } 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) => {\n    const placement = getPlacement(adDetails);\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    await observeUntilIntersection(placement, {\n        root: hasFixedPositionAncestor(placement) ? VIEWPORT_ROOT : document.documentElement,\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 { 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);\n\n    mapToBtrPixel(adDetails)?.fire({\n        id: adDetails.placementId,\n        name: adDetails.placementName,\n        div: getPlacement(adDetails),\n        deviceType: adDetails.deviceType,\n    });\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","/**\n * Parameters for executeWhenConditionMet function.\n */\ninterface ExecuteWhenConditionMetParams {\n    /** Function that returns true when the condition is met */\n    condition: () => boolean;\n    /** Async action to execute when condition is met */\n    action: () => Promise<void>;\n    /** Maximum time to wait in milliseconds (default: 1000ms) */\n    maxWaitMs?: number;\n    /** Multiplier for exponential backoff (default: 1.5) */\n    backoffMultiplier?: number;\n}\n\n/**\n * Repeatedly checks a condition and executes an action when the condition is met.\n * Uses requestAnimationFrame for fast initial checks (first 200ms), then switches\n * to exponential backoff with setTimeout.\n *\n * @param params - Configuration parameters\n * @returns Promise that resolves when action completes, rejects on timeout or error\n * @throws Error if condition is not met within maxWaitMs\n *\n * @example\n * ```typescript\n * await executeWhenConditionMet({\n *   condition: () => document.getElementById('ad-container') !== null,\n *   action: async () => { console.log('Ad container ready'); },\n *   maxWaitMs: 2000,\n *   backoffMultiplier: 2\n * });\n * ```\n */\nexport const executeWhenConditionMet = async ({\n    condition,\n    action,\n    maxWaitMs = 1000,\n    backoffMultiplier = 1.5,\n}: ExecuteWhenConditionMetParams) => {\n    if (condition()) {\n        await action();\n        return;\n    }\n\n    return new Promise<void>((resolve, reject) => {\n        const startTime = performance.now();\n        let currentDelay = 50;\n        const fastPhaseMs = 200;\n\n        const retry = async (): Promise<void> => {\n            if (condition()) {\n                try {\n                    await action();\n                    resolve();\n                } catch (error) {\n                    reject(error);\n                }\n                return;\n            }\n\n            const elapsed = performance.now() - startTime;\n\n            if (elapsed >= maxWaitMs) {\n                reject(new Error(`Condition not met after ${maxWaitMs}ms`));\n                return;\n            }\n\n            if (elapsed < fastPhaseMs) {\n                requestAnimationFrame(retry);\n            } else {\n                setTimeout(retry, currentDelay);\n                currentDelay = Math.min(currentDelay * backoffMultiplier, 200);\n            }\n        };\n\n        retry();\n    });\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';\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const enableSkanViewabilityTracker = async (adDetails: AdDetails) => {\n    const placement: Placement = {\n        id: adDetails.placementId,\n        name: adDetails.placementName,\n        div: getPlacement(adDetails),\n        deviceType: adDetails.deviceType,\n    };\n\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 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);\n    await waitUntilReadyForTracking(adDetails);\n    const placement: Placement = {\n        id: adDetails.placementId,\n        name: adDetails.placementName,\n        div: placementDiv,\n        deviceType: adDetails.deviceType,\n    };\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),\n            adDetails,\n        );\n    } else {\n        mapToMeasurabilityPixel(adDetails).fire(placement);\n    }\n\n    enableSkanViewabilityTracker(adDetails);\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';\n\nexport const getIFrame = (adDetails: AdDetails): HTMLIFrameElement => {\n    const { adUnitIframeId } = adDetails;\n    const iframe = document.getElementById(adUnitIframeId);\n\n    if (!iframe) {\n        emitMetric({\n            metricName: 'html:element:missing:iframe',\n            adDetails,\n        });\n    }\n\n    return iframe 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\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\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                t: boundingClientRect.top,\n                l: boundingClientRect.left,\n                r: boundingClientRect.right,\n                b: boundingClientRect.bottom,\n                xiv: percentVisibleOnX,\n                yiv: percentVisibleOnY,\n                iv: intersectionRatio,\n                z: 1,\n                w: iframe.offsetWidth,\n                h: iframe.offsetHeight,\n            },\n        } as Partial<GeometricInformation> as GeometricInformation,\n        inViewPercentage: Math.round(intersectionRatio * 100),\n    });\n};\n\nexport const sendGeomOnInterval = (adDetails: AdDetails, bridge: SafeFrameExtBridge): void => {\n    const iframe = getIFrame(adDetails);\n\n    if (!iframe) return;\n\n    setInterval(() => {\n        const rect = iframe.getBoundingClientRect();\n\n        bridge.populateGeom({\n            geom: {\n                self: {\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                } as Partial<SelfRelativeAndInView> as SelfRelativeAndInView,\n            } as Partial<GeometricInformation> as GeometricInformation,\n        });\n    }, 250);\n};\n","import type { CsaLatencyMarker } from './global.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","import type { Placement } from '../placement.js';\nimport { csmName } from './util.js';\n\ntype 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\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\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 { CsaLatencyMarker } from '@amzn/apejs-instrumentation/src/metrics/csa/global.js';\nimport { sendCsaLatencyMetric } from '@amzn/apejs-instrumentation/src/metrics/csa/latency.js';\nimport type { LatencyEvent } from '@amzn/apejs-instrumentation/src/metrics/csm/latency.js';\nimport { sendCsmLatencyMetric } from '@amzn/apejs-instrumentation/src/metrics/csm/latency.js';\nimport type { AdDetails, App, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { getWrapper } from '@/host/components/placement.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 = getWrapper(adDetails) ?? (document.getElementById(adDetails.adUnitPlacementId) as HTMLElement);\n    const { placementId: id, placementName: name } = adDetails;\n\n    sendCsmLatencyMetric({ latencyEvent, placement: { id, name }, scope, timestamp });\n    csaEvents[latencyEvent]?.forEach((marker) => sendCsaLatencyMetric(element, marker, timestamp));\n};\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 { 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);\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 {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { Context } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { EventsBridge, OnCreativeLoadPayload, OnErrorPayload } from '@/components/bridge/events/eventsBridge.js';\nimport { createSafeFrameExtBridgeSender } from '@/components/bridge/safeFrameExt/safeFrameExtBridgeSender.js';\nimport { createMapCache } from '@/components/cache.js';\nimport type { ComputedAdDetailsData } from '@/components/commands.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 { mark, PERF_SF_HOST } from '@/components/perf.js';\nimport { collapseSlotHandler } from '@/host/api-client/handlers/collapseSlotHandler.js';\nimport {\n    cacheClickTrackingUrl,\n    fireRetailClickTrackingFromCache,\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 type { HostMessageSender } from '@/host/api-client/hostMessageSender.js';\nimport { sendLatencyMetric, shouldSafeFrameFireLoadedMetrics } from '@/host/components/latency.js';\nimport { getPlacement } from '@/host/components/placement.js';\nimport { toggleNavCartClassOnMutation } from '@/host/slotSpecific/navCartClassToggle.js';\n\nexport const createEventsBridgeReceiver = (hms: HostMessageSender): ReceiverImpl<EventsBridge> => {\n    const clickTrackingUrlCache = createMapCache<string, string>();\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            sendLatencyMetric({ adDetails, latencyEvent: 'bb', scope: 'SF', timestamp });\n\n            mark(PERF_SF_HOST, 'safeFrameReady', adDetails);\n            hms.sendMessageToAd<ComputedAdDetailsData>(adDetails.arid, 'setupComputedAdDetails', {\n                aPageStart: window.aPageStart, // This is used for https://console.harmony.a2z.com/aax-hub/apis/logging-api/aax-log#pixel-view-payload-log computation so we can delay this\n                adStartTime: new Date().getTime(), // https://console.harmony.a2z.com/aax-hub/apis/logging-api/aax-log#pixel-view-payload-log\n            });\n\n            //Exposed the resize event to SafeFrame window\n            window.addEventListener('resize', () => {\n                hms.sendCustomMessageToAd(adDetails.arid, '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        },\n\n        onPreCreativeWrite({ adDetails, timestamp }: Context, latency: number): void {\n            emitMetric({\n                metricName: 'event:prewrite',\n                adDetails,\n                timestamp,\n                metricValue: latency,\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, latency }: OnCreativeLoadPayload,\n        ): void {\n            emitMetric({\n                metricName: 'event:load',\n                adDetails,\n                timestamp,\n                metricValue: latency,\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            cacheClickTrackingUrl(adDetails, clickTrackingUrlCache);\n\n            if (isImageOnlyTemplate) {\n                getPlacement(adDetails).classList.add('is-image-oo');\n            }\n\n            sendEventCreativeLoadedHandler(adDetails, { isBtr });\n            emitWeblabMetric(adDetails);\n        },\n\n        onError({ adDetails }: Context, { code, isBTR, error }: OnErrorPayload): void {\n            logEvent('eventsChannel:onError', adDetails);\n            logEvent(`eventsChannel:onError:${code}`, adDetails);\n            if (code === 'client-setup') {\n                logError('Failed to setup creative', error);\n            }\n            if (!isBTR && (code === 'client-error' || code === 'client-setup')) {\n                collapseSlotHandler(adDetails, code);\n            }\n        },\n\n        onClick({ adDetails }: Context): void {\n            fireRetailClickTrackingFromCache(adDetails, clickTrackingUrlCache.get(adDetails.adUnitPlacementId));\n        },\n    };\n};\n\nconst logEvent = (metric: string, adDetails: AdDetails): void => {\n    const m = metric.toLowerCase();\n    incrementCsmCounter(m, performance.now());\n    incrementCsmPlacementCounter(\n        m,\n        {\n            id: adDetails.placementId,\n            name: adDetails.placementName,\n        },\n        performance.now(),\n    );\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 { logDebug } from '@amzn/apejs-instrumentation/src/metrics/logging.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    options?: GwVideoOrchestratorOptions,\n): void => {\n    window.P?.when(gwVideoOrchestratorPName).execute((gwVideoOrchestrator: GwVideoOrchestrator) => {\n        try {\n            gwVideoOrchestrator.subscribe(element, callback, options);\n        } catch (error) {\n            logDebug(`gw-video-orchestrator error: ${JSON.stringify(error)}`);\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 { AdDetails } from '@amzn/safeframe-model';\n\nimport type { GwVideoOrchestratorOptions } from '@/components/homepage/homepageVideoOrchestrator.js';\nimport { elect, subscribe, unelect } from '@/components/homepage/homepageVideoOrchestrator.js';\nimport { canBeInSameViewport } from '@/components/viewability.js';\nimport type { HostMessageSender } from '@/host/api-client/hostMessageSender.js';\nimport { getIFrame } from '@/host/components/iframe.js';\n\nlet autoplayLock: string | null = null;\n\nexport const requestVideoAutoplayHandler = (\n    adDetails: AdDetails,\n    data: GwVideoOrchestratorOptions,\n    messenger: HostMessageSender,\n) => {\n    const sendCanAutoPlayMessage = (canAutoplay: boolean) =>\n        messenger.sendCustomMessageToAd(adDetails.arid, 'videoAutoplayResponse', canAutoplay);\n\n    if (isHomepage(adDetails.pageType)) {\n        subscribe(getIFrame(adDetails), sendCanAutoPlayMessage, data);\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 { Context } from '@/components/bridge/core/bridge.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { VideoBridge } from '@/components/bridge/video/videoBridge.js';\nimport {\n    haveVideoAutoplayPermissionHandler,\n    releaseVideoAutoplayHandler,\n    requestVideoAutoplayHandler,\n} from '@/components/bridge/video/videoHandlers.js';\nimport type { GwVideoOrchestratorOptions } from '@/components/homepage/homepageVideoOrchestrator.js';\nimport { SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport type { SfVideoContinuousPlaytimeEventDetail } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport type { HostMessageSender } from '@/host/api-client/hostMessageSender.js';\nimport { getPlacement } from '@/host/components/placement.js';\n\nexport const createVideoBridgeReceiver = (hms: HostMessageSender): ReceiverImpl<VideoBridge> => ({\n    updatePlayingTimeForVideo: ({ adDetails }: Context, continuousPlaybackSeconds: number): void => {\n        const placement = getPlacement(adDetails);\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?: GwVideoOrchestratorOptions): void => {\n        requestVideoAutoplayHandler(adDetails, options ?? {}, hms);\n    },\n\n    releaseVideoAutoplay: (): void => {\n        releaseVideoAutoplayHandler();\n    },\n\n    haveVideoAutoplayPermission: ({ adDetails }: Context): void => {\n        haveVideoAutoplayPermissionHandler(adDetails);\n    },\n});\n","import {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport type { Placement } from '@amzn/apejs-instrumentation/src/metrics/placement.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 = (placement: Placement): void => {\n    incrementCsmCounter('adfeedback:sponsoredlabelrendered');\n    incrementCsmPlacementCounter('adfeedback:sponsoredlabelrendered:creative', placement);\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 type { DeviceType } from '@amzn/safeframe-model';\n\n/**\n * The baseline font sizes for each device type.\n * Code references:\n * Desktop: https://tiny.amazon.com/x47zohww/AmazonUIBaseCSS/ab418f40/_reset.scss#L53\n * Mobile: https://tiny.amazon.com/ngvoylv3/AmazonUIBaseCSS/acdd7b75/_base_touch.device_type=mobile.scss#L2\n *\n */\nexport const BASE_FONT_SIZES: Record<DeviceType, number> = {\n    DESKTOP: 16,\n    MSHOP: 10,\n    MWEB: 10,\n};\n\n/**\n * Ensure that length has unit per https://www.w3.org/TR/css3-values/#lengths\n *\n * @param {string} value Length with px, %, or unitless (treat as px)\n * @returns {string} Valid length with px or %\n */\nexport const ensureValidLength = (value: any): string => {\n    if (value && !isPercentage(value) && !isPixel(value)) {\n        return value + 'px';\n    }\n    return value;\n};\n\nexport const isPercentage = (value: string): boolean => {\n    return value?.length > 1 && value.charAt(value.length - 1) === '%';\n};\n\nexport const isPixel = (value: string): boolean => {\n    return value.length > 2 && value.substring(value.length - 2) === 'px';\n};\n\nexport const makeSizeExplicitPercentOrPx = (value: string): string =>\n    isPercentage(value) ? value : `${parseInt(value)}px`;\n\n/**\n * This utility function takes a string value, e.g. 60px or 100%, and computes the appropriate lh value. If the value is\n * a percentage, i.e. 75%, we simply return the string back. Otherwise, we parse the value and divide it by the provided\n * root font size.\n *\n * Keep in mind that `lh` units are calculated based on the current element's line height. For example, if the\n * line-height is 10px, then 5lh = 5 * 10px = 50px;\n *\n * For more details, see this Quip doc:\n * https://quip-amazon.com/lFotAjjaiDqy/Relative-Unit-Sizing-for-APM-Placements\n *\n * SIM ticket to track browser updates and yearly audits:\n * https://sim.amazon.com/issues/CPP-42326\n */\nexport const makeSizeExplicitPercentOrRelativeUnit = (value: string, deviceType: DeviceType = 'MWEB'): string => {\n    if (isPercentage(value)) return value;\n\n    const val = parseFloat(value);\n    const fontSize = BASE_FONT_SIZES[deviceType];\n\n    if (!val || !fontSize) return 'inherit';\n\n    return `${val / fontSize}lh`;\n};\n","import { logDebug, logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\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    logDebug('ChangeSize API has been deprecated');\n    if (!isChangeSizeSupported(adDetails)) return;\n\n    resizePlacement(adDetails, size);\n};\n\nconst resizePlacement = (adDetails: AdDetails, size: PlacementSize): boolean => {\n    if (!isAllowedSize(size)) {\n        logError(`Size w:'${size.width}', h:'${size.height}' is not allow-listed for '${adDetails.placementName}'`);\n        return false;\n    }\n\n    const div = getPlacement(adDetails);\n\n    if (supportChangeSizeResize(adDetails, size)) {\n        div.style.maxHeight = makeSizeExplicitPercentOrPx(size.height);\n    }\n\n    if (isPercentage(size.height) || isPercentage(size.width)) {\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    return true;\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\nconst supportChangeSizeResize = (adDetails: AdDetails, size: PlacementSize): boolean =>\n    adDetails.slotName === 'hero-quick-promo' && isPercentage(size.width);\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport type {} from '@/client/app/safeframeClient.js';\nimport { type TimestampData } from '@/components/commands.js';\nimport { labelRendered, openModal } from '@/components/feedback.js';\nimport { mapToImpressionPixel } from '@/components/pixels/pixelMapper.js';\nimport { changeSizeHandler } from '@/host/api-client/handlers/changeSizeHandler.js';\nimport { collapseSlotHandler } from '@/host/api-client/handlers/collapseSlotHandler.js';\nimport type { HostMessageSender } from '@/host/api-client/hostMessageSender.js';\nimport { sendLatencyMetric } from '@/host/components/latency.js';\nimport { getPlacement } from '@/host/components/placement.js';\nimport { waitUntilReadyForTracking } from '@/host/components/waitUntilReadyForTracking.js';\nimport type { HostContext } from '@/host/context/HostContext.js';\n\n// These are the commands that are supported by all the ad-serving platforms.\n// Do not add anything that you do not want to be run directly by the SF client javascript simply by receiving a message!\n// These are validated staticaly for literals on the client side but at runtime it is fair game\nexport class CommonSupportedCommands {\n    constructor(\n        protected readonly hms: HostMessageSender,\n        public hc: HostContext,\n    ) {}\n\n    changeSize = changeSizeHandler;\n\n    feedbackLabelRendered = (adDetails: AdDetails) =>\n        labelRendered({\n            id: adDetails.placementId,\n            name: adDetails.placementName,\n        });\n    feedbackOpenModal = (adDetails: AdDetails) => openModal(adDetails.adUnitWrapperId ?? adDetails.adUnitPlacementId);\n\n    collapseSlot = collapseSlotHandler;\n\n    /**\n     * Fires the COD impression pixel on the host side using the Light Ads logic\n     *\n     * @param {AdInfo} adInfo - Ad information object\n     */\n    sendEventAddedCreative = async (adDetails: AdDetails) => {\n        await waitUntilReadyForTracking(adDetails);\n        await mapToImpressionPixel(adDetails).fire({\n            id: adDetails.placementId,\n            name: adDetails.placementName,\n            div: getPlacement(adDetails),\n            deviceType: adDetails.deviceType,\n        });\n    };\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: AdDetails, { timestamp }: TimestampData) => {\n        sendLatencyMetric({ adDetails, latencyEvent: 'cf', scope: 'SF', timestamp });\n        sendLatencyMetric({ adDetails, latencyEvent: 'ld', scope: 'SF', timestamp });\n    };\n}\n","import {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { ToHostCommandType } from '@/client/api/internal/clientMessageSender.js';\nimport { executeWhenConditionMet } from '@/components/executeWhenConditionMet.js';\nimport type { ClientMessageToHost } from '@/components/messenger.js';\nimport { IFRAME_READY_RETRY_WEBLAB } from '@/components/weblabs.js';\nimport type { CommonSupportedCommands } from '@/host/api-client/CommonSupportedCommands.js';\n\n/**\n * Handles messages sent from the SafeFrame client to the host.\n * Routes commands to supported command handlers. Bridge messages\n * (CSM, Events) are handled by the bridge via {@link bindHostImpl}.\n */\nexport class HostMessageReceiver {\n    constructor(readonly supportedCommands: CommonSupportedCommands) {}\n\n    /**\n     * Receives a message from the SafeFrame client.\n     * When {@link IFRAME_READY_RETRY_WEBLAB} is `t1`, defers execution until the iframe element is present in the DOM.\n     */\n    receiveMessage = async ({ data }: MessageEvent<ClientMessageToHost>) => {\n        /**\n         * Other bridges (e.g. CSM, Events) share the same message port,\n         * so not every message will carry a `command`. Default to an empty\n         * object and bail early when `command` is absent to ignore messages\n         * intended for those other bridges.\n         */\n        const { command, adDetails, payload } = data ?? {};\n        if (!command) return;\n\n        try {\n            if (IFRAME_READY_RETRY_WEBLAB().is('t1')) {\n                await executeWhenConditionMet({\n                    condition: () => !!document.getElementById(adDetails.adUnitIframeId),\n                    action: async () => await this.execute(command, adDetails, payload),\n                });\n            } else {\n                await this.execute(command, adDetails, payload);\n            }\n        } catch (ex) {\n            logError(`Problem with command '${command}': ${JSON.stringify(payload)}`, ex);\n        }\n    };\n\n    private execute = (command: ToHostCommandType, adDetails: AdDetails, payload: any): Promise<void> | undefined => {\n        const supportedAction = this.supportedCommands[command as keyof typeof this.supportedCommands];\n        if (typeof supportedAction === 'function') {\n            logAPIInvocation(command, adDetails);\n            return Promise.resolve(supportedAction(adDetails, payload));\n        }\n\n        return Promise.resolve();\n    };\n}\n\nconst logAPIInvocation = (command: string, adDetails: AdDetails): void => {\n    const metric = `messenger:${command}`;\n    incrementCsmCounter(metric);\n    incrementCsmPlacementCounter(metric, {\n        id: adDetails.placementId,\n        name: adDetails.placementName,\n    });\n};\n","import type { HostMessageToClient } from '@/components/messaging/types.js';\nimport type { ToClientCommandType } from '@/components/messaging/types.js';\nimport type { AdMap } from '@/types/adCommon.js';\n\n/*\n * This class is responsible for sending messages to the Safeframe\n */\nexport class HostMessageSender {\n    constructor(public readonly adMap: AdMap) {}\n\n    sendMessageToAd = <T>(arid: string, command: ToClientCommandType, data?: T) => {\n        const port1 = this.adMap[arid].messagePort;\n        const msg: HostMessageToClient = {\n            command: command,\n            data: data,\n        };\n        port1.postMessage(msg);\n    };\n\n    sendCustomMessageToAd = (arid: string, msgKey: string, data: any) => {\n        const msgData = {\n            key: msgKey,\n            data: data,\n        };\n        this.sendMessageToAd(arid, 'customMessage', msgData);\n    };\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 { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\n\nimport 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 { 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            logError(`Bridge error in ${namespace}.${data.method}`, e);\n        }\n    });\n};\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { bindReceiver } from '@/components/bridge/core/receiver.js';\nimport type { ReceiverImpl } from '@/components/bridge/core/receiver.js';\nimport type { CsaBridge } from '@/components/bridge/csa/csaBridge.js';\nimport type { CsmBridge } from '@/components/bridge/csm/csmBridge.js';\nimport type { EventsBridge } from '@/components/bridge/events/eventsBridge.js';\nimport type { VideoBridge } from '@/components/bridge/video/videoBridge.js';\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport { mark, PERF_SF_HOST } from '@/components/perf.js';\nimport type { HostMessageReceiver } from '@/host/api-client/hostMessageReceiver.js';\nimport type { HostContext } from '@/host/context/HostContext.js';\n\nexport interface SafeframeApi {\n    // Loads all the ads on the page\n    secondPhaseLoadAd: (\n        arid: string,\n        adDetails: AdDetails,\n        messagePortFromClient: MessagePort,\n        startSafeFrameCSM?: Date,\n    ) => void;\n    setupMessageChannel: (messagePortFromClient: MessagePort, adDetails: AdDetails, startSafeFrameCSM?: Date) => void;\n    collapsedPlacements: Set<string>;\n}\n\nexport class SafeframeApiImpl implements SafeframeApi {\n    constructor(\n        readonly hc: HostContext,\n        readonly hmr: HostMessageReceiver,\n        private readonly eventsImpl: ReceiverImpl<EventsBridge>,\n        private readonly csmImpl: ReceiverImpl<CsmBridge>,\n        private readonly csaImpl: ReceiverImpl<CsaBridge>,\n        private readonly videoImpl: ReceiverImpl<VideoBridge>,\n    ) {}\n\n    collapsedPlacements: Set<string> = new Set<string>();\n\n    /**\n     * Initializes an entry in the ad map using the ARID (Ad Request ID) as the key.\n     * @param {AdDetails} adDetails - Object containing ad configuration details including ARID and slot name\n     * @param {MessagePort} clientSetupMessagePort - Message port for communication with the client setup\n     * @throws {Error} May throw an error during ad map entry creation\n     */\n    readonly initializeAdMap = (adDetails: AdDetails, clientSetupMessagePort: MessagePort) => {\n        try {\n            this.hc.adMap[adDetails.arid] = {\n                messagePort: clientSetupMessagePort,\n            };\n        } catch (ex) {\n            logError(`Error creating safeFrame ${adDetails.slotName}`, ex);\n        }\n    };\n\n    /**\n     * This is called from inline GPAT script when the iframe for a slot has emitted an \"sf iframe ready\" message.\n     * It is responsible for setting up globals, firing metrics, and rendering the sponsored label.\n     */\n    readonly secondPhaseLoadAd = async (\n        arid: string,\n        adDetails: AdDetails,\n        messagePortFromClient: MessagePort,\n    ): Promise<void> => {\n        await this.setupMessageChannel(messagePortFromClient, adDetails);\n    };\n\n    readonly setupMessageChannel = async (\n        messagePortFromClient: MessagePort,\n        adDetails: AdDetails,\n        _startSafeFrameCSM?: Date,\n    ): Promise<void> => {\n        mark(PERF_SF_HOST, 'Start setupMessagePort', adDetails);\n\n        this.initializeAdMap(adDetails, messagePortFromClient);\n\n        try {\n            bindReceiver(messagePortFromClient, 'Events', this.eventsImpl);\n            bindReceiver(messagePortFromClient, 'Csm', this.csmImpl);\n            bindReceiver(messagePortFromClient, 'Csa', this.csaImpl);\n            bindReceiver(messagePortFromClient, 'Video', this.videoImpl);\n            connectMessageChannel(this.hc, adDetails, this.hmr);\n        } catch (e) {\n            collapsePlacement({ adDetails, code: 'host-setup' });\n            throw e;\n        }\n    };\n}\n\n/**\n * Assigns {@link HostMessageReceiver} as listener on the message port.\n * Message Channels work like a queue that holds messages until consumed,\n * so this function triggers ingestion of any waiting messages from the iframe.\n */\nexport const connectMessageChannel = (hc: HostContext, adDetails: AdDetails, hmr: HostMessageReceiver): void => {\n    hc.adMap[adDetails.arid].messagePort.onmessage = hmr.receiveMessage;\n};\n","import type { AdMap } from '@/types/adCommon.js';\n\nexport class HostContext {\n    constructor(public readonly adMap: AdMap = {}) {}\n}\n","import { createCsaBridgeReceiver } from '@/components/bridge/csa/csaBridgeReceiver.js';\nimport { createCsmBridgeReceiver } from '@/components/bridge/csm/csmBridgeReceiver.js';\nimport { createEventsBridgeReceiver } from '@/components/bridge/events/eventsBridgeReceiver.js';\nimport { createVideoBridgeReceiver } from '@/components/bridge/video/videoBridgeReceiver.js';\nimport { CommonSupportedCommands } from '@/host/api-client/CommonSupportedCommands.js';\nimport { HostMessageReceiver } from '@/host/api-client/hostMessageReceiver.js';\nimport { HostMessageSender } from '@/host/api-client/hostMessageSender.js';\nimport { MobileSupportedCommands } from '@/host/api-client/MobileSupportedCommands.js';\nimport { SafeframeApiImpl } from '@/host/api-page/safeframe-api.js';\nimport { HostContext } from '@/host/context/HostContext.js';\n\nexport const createSafeframeDesktopApi = (): SafeframeApiImpl => {\n    const hc = new HostContext();\n    const hms = new HostMessageSender(hc.adMap);\n    const hmr = new HostMessageReceiver(new CommonSupportedCommands(hms, hc));\n    return new SafeframeApiImpl(\n        hc,\n        hmr,\n        createEventsBridgeReceiver(hms),\n        createCsmBridgeReceiver(),\n        createCsaBridgeReceiver(),\n        createVideoBridgeReceiver(hms),\n    );\n};\n\nexport const createSafeframeMobileApi = (): SafeframeApiImpl => {\n    const hc = new HostContext();\n    const hms = new HostMessageSender(hc.adMap);\n    const hmr = new HostMessageReceiver(new MobileSupportedCommands(hms, hc));\n    return new SafeframeApiImpl(\n        hc,\n        hmr,\n        createEventsBridgeReceiver(hms),\n        createCsmBridgeReceiver(),\n        createCsaBridgeReceiver(),\n        createVideoBridgeReceiver(hms),\n    );\n};\n","import { mark, PERF_SF_HOST } from '@/components/perf.js';\nimport { createSafeframeDesktopApi, createSafeframeMobileApi } from '@/host/api-page/safeframe-api-factory.js';\nimport type { SafeframeApi } from '@/host/api-page/safeframe-api.js';\n\ndeclare global {\n    interface Window {\n        APE_SF: SafeframeApi | undefined;\n    }\n}\n\nexport const initSafeframeHostDesktop = (): void => {\n    mark(PERF_SF_HOST, 'initSafeframeHostDesktop');\n    if (window.APE_SF) return;\n\n    mark(PERF_SF_HOST, 'initSafeframeHostDesktop init');\n    window.APE_SF = createSafeframeDesktopApi();\n};\n\nexport const initSafeframeHostMobile = (): void => {\n    mark(PERF_SF_HOST, 'initSafeframeHostMobile');\n    if (window.APE_SF) return;\n\n    mark(PERF_SF_HOST, 'initSafeframeHostMobile init');\n    window.APE_SF = createSafeframeMobileApi();\n};\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\n\nimport { safeFunctionWrapper } from '@/components/util.js';\nimport { initSafeframeHostDesktop } from '@/host/initSafeframeHost.js';\n\nsafeFunctionWrapper(() => initSafeframeHostDesktop(), logError, 'Error initializing safeFrame')();\n"],"x_google_ignoreList":[0,5,6,7,11,21,22,23,24,25,26,54,65,66],"mappings":"YAaA,IAAa,EAAY,GAA0B,CAC/C,QAAQ,MAAM,EAAQ,EAkBb,GAAY,EAAiB,IAA4B,CAClE,QAAQ,MAAM,EAAS,KAAK,UAAU,EAAI,CAAC,CAC3C,EAAW,QAAS,EAAS,EAAQ,EAAS,EAAI,CAAC,EAQ1C,GAAY,EAAiB,IAA4B,CAClE,QAAQ,MAAM,EAAS,KAAK,UAAU,EAAI,CAAC,CAC3C,EAAW,QAAS,EAAS,EAAQ,EAAS,EAAI,CAAC,EAGjD,GAAc,EAAiB,EAAiB,IAAqB,UACvE,GAAA,EAAA,QAAO,aAAA,MAAA,EAAA,KAAA,EAAa,EAAK,CACrB,SAAU,EACV,YAAa,gBACb,QAAS,EAAU,MACtB,CAAC,EAGA,GAAW,EAAiB,IAC9B,aAAe,MAAQ,EAAgB,MAAV,GAAiC,EAAQ,CCxD7D,GACT,EACA,EACA,KAEQ,GAAG,IAAgB,CACvB,GAAI,CACA,EAAQ,GAAG,EAAK,OACX,EAAI,CACT,GAAA,MAAA,EAAe,GAA8B,mBAAoB,EAAG,GAmCnE,EAA2B,GAC/B,GAIE,EAAI,MAAM,oBAAoB,CAAC,KAAK,GAAG,CC/CrC,EAAe,eAMf,GAAe,EAAe,EAAiB,IACxD,GAAG,IAAQ,EAAY,IAAI,EAAU,gBAAkB,GAAG,KAAK,IAEtD,GAAQ,EAAe,EAAiB,IAAkC,SACnF,IAAM,EAAa,EAAY,EAAO,EAAS,EAAU,CAIzD,OAFA,EAAA,cAAA,OAAA,EAAA,EAAa,OAAA,MAAA,EAAA,KAAA,EAAO,EAAW,CAExB,GCZE,OAA0D,CACnE,KACI,EACA,EACA,EACA,EACA,IACC,+BAAO,MAAA,OAAA,EAAA,EAAA,KAAA,EAAM,EAAc,EAAQ,GAAA,KAAA,IAAA,GAAA,EAAA,KAAA,EAAG,EAAQ,EAAK,EAC3D,ECRY,OAA0D,CACnE,YAAa,EAAe,EAAc,IACtC,6BAAO,aAAA,KAAA,IAAA,GAAA,EAAA,KAAA,EAAa,EAAO,EAAe,EAC9C,GAAI,CACA,OAAQ,EAAe,EAAgB,IAAmB,yBAAO,KAAA,OAAA,EAAA,EAAI,QAAA,KAAA,IAAA,GAAA,EAAA,KAAA,EAAQ,EAAQ,EAAM,EAC9F,CACJ,ECNK,EAAQ,mCACR,EAAQ,IAAI,IAEZ,MAAqC,CACvC,GAAI,CAAC,EAAM,IAAI,OAAO,SAAS,KAAK,CAAE,CAClC,IAAM,EAAQ,EAAM,KAAK,OAAO,SAAS,KAAK,CACxC,EAAa,GAAS,EAAM,GAAK,EAAM,GAAK,KAClD,EAAM,IAAI,OAAO,SAAS,KAAM,EAAW,CAE/C,OAAO,EAAM,IAAI,OAAO,SAAS,KAAK,EAG7B,EAAyB,GAAgC,CAClE,IAAM,EAAa,GAAe,CAClC,GAAI,CAAC,GAAQ,CAAC,EACV,OAAO,KAEX,IAAM,EAAY,EAAK,MAAM,IAAI,CAEjC,OADA,EAAU,OAAO,EAAU,OAAS,EAAG,EAAG,EAAW,CAC9C,EAAU,KAAK,IAAI,EAGjB,GAA8B,GAAuC,CAC9E,IAAM,EAAa,GAAe,CAKlC,OAJK,EAIE,GAAG,EAAY,GAAG,IAHd,MC7BF,EAAW,GAAiB,EAAK,QAAQ,KAAM,IAAI,CCanD,GAAgC,EAAgB,EAAsB,EAAQ,IAAM,CAC7F,GAAI,CAAC,IAAoB,CAAE,OAE3B,IAAM,GAAe,EAAgB,EAA2B,IAAkB,CACzE,GACL,GAAQ,GAAG,GAAkB,EAAO,CAAC,GAAG,IAAc,EAAM,EAGhE,EAAY,EAAQ,EAAU,GAAI,EAAM,CACxC,EAAY,EAAQ,GAA2B,EAAU,GAAG,CAAE,EAAM,CAEpE,EAAY,EAAQ,EAAQ,EAAU,KAAK,CAAE,EAAM,CACnD,EAAY,EAAQ,EAAsB,EAAQ,EAAU,KAAK,CAAC,CAAE,EAAM,EAUjE,GAAuB,EAAgB,EAAQ,IAAM,CACzD,IAAoB,EAEzB,GAAQ,GAAkB,EAAO,CAAE,EAAM,EAGvC,OAA2B,wBAAO,SAAA,OAAA,EAAA,EAAQ,KAAA,KAAA,IAAA,GAAA,EAAI,QAAU,YACxD,IAAW,EAAgB,IAAkB,oCAAQ,KAAA,KAAA,IAAA,GAAA,EAAI,MAAM,EAAQ,EAAM,EAE7E,GAAoB,eACpB,GAAqB,GACvB,EAAO,WAAW,GAAkB,CAAG,EAAS,GAAG,GAAkB,GAAG,ICzBtE,IACF,EACA,EACA,IACoC,CACpC,IAAM,OAAiC,CAAE,YAAW,UAAW,IAAI,KAAQ,EAC3E,QAAS,EAAgB,GAAG,IAA0B,CAClD,GAAI,CACA,EAAK,YAAY,CAAE,YAAW,SAAQ,OAAM,QAAS,GAAY,CAAE,CAAC,OAC/D,EAAG,CACR,EAAS,wBAAwB,EAAU,GAAG,IAAU,EAAE,KA2BzD,IACT,EACA,EACA,IAGO,GADM,GAAY,EAAM,EAAW,EAAU,CACA,GAAG,CAUrD,IAAc,EAAgC,IAChD,IAAI,UAAY,GAAI,CAChB,MAAM,EAAS,EAAU,EAAiB,CACtC,EAAK,EAAQ,GAAG,EAAK,EAEzB,IAAI,EAAS,EAAuB,CAC5B,YAAO,GAAS,UAAY,IAAS,QAEzC,OAAO,GAAW,EADL,EAAS,GAAG,EAAO,GAAG,IAAS,EACf,EAEpC,CAAC,CC/EO,IAAkC,EAAiB,IAC5D,GAAa,EAAI,eAAgB,EAAU,CCIlC,OAA6C,CACtD,IAAM,EAAM,IAAI,IAEhB,MAAO,CACH,IAAI,EAAQ,EAAgB,CACxB,EAAI,IAAI,EAAK,EAAM,EAEvB,IAAI,EAAuB,CACvB,OAAO,EAAI,IAAI,EAAI,EAE1B,ECpBC,GAAc,aACd,GAAuB,yCAGvB,IAAe,EAA0B,IAC3C,+BAAO,MAAA,OAAA,EAAA,EAAA,KAAA,EAAM,SAAU,CAAE,WAAY,GAAa,mBAAkB,CAAC,GAAA,KAAA,IAAA,GAAA,EAAA,KAAA,EAAG,MAAO,EAAK,EAqB3E,IAAiB,CAC1B,aACA,cACA,YAAY,IAAI,KAChB,aACA,aAEA,GAAY,GAAsB,CAC9B,aACA,cACA,UAAW,EAAU,SAAS,CAC9B,aACA,GAAI,GAAW,CAAE,UAAS,CAC7B,CAAC,CCjCA,MACD,6BAAO,eAAA,KAAA,EAAA,aAAiB,CAAE,kBAAmB,IAAI,IAAO,CAAjD,GAEC,GAAoB,GAA0B,GAAc,CAAC,kBAAkB,IAAI,EAAK,CAExF,GAAqB,GAAuB,CACrD,GAAc,CAAC,kBAAkB,IAAI,EAAK,ECOjC,GAAgB,EAA8B,IAA2B,CAClF,IAAM,MACF,4BAAe,mBAAA,OAAA,EAAA,EAAmB,KAAA,KAAA,IAAA,GAAA,EAAS,aAAa,EAE5D,MAAO,CACH,GAAG,EAAqC,CACpC,OAAO,GAAiB,GAAK,GAEjC,eAAyB,CACrB,MAAO,CAAC,CAAC,GAAiB,EAAI,GAAiB,GAAK,KAExD,cAAmC,OAC/B,OAAA,EAAO,GAAiB,GAAA,KAAI,IAAJ,GAE/B,EAoBQ,OACT,EAAa,OAAQ,4DAA4D,CAMxE,OACT,EAAa,OAAQ,oEAAoE,CAahF,OACT,EAAa,OAAQ,+DAA+D,CAa3E,OACT,EAAa,OAAQ,0DAA0D,CAatE,OAA2B,EAAa,OAAQ,mDAAmD,CCbnG,GAAc,CACvB,aACA,cAAc,EACd,UAAW,CAAE,UACb,eACmC,CAC9B,IAAoB,CAAC,GAAG,KAAK,EAElC,GAAc,CACV,aACA,cACA,YACA,WAAY,CAAE,GAAG,EAAQ,CAC5B,CAAC,EAGO,GAAkB,GAA4C,CACnE,GAAiB,EAAO,WAAW,GACvC,GAAkB,EAAO,WAAW,CACpC,EAAW,EAAO,GAGhB,EAAqB,kBAEd,GAAoB,GAAgD,OACxE,IAAoB,CAAC,GAAG,KAAK,GAC9B,GAAiB,EAAmB,GACxC,GAAkB,EAAmB,CAErC,GAAc,CACV,WAAY,EACZ,YAAa,EACb,WAAY,CAAE,UAAW,EAAU,OAAO,UAAW,CACrD,SAAA,EAAS,OAAO,mBAAA,KAAoB,EAAE,CAAtB,EACnB,CAAC,ICvHA,GAAmB,uCAEZ,GAAmB,GAA+B,CAC3C,YAAY,iBAAiB,WAAW,CAClC,KAAM,GAAU,kBAAM,KAAK,MAAM,GAAiB,GAAA,KAAA,IAAA,GAAA,EAAG,IAAG,EAG1E,GAAe,CACX,WAAY,oBACZ,YACH,CAAC,ECVJ,GAAe,GAAkE,mBAAoB,EAE9F,GAAc,GAA8D,SAKrF,OAJI,GAAY,EAAU,CACf,EAAU,gBAAkB,SAAS,eAAe,EAAU,gBAAgB,CAAG,MAG5F,GAAA,EAAO,SAAS,eAAe,EAAU,kBAAkB,GAAA,KAAA,IAAA,GAAA,EAAE,gBAAA,KAAiB,KAAjB,GAGpD,EAAgB,GAA0D,CACnF,GAAM,CAAE,qBAAsB,EACxB,EAAY,SAAS,eAAe,EAAkB,CAS5D,OAPK,GACD,EAAW,CACP,WAAY,iCACZ,YACH,CAAC,CAGC,GCnBE,GAAkB,GAA0C,CACrE,GAAI,CAEA,GAAM,CAAE,IAAG,KADC,EAAa,EAAU,CACd,uBAAuB,CACtC,EAAY,CAAE,GAAI,EAAU,YAAa,KAAM,EAAU,cAAe,CAC9E,EAA6B,eAAgB,EAAW,EAAE,CAC1D,EAA6B,eAAgB,EAAW,EAAE,CAC1D,EAAW,CAAE,WAAY,eAAgB,YAAa,EAAG,YAAW,CAAC,CACrE,EAAW,CAAE,WAAY,eAAgB,YAAa,EAAG,YAAW,CAAC,OAChE,EAAI,CAIT,SCTF,GAAQ,GAAsC,CAC5C,IACA,EAAQ,MAAM,QAAU,SAInB,IAAqB,CAAE,YAAW,UAA0C,CACrF,GAAK,GAAW,EAAU,CAAC,CAC3B,GAAK,EAAa,EAAU,CAAC,CAE7B,EAAW,CAAE,WAAY,qBAAsB,YAAW,CAAC,CACvD,GACA,EAAW,CAAE,WAAY,sBAAsB,IAAQ,YAAW,CAAC,ECZ9D,IAAuB,EAAsB,IAAmC,SACzF,IAAA,EAAI,OAAO,SAAA,MAAA,EAAQ,oBAAoB,IAAI,EAAU,kBAAkB,CAAE,CACrE,EAAS,yBAAyB,CAClC,OAGJ,IAAM,EAAY,CAAE,GAAI,EAAU,YAAa,KAAM,EAAU,cAAe,CAC9E,EAAoB,yBAAyB,CAC7C,EAA6B,yBAA0B,EAAU,CACjE,EAAoB,yBAAyB,IAAO,CACpD,EAA6B,yBAAyB,IAAQ,EAAU,CACxE,EAAoB,YAAY,EAAK,aAAa,GAAG,CACrD,EAA6B,YAAY,EAAK,aAAa,GAAI,EAAU,CAEzE,GAAkB,CAAE,YAAW,OAAM,CAAC,EAEtC,EAAA,OAAO,SAAA,MAAA,EAAQ,oBAAoB,IAAI,EAAU,kBAAkB,ECrB1D,GAA2B,2CAC3B,GAA+B,8CAC/B,GAA2B,gDAE3B,IAAyB,EAAsB,IAA6C,OACrG,IAAM,GAAA,EAAM,EAAa,EAAU,GAAA,KAAA,IAAA,GAAA,EAAE,aAAa,kBAAkB,CAChE,GACA,EAAS,IAAI,EAAU,kBAAmB,EAAI,EAIzC,IAAoC,EAAsB,IAAkC,CACrG,GAAI,EAAK,QACL,EAAA,EAAa,EAAU,GAAA,MAAA,EAAE,gBAAgB,UAAU,CACnD,GAAwB,EAAI,MAE5B,OAAO,GAAG,MAAM,GAA8B,EAAE,EAI3C,GAA0B,KAAO,IAAmC,CAC7E,GAAI,CACA,IAAM,EAAW,MAAM,MAAM,EAAwB,CAAE,UAAW,GAAM,SAAU,SAAU,CAAC,CACzF,EAAS,IAAM,EAAS,OAAS,iBACjC,OAAO,GAAG,MAAM,GAA0B,EAAE,CAE5C,OAAO,GAAG,MAAM,GAA0B,EAAE,OAE3C,EAAK,CACV,OAAO,GAAG,MAAM,GAA0B,EAAE,GC3BvC,IACT,EACA,IACS,CACT,IAAM,EAAoC,GAAiB,EAAyB,CAChF,EAAwB,EAG5B,IAAK,GAAM,CAAC,EAAG,KAAM,EAAe,CAChC,GAAI,CAAC,GAAuB,EAAG,EAAE,CAAE,SAEnC,IAAM,EAAiB,SAAS,iBAAiB,EAAG,EAAE,CAClD,GAAkB,GAA4B,EAAgB,EAAiB,EAC/E,IAGR,OAAO,EAAwB,EAAc,QAGpC,GAAoB,GAA6C,CAC1E,IACM,EAAoC,EAAE,CAC5C,IAAK,IAAI,EAAI,EAAG,EAAI,GAAM,IACtB,EAAc,KAAK,CACf,EAAY,KAAO,EAAY,MAAQ,EACvC,EAAY,IAAO,EAAY,QAAU,EAAI,IAAQ,GACxD,CAAC,CAEN,OAAO,GAGE,IAA0B,EAAW,IAAuB,CACrE,IAAM,EAAwB,OAAO,YAAc,SAAS,gBAAgB,YACtE,EAAyB,OAAO,aAAe,SAAS,gBAAgB,aAC9E,OAAO,GAAK,GAAK,GAAK,GAAiB,GAAK,GAAK,GAAK,GAG7C,IAA+B,EAAyB,IAA0C,CAC3G,GACI,EAAE,aAA0B,cAC5B,IAAmB,GACnB,EAAgB,SAAS,EAAe,CAExC,MAAO,GAGX,IAAM,EAAgB,OAAO,iBAAiB,EAAe,CAC7D,GACI,EAAc,UAAY,QAC1B,EAAc,aAAe,UAC7B,EAAc,gBAAkB,QAChC,WAAW,EAAc,QAAQ,CAAG,GAEpC,MAAO,GAGX,IAAM,EAAkB,EAAc,gBAOtC,MAHA,GADI,IAAoB,eAFH,QAEiC,KAAK,EAAgB,EAAI,IAAoB,KACpE,CAAC,EAAc,gBAAgB,SAAS,MAAM,GCnEpE,IAAkC,EAAwB,IAAyB,CAC5F,IAAM,EAAW,KAAK,IAClB,EACA,KAAK,IAAI,EAAc,MAAO,EAAY,MAAM,CAAG,KAAK,IAAI,EAAc,KAAM,EAAY,KAAK,CACpG,CAEK,EAAW,KAAK,IAClB,EACA,KAAK,IAAI,EAAc,OAAQ,EAAY,OAAO,CAAG,KAAK,IAAI,EAAc,IAAK,EAAY,IAAI,CACpG,CAQD,OANI,IAAa,GAAK,IAAa,EACxB,EAGc,EAAW,GACJ,EAAc,MAAQ,EAAc,SAI3D,EAAiC,GAKxC,CACF,GAAM,CAAE,SAAQ,MAAK,OAAO,EAAG,QAAQ,IAAa,EAAK,EACzD,MAAO,CACH,MACA,OAAQ,EAAM,EACd,OACA,MAAO,EAAO,EACd,QACA,SACH,EAGQ,OACF,OAAO,YAAc,SAAS,gBAAgB,YCpC5C,EAAgB,OA2BhB,GAAkB,KAC3B,IAEO,IAAI,SAAS,EAAK,IAAQ,CAC7B,GAAI,OAAO,EAAM,KAAe,CAAC,EAAG,CAChC,EAAQ,MAAM,+BAA+B,CAAC,CAC9C,OAGJ,IAAM,EAAU,eAAiB,CAC7B,EAAQ,MAAM,+BAA+B,CAAC,EAC/C,EAAU,CAEP,EAAY,YAAY,KAAK,CACnC,EAAE,KAAK,EAAc,CAAC,QAAS,GAAS,OACpC,GAAI,EAAA,KAAA,OAAA,EAAC,EAAM,QAAA,OAAA,EAAA,EAAO,iBAAA,OAAA,EAAgB,iBAAiB,CAC/C,aAAa,EAAQ,CACrB,EAAQ,MAAM,+BAA+B,CAAC,CAC9C,OAGJ,EAAK,MAAM,eAAe,gBAAgB,CACtC,gBAAkB,GAAiC,CAC/C,aAAa,EAAQ,CACrB,EAAI,CACA,eAAgB,EAAO,eAAiB,EAAE,EAAE,IAAI,EAA8B,CAC9E,kBAAmB,EAAO,kBAC1B,UAAW,YAAY,KAAK,CAAG,EAClC,CAAC,EAEN,iBAAoB,CAChB,aAAa,EAAQ,CACrB,EAAQ,MAAM,+BAA+B,CAAC,EAErD,CAAC,EACJ,EACJ,CCrDO,GACT,GACO,CACH,OAAO,EAAM,KAAe,CAAC,GAGjC,EAAE,KAAK,EAAc,CAAC,QAAS,GAAS,CACpC,GAAA,MAAA,EAAM,iBAAiB,sBAAuB,EAAQ,EACxD,EAOO,GACT,GACO,CACH,OAAO,EAAM,KAAe,CAAC,GAGjC,EAAE,KAAK,EAAc,CAAC,QAAS,GAAS,CACpC,GAAA,MAAA,EAAM,oBAAoB,sBAAuB,EAAQ,EAC3D,EChBO,IACT,EACA,IACS,CACT,IAAM,EAAwB,EAAuB,0BAA0B,CAO/E,OANI,EAAsB,SAAW,EAC1B,EAEoB,EAAsB,QAAQ,EAAO,IACzD,EAAQ,GAA+B,EAA0B,EAAK,CAC9E,EAAE,EAII,GAA0B,KAAO,IAAkE,CAE5G,GAAI,CACA,EAAuB,yBAAyB,EAAE,CAAC,CAC9C,EAAuB,kBACxB,EAAuB,gBAAmB,GACtC,GAAiC,EAAU,EAAuB,CACtE,GAAqC,EAAuB,gBAAgB,EAEhF,IAAM,EAAqB,MAAM,GAAgB,IAAoB,CACrE,EAAuB,yBAAyB,GAAqB,EAAmB,CAAC,OACpF,EAAK,CACV,QAAQ,MAAM,wCAAyC,EAAI,GAI7D,IACF,EACA,IACC,OACD,EAAuB,2BAAA,GAAA,OAAA,EAClB,EAAkC,SAAA,KAAA,IAAA,GAAA,EAAQ,gBAAiB,EAAE,EAAE,IAAI,EAA8B,CACrG,EAGC,GAAwB,GACtB,EAAS,kBACF,CAAC,EAA8B,CAAE,OAAQ,OAAO,YAAa,IAAK,EAAG,CAAC,CAAC,CAE3E,EAAS,cAAc,IAAI,EAA8B,CAGvD,GAA4C,GAAyD,CAC9G,GAAI,EAAuB,gBAAiB,CACxC,GAAI,CACA,GAAwC,EAAuB,gBAAgB,SAC3E,EAGR,EAAuB,gBAAkB,IAAA,KC/DpC,MAAuE,CAChF,IAAI,EAAmC,EAAE,CAEnC,EAAiD,CACnD,gBAAiB,IAAA,GACjB,yBAA2B,GAAqB,CAC5C,EAAwB,GAE5B,6BAAgC,EACnC,CAID,OAFA,GAAwB,EAAuB,CAExC,CACH,yBAAyB,CACrB,UACA,yBAAyB,EAAQ,uBAAuB,EACpB,CACpC,IAAM,EAA2B,GAA4B,EAAS,EAAuB,CACvF,EAA8B,GAChC,EACA,EACH,CACD,OAAO,KAAK,IAAI,EAA0B,EAA4B,EAE1E,SAAgB,CACZ,GAAyC,EAAuB,EAEvE,ECzBQ,GAA6B,CACtC,SACA,iBACA,SACA,UACA,eACyD,CACzD,IAAM,EAAW,IAAI,sBAAsB,EAAS,IAAa,CAC7D,EAAQ,QAAS,GAAU,CACnB,EAAM,eACN,EAAe,EAAU,EAAM,CAE/B,EAAO,EAAU,EAAM,EAE7B,EACH,EAAQ,CAUX,MARI,EAAE,aAAkB,UAAY,GAChC,EAAW,CACP,WAAY,uCACZ,YACH,CAAC,CAGN,EAAS,QAAQ,EAAO,CACjB,GAGE,GAA2B,MACpC,EACA,IAEO,IAAI,QAAoC,GACpC,EAA0B,CAC7B,SACA,gBAAiB,EAAU,IAAU,CACjC,EAAQ,EAAM,CACd,EAAS,UAAU,EAAM,OAAO,EAEpC,WAAc,GACd,UACH,CAAC,CACJ,CCtCO,GAAb,KAAqE,CAOjE,YACI,EACA,EACA,EACA,EACA,EACA,EACF,CANmB,KAAA,MAAA,EACR,KAAA,oBAAA,EACA,KAAA,wBAAA,EACQ,KAAA,mBAAA,EACA,KAAA,oBAAA,EACA,KAAA,UAAA,qBATgB,IAAI,uBACR,uCA8FC,GAA+B,CACzD,KAAK,eACL,KAAK,WAAW,sCAAuC,EAAG,EAAU,mBAI9D,EAAoB,EAAQ,EAAG,IAAgC,CACpE,KAAK,cAAc,IAAI,EAAW,GACnC,EAAoB,EAAY,EAAM,CAClC,GACA,EAA6B,EAAY,EAAW,EAAM,CAE9D,KAAK,cAAc,IAAI,EAAW,GA/F1C,qBAAqB,EAAgC,EAAsB,CACvE,EAAS,UAAU,EAAU,IAAI,CACjC,aAAa,KAAK,mBAAmB,CACrC,cAAc,KAAK,2BAA2B,CAC9C,KAAK,wBAAwB,iCAAiC,CAC9D,KAAK,+BAA+B,EAAU,CAC9C,KAAK,mBAAmB,SAAS,CAGrC,mCAAoC,CAChC,aAAa,KAAK,mBAAmB,CACrC,cAAc,KAAK,2BAA2B,CAC9C,cAAc,KAAK,0BAA0B,CAC7C,KAAK,wBAAwB,iCAAiC,CAGlE,eAAe,EAAgC,EAA4B,CACvE,KAAK,KAAK,EAAU,CACpB,KAAK,qBAAqB,EAAU,EAAU,CAGlD,iBAAiB,EAAgC,EAAsB,CAEnE,KAAK,mBAAqB,eAChB,KAAK,eAAe,EAAU,EAAU,CAC9C,KAAK,oBAAoB,uBAC5B,CAED,KAAK,kCAAkC,EAAU,EAAU,CAC3D,KAAK,wBAAwB,+BAA+B,KAAK,mBAAoB,EAAU,EAAU,CAI7G,kCAAkC,EAAgC,EAAsB,CAEpF,KAAK,2BAA6B,gBAAkB,CAChD,GAAI,CACgC,KAAK,mBAAmB,wBACpD,EACA,KAAK,oBAAoB,oBAC5B,GAEG,KAAK,cAAgB,GACrB,aAAa,KAAK,mBAAmB,CACrC,cAAc,KAAK,2BAA2B,CAC9C,KAAK,iBAAiB,EAAU,EAAU,QAEzC,EAAY,CACjB,EAAA,GAAA,KAAA,IAAA,GAAS,EAAO,QAAS,EAAM,CAC/B,cAAc,KAAK,2BAA2B,GAf3B,IAiBb,CAGlB,MAAM,EAA4B,CAC9B,EAA0B,CACtB,OAAQ,EAAU,IAClB,eAAiB,GAAa,KAAK,iBAAiB,EAAU,EAAU,CACxE,WAAc,KAAK,mCAAmC,CACtD,QAAS,CAAE,UAAW,KAAK,oBAAoB,oBAAqB,CACpE,UAAW,KAAK,UACnB,CAAC,CAGN,MAAM,KAAK,EAAqC,YACxC,EAAK,qBAAuB,CAAC,EAAK,oBAAoB,iBAAiB,EACvE,MAAM,EAAK,0BAA0B,CAGzC,EAAK,MAAM,KAAK,EAAU,CAG9B,0BAAkD,CAC9C,OAAO,IAAI,QAAS,GAAY,CAC5B,KAAK,0BAA4B,gBAAkB,CAC3C,KAAK,qBAAuB,KAAK,oBAAoB,iBAAiB,GACtE,cAAc,KAAK,0BAA0B,CAC7C,GAAS,GAEd,IAAI,EACT,GC5GJ,EAAiB,IAAI,QAEd,IACT,EACA,IACgB,kBAAe,IAAI,EAAa,GAAA,KAAA,IAAA,GAAA,EAAE,IAAI,EAAI,EAEjD,IACT,EACA,EACA,IACO,CACP,IAAM,EAAQ,EAAe,IAAI,EAAa,CAC1C,EACA,EAAM,IAAI,EAAK,EAAM,CAErB,EAAe,IAAI,EAAc,IAAI,IAAI,CAAC,CAAC,EAAK,EAAM,CAAC,CAAC,CAAC,ECX3D,GAAQ,IACR,GAAQ,IAIR,IAAiB,EAAkB,EAAsB,IAC3D,GAAsC,EAAK,EAAK,EAAM,CAE7C,GAAiB,EAAkB,IAC5C,GAAsC,EAAK,EAAI,GAAK,GAE3C,GAAkB,EAAkB,IAA+B,GAAc,EAAK,EAAK,GAAM,CAEjG,GAAkB,EAAkB,IAA+B,GAAc,EAAK,EAAK,GAAM,CCbjG,GAAiB,EAA6B,IAAgD,CACvG,EAAoB,EAAW,CAC/B,EAA6B,EAAY,CAAE,GAAI,EAAU,YAAa,KAAM,EAAU,cAAe,CAAC,CACtG,EAAoB,GAAG,EAAW,GAAG,EAAU,mBAAmB,cAAc,CAChF,EAAoB,GAAG,EAAW,UAAU,EAAU,WAAW,aAAa,GAAG,CACjF,EAAW,CAAE,aAAY,YAAW,CAAC,ECLnC,GAA8B,CAAE,UAAW,GAAM,KAAM,UAAW,CAc3D,EAAb,KAAwC,CACpC,YACI,EACA,EACA,EACA,EACA,EAAoC,EAAE,CACxC,CALmB,KAAA,IAAA,EACA,KAAA,iBAAA,EACA,KAAA,gBAAA,EACA,KAAA,UAAA,EACA,KAAA,OAAA,aAuBJ,GAA2C,CACxD,IAAM,EAAQ,SAAS,cAAc,MAAM,CAI3C,MAHA,GAAM,GAAK,GAAG,KAAK,gBAAgB,OAAO,GAAG,EAAU,OACvD,EAAM,MAAM,QAAU,OACtB,EAAM,aAAa,YAAa,KAAK,iBAAiB,KAAK,IAAK,EAAU,CAAC,CACpE,GAzBX,MAAa,KAAK,EAAqC,YAC/C,MAAc,EAAU,IAAK,EAAK,gBAAgB,WAAW,CACjE,GAAe,EAAU,IAAK,EAAK,gBAAgB,WAAW,CAC9D,GAAI,CACA,MAAM,MAAM,EAAK,iBAAiB,EAAK,IAAK,EAAU,CAAE,GAAe,OAClE,EAAG,CAER,MADA,EAAe,EAAU,IAAK,EAAK,gBAAgB,WAAW,CACxD,EAEV,EAAU,IAAI,YAAY,EAAK,MAAM,EAAU,CAAC,CAChD,EAAc,EAAK,gBAAgB,WAAY,EAAK,UAAU,CAG9D,EAAK,OAAO,QAAS,GAAU,MAAM,EAAO,GAAe,CAAC,ICtCvD,GAAkC,CAAE,OAAQ,qBAAsB,WAAY,gBAAiB,CAC/F,GAAyC,CAClD,OAAQ,iBACR,WAAY,gBACf,CACY,GAA4C,CACrD,OAAQ,oBACR,WAAY,gBACf,CACY,GAA8C,CACvD,OAAQ,sBACR,WAAY,iBACf,CCdY,GAAkC,GAAqC,CAChF,IAAM,EAAe,OAAO,aAAe,SAAS,gBAAgB,aAC9D,EAAc,OAAO,YAAc,SAAS,gBAAgB,YAE5D,EAAc,CAChB,IAAK,KAAK,IAAI,EAAG,EAAgB,IAAI,CACrC,KAAM,KAAK,IAAI,EAAG,EAAgB,KAAK,CACvC,OAAQ,KAAK,IAAI,EAAc,EAAgB,OAAO,CACtD,MAAO,KAAK,IAAI,EAAa,EAAgB,MAAM,CACtD,CAgBD,OAbI,EAAgB,KAAO,GACvB,EAAgB,MAAQ,GACxB,EAAgB,QAAU,GAC1B,EAAgB,OAAS,GACzB,EAAgB,OAAS,GACzB,EAAgB,QAAU,EAEnB,GAGU,EAAY,MAAQ,EAAY,OAAS,EAAY,OAAS,EAAY,MAC7E,EAAgB,MAAQ,EAAgB,SCtBjD,EAAW,CACpB,kBAAmB,IACnB,iBAAkB,IACrB,CAYY,GAA+B,GAAkC,CAC1E,GAAI,GAAqB,EAAU,CAAE,CACjC,IAAM,EAAyB,CAC3B,OAAQ,EAAS,kBACjB,MAAO,EAAS,iBACnB,CACD,OAAO,GAAkB,EAAU,IAAK,EAAW,CAEvD,OAAO,EAAU,IAAI,uBAAuB,EAQnC,GAAwB,GACX,EAAU,KAAK,aAAa,GAChB,6BAWzB,IAAqB,EAAsB,IAAuC,CAC3F,IAAM,EAAkB,EAAQ,uBAAuB,CAEjD,GADU,EAAgB,KAAO,EAAgB,OAAS,EAC1C,EAAc,MAAQ,EAC5C,OAAO,IAAI,QAAQ,EAAM,EAAgB,EAAG,EAAc,MAAO,EAAc,OAAO,EC3C7E,EACT,GACqB,CACrB,IAAM,EAA6B,IAAI,IAEjC,GAAc,EAAoB,EAAQ,EAAG,IAAgC,CAC1E,EAAc,IAAI,EAAW,GAC9B,EAAoB,EAAY,EAAM,CAClC,GACA,EAA6B,EAAY,EAAW,EAAM,CAE9D,EAAc,IAAI,EAAW,GAI/B,GAA2B,EAAsB,IAA+B,CAClF,IAAM,EAA2B,GAA4B,EAAU,CAOjE,EAN8B,GAA+B,EAAyB,CAC9D,EAA4B,yBAAyB,CAC/E,QAAS,EAAU,IACnB,uBAAwB,EAC3B,CAAC,CAEoF,EAItF,OAHI,GACA,EAAW,4BAA6B,EAAG,EAAU,CAElD,GAGX,MAAO,CACH,wBAAwB,EAAsB,EAA4B,CACtE,OAAO,EAAwB,EAAW,EAAU,EAExD,SAAgB,CACZ,EAA4B,SAAS,EAE5C,ECpCQ,OAA8D,CACvE,IAAM,GACF,EACA,EACA,IACC,CACG,SAAS,QACT,aAAa,EAAU,CACvB,EAAS,UAAU,EAAU,IAAI,EAEjC,EAAS,QAAQ,EAAU,IAAI,EAIvC,MAAO,CACH,iCAAwC,CAChC,KAAK,yBACL,SAAS,oBAAoB,mBAAoB,KAAK,uBAAuB,CAC7E,KAAK,uBAAyB,IAAA,KAItC,+BACI,EACA,EACA,EACI,CACJ,KAAK,iCAAiC,CACtC,KAAK,2BAA+B,EAA6B,EAAW,EAAU,EAAU,CAChG,SAAS,iBAAiB,mBAAoB,KAAK,uBAAuB,EAEjF,ECdQ,GAAmC,GAAmC,QAC/E,EAAA,OAAO,IAAA,MAAA,EAAG,KAAA,uBAA6B,CAAC,QAAS,GAA6C,CAC1F,EAAoB,gCAAgC,CAAe,cAAa,CAAC,EACnF,EAUO,GAAiC,GAAmC,QAC7E,EAAA,OAAO,IAAA,MAAA,EAAG,KAAA,uBAA6B,CAAC,QAAS,GAA6C,CAC1F,EAAoB,8BAA8B,CAAe,cAAa,CAAC,EACjF,ECrCA,EAAc,iBAEP,GAAb,KAAsD,CAClD,YAAY,EAAwD,CAAvC,KAAA,UAAA,EAE7B,MAAM,KAAK,EAAqC,YACxC,MAAc,EAAU,IAAK,EAAY,CAG7C,GAAe,EAAU,IAAK,EAAY,CAC1C,GAAI,CACA,GAAgC,EAAK,UAAU,YAAa,OACvD,EAAG,CAER,MADA,EAAe,EAAU,IAAK,EAAY,CACpC,EAEV,EAAc,EAAa,EAAK,UAAU,IChB5C,EAAc,kBAEP,GAAb,KAAgD,CAC5C,YAAY,EAAwD,CAAvC,KAAA,UAAA,EAE7B,MAAM,KAAK,EAAqC,YACxC,MAAc,EAAU,IAAK,EAAY,CAG7C,GAAe,EAAU,IAAK,EAAY,CAC1C,GAAI,CACA,GAA8B,EAAK,UAAU,YAAa,OACrD,EAAG,CAER,MADA,EAAe,EAAU,IAAK,EAAY,CACpC,EAEV,EAAc,EAAa,EAAK,UAAU,ICvBrC,GAAyB,aCEzB,EAAe,eACf,GAAkB,kBCJzB,GAA2B,KAC3B,GAAe,GAoBR,IACT,EACA,EACA,IACS,CACT,GAAI,IAAkB,GAClB,MAAU,MACN,0DACI,KAAK,UAAU,CAAiB,gBAAe,CAAC,CACvD,CAEL,IAAM,EAAY,IAAI,IAAI,EAAI,CACxB,EAAK,EAAU,aAAa,IAAI,EAAc,CAE9C,EAAqB,KAAK,MADL,GAAU,GACoB,CACnD,EAAmB,OAAO,OAAO,EAAoB,EAAsB,CAEjF,OADA,EAAU,aAAa,IAAI,EAAe,KAAK,UAAU,EAAiB,CAAC,CACpE,EAAU,UAAU,EChClB,GAA0C,GAEnD,GAAuB,EAAwB,EAAI,CAAA,IAAgB,CAC/D,kBAAmB,GACtB,CAAC,CCRO,GAAiD,GAAwB,ECWzE,MACF,OAAO,aAAe,SAAS,gBAAgB,aAM7C,MACF,OAAO,YAAc,SAAS,gBAAgB,YAO5C,GAA4B,GAChB,EAAK,uBAAuB,CAC7B,IAAM,GAAc,CAG/B,IAAuC,EAAuB,KAChE,CACH,EAAG,EAAa,IAChB,EAAG,EAAa,KAChB,EAAG,EAAa,MAChB,EAAG,EAAa,OAChB,EAAG,EAAa,MAChB,EAAG,EAAa,OACb,IACN,EAMQ,EAAsB,GAExB,GADc,EAAK,uBAAuB,CACQ,OAAO,OAAO,iBAAiB,EAAM,KAAK,CAAC,OAAO,CAAC,CAWnG,GAAc,GAA2C,CAClE,IAAM,EAAM,GAAyC,EAAK,CAM1D,OALI,GAAO,KACA,UACA,GAAO,IAOhB,GAAuC,GAClC,EAAQ,QAAU,GAAK,EAAQ,SAAW,EAQrD,SAAgB,GAAyC,EAAkC,CACvF,IAAM,EAAU,SAAS,KAAK,uBAAuB,CACrD,GAAI,GAAoC,EAAQ,CAAE,OAAO,KACzD,IAAM,EAAU,EAAmB,EAAK,CAClC,EAAK,GAAc,CACnB,EAAK,GAAa,CAIlB,EAFgB,KAAK,IAAI,EAAG,KAAK,IAAI,EAAQ,KAAO,EAAI,EAAQ,EAAE,CAAG,EAAQ,EAAE,CAC9D,KAAK,IAAI,EAAG,KAAK,IAAI,EAAQ,IAAM,EAAI,EAAQ,EAAE,CAAG,EAAQ,EAAE,EAC3B,EAAQ,EAAI,KAAK,IAAI,EAAQ,EAAG,EAAG,EAE7F,OADuC,OAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,EAAc,CAAC,CAAC,QAAQ,EAAE,CAAC,CAIrG,IAAa,IAAuB,EAAoB,IAAuC,CAC3F,IAAM,EAAY,EAAmB,EAAM,CACrC,EAAY,EAAmB,EAAM,CACrC,EAAK,GAAa,CAClB,EAAK,GAAc,CACzB,OACI,GACA,IACC,KAAK,IAAI,EAAU,EAAI,EAAU,EAAE,CAAG,GAAM,KAAK,IAAI,EAAU,EAAI,EAAU,EAAE,CAAG,KAClF,KAAK,IAAI,EAAU,EAAI,EAAU,EAAE,CAAG,GAAM,KAAK,IAAI,EAAU,EAAI,EAAU,EAAE,CAAG,ICnG9E,IAAoD,EAAa,IAA8B,CACxG,IAAM,EAAa,CAAE,IAAK,GAAW,EAAO,IAAI,CAAE,CAC5C,EAAoB,mBAAmB,KAAK,UAAU,EAAW,CAAC,CACxE,OAAO,EAAa,KAAK,EAAI,CACvB,EAAI,QAAQ,EAAA,MAA0B,CAAC,QAAQ,GAAiB,EAAkB,CAClF,GAAG,EAAI,QAAQ,MAAO,GAAG,CAAC,OAAkB,KCRzC,EAAM,CACf,KAAM,EAAsB,IAAyB,CACjD,EAAU,IAAI,QAAQ,MAAQ,OAAO,EAAM,EAE/C,IAAM,GACK,EAAU,IAAI,QAAQ,QAAU,OAE9C,CCSY,GAAsB,GAAiD,OAChF,IAAM,EAAmB,EAAe,UAAU,IAAI,uBAAuB,CAC7E,MAAO,CACH,EAAG,CACC,IAAK,EAAe,WACpB,EAAG,EAAe,oBAClB,EAAG,EAAe,uBAClB,GAAI,EAAe,MACtB,CACD,GAAI,OAAO,aAAe,SAAS,gBAAgB,aACnD,GAAI,OAAO,YAAc,SAAS,gBAAgB,YAClD,GAAI,OAAO,QACX,GAAI,OAAO,QACX,GAAI,EAAiB,OACrB,GAAI,EAAiB,MACrB,IAAK,EAAiB,IACtB,KAAM,EAAiB,KACvB,KAAM,IAAI,MAAM,CAAC,SAAS,GAAA,EAAI,OAAO,aAAA,KAAc,EAAd,IAAoB,IACzD,KAAM,IAAI,MAAM,CAAC,SAAS,CAAG,EAAe,aAAe,IAC9D,EAGQ,GAAsC,GAAgE,CAC/G,IAAM,EAAc,IAAI,MAAM,CAAC,SAAS,CACxC,OAAQ,EAAa,IAAiC,CAClD,IAAM,EAAiC,CACxB,YACX,WAAY,EAAoB,WAChC,oBAAqB,EAAoB,oBACzC,uBAAwB,EAAoB,uBAC5C,MAAO,EAAI,IAAI,EAAU,CACzB,cACH,CAEK,EAAoB,mBAAmB,KAAK,UAAU,GAAmB,EAAe,CAAC,CAAC,CAEhG,OAAO,EAAa,KAAK,EAAI,CACvB,EAAI,QAAQ,EAAA,IAAiC,CAAC,QAAQ,GAAiB,EAAkB,CACzF,GAAG,EAAI,QAAQ,OAAQ,GAAG,CAAC,KAAyB,MC1BrD,EAAwB,CACjC,UAzBmC,CACnC,WAAY,MACZ,oBAAqB,GACrB,uBAAwB,IAC3B,CAsBG,kBApB2C,CAC3C,WAAY,MACZ,oBAAqB,GACrB,uBAAwB,IAC3B,CAiBG,YAfqC,CACrC,WAAY,MACZ,oBAAqB,GACrB,uBAAwB,IAC3B,CAYG,KAV8B,CAC9B,WAAY,OACZ,oBAAqB,GACrB,uBAAwB,IAC3B,CAOA,CCdY,GACT,EACA,EACA,EACA,EACA,IACY,CAMZ,IAAM,EAAS,GAA+B,CAC1C,IAAI,EAEE,EAAe,CAAE,cAAe,GAAO,CAE7C,EAA0B,CACtB,OAAQ,EAAU,IAClB,eAAiB,GAAc,EAAU,EAAe,EAAW,EAAU,EAAM,CACnF,WAAA,GAAA,KAAA,IAAA,GAAc,GAAW,CACzB,QAAS,CAAE,UAAW,EAAoB,oBAAqB,CAC/D,YACH,CAAC,EAiBA,GAAkB,EAAsB,EAAgC,IAA0B,CACpG,IAAI,EAAmB,YAAY,KAAK,CACpC,EAAa,GAEX,EAAa,gBAAkB,CAE7B,EAAa,EAAU,EAAI,IAAU,EACrC,EAAM,cAAgB,GACtB,EAAa,IAGR,GACL,EAAmB,YAAY,KAAK,CACpC,EAAa,IAIb,GAAgB,EAAkB,EAAoB,uBAAuB,EAC7E,GAAgB,EAAoB,GAEpC,EAAO,QAAS,GAAU,EAAM,KAAK,EAAU,CAAC,CAChD,EAAQ,EAAM,cAAc,CAC5B,EAAS,UAAU,EAAU,IAAI,GAEtC,GAAqB,CAElB,GAAW,EAAgB,KAAgB,CACzC,GACA,GAAuB,EAAU,CAErC,cAAc,EAAW,CACzB,EAAmB,SAAS,EAGhC,OAAO,GAOL,EAAgB,GAAkC,CACpD,GAAI,CACA,OAAO,EAAmB,wBAAwB,EAAW,EAAoB,oBAAoB,OAChG,EAAY,CAEjB,OADA,EAAA,GAAA,KAAA,IAAA,GAAS,EAAO,QAAS,EAAM,CACxB,KAIf,MAAO,CAAE,QAAO,sBAAqB,EAOnC,GAAuB,IAMvB,OAA0B,SAAS,OAQnC,IAAmB,EAA0B,IAC/C,YAAY,KAAK,CAAG,GAAoB,EAOtC,GAAmB,GAA8C,EAAW,MAAO,GAAM,EAAE,iBAAiB,CAAC,CAM7G,GAA0B,GAA+B,CAC3D,IAAM,EAAa,sCACnB,EAAoB,EAAW,CAC/B,EAA6B,EAAY,EAAU,EC3H1C,GAAiB,GACnB,EAAU,YACX,IAAI,EAAM,EAAU,YAAa,GAAqB,GAAgB,EAAU,CAChF,IAAA,GAGG,IAAwB,EAAuC,EAAsB,EAAE,GAChG,IAAI,EAAM,EAAU,eAAgB,GAA4B,GAAuB,EAAW,EAAU,CAEnG,GAA2B,GACpC,IAAI,EAAM,EAAU,iBAAkB,GAA+B,GAA0B,EAAU,CAEhG,GAAqB,MAC9B,EACA,EACA,EACA,IAEI,IAAc,IACP,EAAmB,EAAW,EAAsB,UAAW,MAAM,GAAoB,CAAC,CAC1F,GAAU,EAAU,WAAW,EAAI,GAAU,EAAY,CACzD,EAAmB,EAAW,EAAsB,kBAAkB,CAEtE,EAAmB,EAAW,EAAsB,YAAY,CAIzE,GAAa,GAAoC,IAAe,UAOhE,GAAa,GAAsC,GAA8B,EAAY,EAAI,OAEjG,GAAiC,GACnC,EAAY,uBAAuB,CAAC,OAAS,EAAY,uBAAuB,CAAC,MAE/E,GACF,EACA,EACA,IACY,CACZ,IAAM,EAAQ,IAAI,EACd,EAAU,iBACV,GAAmC,EAAS,CAC5C,GACA,EACH,CAWG,OATA,IAAgC,CAAC,GAAG,KAAK,CAClC,EACH,CAAC,EAAM,CACP,EACA,EAAyB,GAAmC,CAAC,CAC7D,EAAY,CAAC,EAAU,CAAG,EAAE,CAC5B,EACH,CAEM,IAAI,GACP,EACA,EACA,IAA8B,CAC9B,EAAyB,GAAmC,CAAC,CAC7D,EACA,EACH,EAII,GAA4B,GAC9B,EAAU,YAAc,IAAI,GAAoB,EAAU,CAAG,IAAA,GAG3D,GAAsB,GAAiE,CAChG,GAAI,EAAU,YAEV,OAAO,IAAI,GADO,IAAI,GAAc,EAAU,CAG1C,EAAsB,KACtB,IAA8B,CAC9B,EAAyB,GAAmC,CAAC,CAC7D,IAAA,GACA,EACH,EC3FH,GAAqD,CACvD,EAAG,EACH,GAAI,GACJ,GAAI,GACJ,GAAI,GACJ,GAAI,GACJ,GAAI,GACP,CAEK,GAAmD,CACrD,EAAG,EACH,GAAI,IACJ,GAAI,IACJ,GAAI,IACJ,GAAI,IACJ,GAAI,IACJ,GAAI,IACJ,GAAI,IACJ,GAAI,IACJ,GAAI,IACP,CAEY,GAA+B,GACjC,IAAiB,MAAQ,IAAsB,CAAC,eAAe,CAGpE,GAAyB,IACpB,CACH,iBAA2B,CACvB,OAAO,EAAI,IAAI,EAAU,EAEhC,EAGQ,IACT,EACA,EACA,EACA,IACO,CACP,IAAM,EAAsB,CACxB,WAAY,GACZ,oBAAqB,GAA2B,IAAsB,CAAC,cAAc,EACrF,uBAAwB,GAAyB,IAA8B,CAAC,cAAc,EACjG,CAE6B,EAC1B,CAAC,EAAO,gBAAiB,EAAO,mBAAmB,CACnD,EACA,EACA,EAAE,CACF,EACH,CACqB,MAAM,EAAU,CAGlC,EAAO,UACuB,EAC1B,CAAC,EAAO,SAAS,CACjB,EACA,EACA,CAAC,GAAsB,EAAU,CAAC,CAClC,EACH,CACqB,MAAM,EAAU,EC7D9C,SAAS,GAAU,EAAO,EAAU,EAAS,CAC3C,IAAI,EAAO,GAAW,EAAE,CACpB,EAAkB,EAAK,WACvB,EAAa,IAAoB,IAAK,GAAI,GAAQ,EAClD,EAAiB,EAAK,UACtB,EAAY,IAAmB,IAAK,GAAI,GAAQ,EAChD,EAAoB,EAAK,aACzB,EAAe,IAAsB,IAAK,GAAI,IAAA,GAAY,EAQ1D,EACA,EAAY,GAEZ,EAAW,EAEf,SAAS,GAAuB,CAC1B,GACF,aAAa,EAAU,CAK3B,SAAS,EAAO,EAAS,CACvB,IACI,GADQ,GAAW,EAAE,EACM,aAC3B,EAAe,IAAuB,IAAK,GAAI,GAAQ,EAE3D,GAAsB,CACtB,EAAY,CAAC,EASf,SAAS,GAAU,CACjB,IAAK,IAAI,EAAO,UAAU,OAAQ,EAAiB,MAAM,EAAK,CAAE,EAAO,EAAG,EAAO,EAAM,IACrF,EAAW,GAAQ,UAAU,GAG/B,IAAI,EAAO,KACP,EAAU,KAAK,KAAK,CAAG,EAE3B,GAAI,EACF,OAIF,SAAS,GAAO,CACd,EAAW,KAAK,KAAK,CACrB,EAAS,MAAM,EAAM,EAAW,CAQlC,SAAS,GAAQ,CACf,EAAY,IAAA,GAGV,CAAC,GAAa,GAAgB,CAAC,GAMjC,GAAM,CAGR,GAAsB,CAElB,IAAiB,IAAA,IAAa,EAAU,EACtC,GAMF,EAAW,KAAK,KAAK,CAEhB,IACH,EAAY,WAAW,EAAe,EAAQ,EAAM,EAAM,GAO5D,GAAM,CAEC,IAAe,KAYxB,EAAY,WAAW,EAAe,EAAQ,EAAM,IAAiB,IAAA,GAAY,EAAQ,EAAU,EAAM,EAM7G,MAFA,GAAQ,OAAS,EAEV,ECrIT,IAAa,GAAa,MAAO,EAAoC,IAA0B,CACvF,MAAA,MAAC,EAAgB,MAAM,CAAC,MAAM,eAAe,CAMjD,OAAO,MAAM,GACT,SAAS,EAAgB,GAAG,CAC5B,GACC,EAAmB,IAA4B,CAC5C,IAAM,EAAW,GAAyB,EAAK,CAC/C,OAAO,GAAQ,GAAY,GAElC,EAOC,GAAiB,MACnB,EACA,EACA,IAEO,IAAI,QAAe,GAAM,CAC5B,IAAM,MAAwB,CACtB,EAAyB,EAAU,EAAO,GAC1C,GAAG,CACH,OAAO,oBAAoB,SAAU,EAAyB,CAC9D,OAAO,oBAAoB,SAAU,EAAyB,GAIhE,EAA2B,EAC7B,GAAS,OAAU,CACf,GAAiB,EACnB,CACF,EACH,CACD,OAAO,iBAAiB,SAAU,EAAyB,CAC3D,OAAO,iBAAiB,SAAU,EAAyB,CAI3D,GAAiB,EACnB,CC7CO,EAA4B,KAAO,IAAyB,CACrE,IAAM,EAAY,EAAa,EAAU,CAErC,EAAU,iBACV,MAAM,GAAW,EAAU,gBAAiB,EAAU,CAO1D,MAAM,GAAyB,EAAW,CACtC,KAAM,GAAyB,EAAU,CAAG,GAAgB,SAAS,gBACxE,CAAC,EAIA,GAAgB,KAOhB,GAA4B,GAAkC,CAChE,IAAI,EAAoC,EACxC,KAAO,GAAe,CAGlB,GADoB,OAAO,iBAAiB,EAAe,KAAK,CAChD,iBAAiB,WAAW,GAAK,QAC7C,MAAO,GAEX,EAAgB,EAAc,cAGlC,MAAO,ICrCE,GAAwC,KAAO,IAAyB,OAE7E,GAA4B,OAAO,EAAU,mBAAmB,YAAY,CAAC,GAEjF,MAAM,EAA0B,EAAU,EAE1C,EAAA,GAAc,EAAU,GAAA,MAAA,EAAE,KAAK,CAC3B,GAAI,EAAU,YACd,KAAM,EAAU,cAChB,IAAK,EAAa,EAAU,CAC5B,WAAY,EAAU,WACzB,CAAC,GClBN,SAAgB,GAA0B,EAAqB,EAAc,EAA0C,CACnH,EAAO,iBAAiB,GAAQ,GAAa,CACzC,EAAQ,EAAoB,GACZ,CC8BxB,IAAa,GAA0B,MAAO,CAC1C,YACA,SACA,YAAY,IACZ,oBAAoB,OACa,CACjC,GAAI,GAAW,CAAE,CACb,MAAM,GAAQ,CACd,OAGJ,OAAO,IAAI,SAAe,EAAS,IAAW,CAC1C,IAAM,EAAY,YAAY,KAAK,CAC/B,EAAe,GAGb,EAAQ,SAA2B,CACrC,GAAI,GAAW,CAAE,CACb,GAAI,CACA,MAAM,GAAQ,CACd,GAAS,OACJ,EAAO,CACZ,EAAO,EAAM,CAEjB,OAGJ,IAAM,EAAU,YAAY,KAAK,CAAG,EAEpC,GAAI,GAAW,EAAW,CACtB,EAAW,MAAM,2BAA2B,EAAU,IAAI,CAAC,CAC3D,OAGA,EAAU,IACV,sBAAsB,EAAM,EAE5B,WAAW,EAAO,EAAa,CAC/B,EAAe,KAAK,IAAI,EAAe,EAAmB,IAAI,GAItE,GAAO,EACT,ECvEO,GAA6C,mCAM7C,GAA0C,GAA6C,CAChG,IAAI,EAAmC,EAUvC,OARA,GACI,EAAU,IACV,GACC,GAAU,CACP,EAAmC,EAAM,OAAO,kCAEvD,CAEM,CACH,iBAA2B,CACvB,OAAO,GAAoC,GAElD,ECpBQ,GAA+B,KAAO,IAAyB,SACxE,IAAM,EAAuB,CACzB,GAAI,EAAU,YACd,KAAM,EAAU,cAChB,IAAK,EAAa,EAAU,CAC5B,WAAY,EAAU,WACzB,CAED,OAAA,EAAM,GAAyB,EAAU,GAAA,KAAA,IAAA,GAAA,EAAE,KAAK,EAAU,GAC1D,EAAA,GAAmB,EAAU,GAAA,MAAA,EAAE,MAAM,EAAU,ECKtC,GAAiC,MAAO,EAAsB,IAA+B,CACtG,IAAM,EAAe,EAAa,EAAU,CAC5C,MAAM,EAA0B,EAAU,CAC1C,IAAM,EAAuB,CACzB,GAAI,EAAU,YACd,KAAM,EAAU,cAChB,IAAK,EACL,WAAY,EAAU,WACzB,CAID,GAFA,EAAI,IAAI,EAAW,EAAK,MAAM,CAE1B,GAA4B,OAAO,EAAU,mBAAmB,YAAY,CAAC,CAAE,CAC/E,IAAM,EAA8B,GAAmC,CACvE,GACI,EACA,CACI,gBAAiB,GAAqB,EAAU,CAChD,SAAU,GAAc,EAAU,CAClC,mBAAoB,GAAwB,EAAU,CACzD,CACD,EAAyB,EAA4B,CACrD,EACH,MAED,GAAwB,EAAU,CAAC,KAAK,EAAU,CAGtD,GAA6B,EAAU,EAEtC,MAAM,GAAgB,EAAW,EAAU,EAAE,MAAM,EAAU,EAG5D,GAAkB,MAAO,EAAsB,IAE1C,GAAmB,EAAU,UAAW,EAAU,IAAK,MADxB,QAAQ,QAAQ,GAAuC,EAAU,CAAC,CACP,CCnDxF,EAAa,GAA4C,CAClE,GAAM,CAAE,kBAAmB,EACrB,EAAS,SAAS,eAAe,EAAe,CAStD,OAPK,GACD,EAAW,CACP,WAAY,8BACZ,YACH,CAAC,CAGC,GCNL,GAA4B,MAAM,KAAK,CAAE,OAAQ,IAAK,EAAG,EAAG,KAAO,EAAI,GAAK,IAAI,CAEzE,IAAkC,EAAsB,IAA+B,CAChG,IAAM,EAAS,EAAU,EAAU,CAC9B,GAEL,IAAI,qBAAsB,GAAY,EAAQ,QAAS,GAAU,GAAiB,EAAQ,EAAM,CAAC,CAAE,CAC/F,UAAW,GACd,CAAC,CAAC,QAAQ,EAAO,EAGhB,IACF,EACA,CAAE,SAAQ,mBAAkB,qBAAoB,uBACzC,CACP,IAAM,EAAS,EACT,EAAoB,EAAiB,MAAQ,EAAmB,MAChE,EAAoB,EAAiB,OAAS,EAAmB,OAEvE,EAAO,qBAAqB,CACxB,KAAM,CACF,KAAM,CACF,EAAG,EAAmB,IACtB,EAAG,EAAmB,KACtB,EAAG,EAAmB,MACtB,EAAG,EAAmB,OACtB,IAAK,EACL,IAAK,EACL,GAAI,EACJ,EAAG,EACH,EAAG,EAAO,YACV,EAAG,EAAO,aACb,CACJ,CACD,iBAAkB,KAAK,MAAM,EAAoB,IAAI,CACxD,CAAC,EAGO,IAAsB,EAAsB,IAAqC,CAC1F,IAAM,EAAS,EAAU,EAAU,CAE9B,GAEL,gBAAkB,CACd,IAAM,EAAO,EAAO,uBAAuB,CAE3C,EAAO,aAAa,CAChB,KAAM,CACF,KAAM,CACF,EAAG,EAAK,IACR,EAAG,EAAK,KACR,EAAG,EAAK,MACR,EAAG,EAAK,OACR,EAAG,EACH,EAAG,EAAO,YACV,EAAG,EAAO,aACb,CACJ,CACJ,CAAC,EACH,IAAI,ECvDE,IAAwB,EAAsB,EAA0B,IAA2B,UAC5G,GAAA,EAAA,QAAO,MAAA,MAAA,EAAA,KAAA,EAAM,UAAW,CAAE,UAAS,CAAC,CAAC,OAAQ,EAAA,GAAA,KAAA,IAAA,GAAQ,EAAW,SAAS,CAAC,EC0ExE,IAAe,EAAqB,EAAe,IAAuB,aACxE,IAAU,MAAM,GAAA,EAAA,QAAO,MAAA,MAAA,EAAA,KAAA,EAAM,EAAO,EAAO,CAAE,GAAI,EAAG,CAAE,EAAK,EAC1D,GAAA,EAAA,QAAO,MAAA,MAAA,EAAA,KAAA,EAAM,EAAO,EAAO,CAAE,GAAI,EAAG,CAAE,EAAK,EAiBvC,IAAwB,CAAE,eAAc,QAAO,YAAW,eAAqC,OACxG,IAAM,EAAS,gBAAgB,EAAQ,GAAG,EAAQ,EAAM,CAAC,GAAK,KACxD,GAAA,EAAA,GAAA,KAAA,IAAA,GAAO,EAAW,SAAS,GAAA,KAAI,KAAK,KAAK,CAAd,EAEjC,GAAY,EAAc,EAAS,EAAU,GAAI,EAAK,CACtD,GAAY,EAAc,EAAS,EAAQ,EAAU,KAAK,CAAE,EAAK,ECjG/D,GAA+D,CACjE,GAAI,CAAC,KAAM,YAAY,CACvB,GAAI,CAAC,eAAe,CACpB,GAAI,CAAC,kBAAmB,aAAa,CACrC,GAAI,CAAC,SAAU,aAAa,CAC/B,CAEY,GAAqB,CAAE,YAAW,eAAc,QAAO,eAAuC,SACvG,IAAM,GAAA,EAAU,GAAW,EAAU,GAAA,KAAK,SAAS,eAAe,EAAU,kBAAkB,CAAzD,EAC/B,CAAE,YAAa,EAAI,cAAe,GAAS,EAEjD,GAAqB,CAAE,eAAc,UAAW,CAAE,KAAI,OAAM,CAAE,QAAO,YAAW,CAAC,EACjF,EAAA,GAAU,KAAA,MAAA,EAAe,QAAS,GAAW,GAAqB,EAAS,EAAQ,EAAU,CAAC,EAQrF,GACT,GACU,CAAC,EAAU,+BChCZ,GAAe,qBACtB,GAAwB,WACjB,GAA0B,wBAC1B,GAA0B,wBAE1B,GAAgC,GAA+B,CACxE,IAAM,EAAS,SAAS,gBAClB,EAAe,EAAa,EAAU,CAE5C,GAAmB,EAAQ,EAAa,CAExC,IAAI,iBAAkB,GAAc,CAChC,IAAK,IAAM,KAAY,EACnB,GAAI,EAAS,OAAS,cAAgB,EAAS,gBAAkB,QAAS,CACtE,IAAM,EAAgB,EAAS,OAC/B,GAAmB,EAAe,EAAa,GAGzD,CAAC,QAAQ,EAAQ,CACf,WAAY,GACZ,gBAAiB,CAAC,QAAQ,CAC7B,CAAC,EAGA,IAAsB,EAAwB,IAA8B,CAC9E,GAAI,EAAc,UAAU,SAAA,2BAA8B,CAAE,CACxD,EAAa,UAAU,IAAI,GAAsB,CACjD,IAAM,EAAW,IAAa,CAC9B,EAAa,MAAM,YAAY,GAAyB,GAAG,EAAS,IAAI,CACxE,EAAa,MAAM,YAAY,GAAyB,GAAG,EAAW,EAAE,IAAI,MAE5E,EAAa,UAAU,OAAO,GAAsB,EAItD,OAA4B,CAC9B,IAAM,EAAM,SAAS,cAAc,GAAa,CAChD,OAAO,aAAe,YAAc,EAAI,YAAc,GCZ7C,GAA8B,GAAuD,CAC9F,IAAM,EAAwB,IAAgC,CAE9D,MAAO,CACH,iBAAiB,CAAE,YAAW,YAAW,eAAwB,EAAyB,CACtF,EAAW,CACP,WAAY,cACZ,YACA,YACA,YAAa,EAChB,CAAC,CACF,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,CAE5E,EAAK,EAAc,iBAAkB,EAAU,CAC/C,EAAI,gBAAuC,EAAU,KAAM,yBAA0B,CACjF,WAAY,OAAO,WACnB,YAAa,IAAI,MAAM,CAAC,SAAS,CACpC,CAAC,CAGF,OAAO,iBAAiB,aAAgB,CACpC,EAAI,sBAAsB,EAAU,KAAM,SAAU,CAChD,OAAQ,OAAO,YACf,MAAO,OAAO,WACjB,CAAC,EACJ,CAEF,GAA6B,EAAU,CACvC,IAAM,EAAqB,GAA+B,EAAa,EAAU,CACjF,GAA+B,EAAW,EAAmB,CAC7D,GAAmB,EAAW,EAAmB,CACjD,GAAe,EAAU,CACzB,GAAgB,EAAU,EAG9B,mBAAmB,CAAE,YAAW,aAAsB,EAAuB,CACzE,EAAW,CACP,WAAY,iBACZ,YACA,YACA,YAAa,EAChB,CAAC,EAGN,oBAAoB,CAAE,YAAW,aAAsB,EAAuB,CAC1E,EAAW,CACP,WAAY,kBACZ,YACA,YACA,YAAa,EAChB,CAAC,CACF,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,EAGhF,wBAAwB,CAAE,YAAW,aAAsB,EAAuB,CAC9E,EAAW,CACP,WAAY,YACZ,YACA,YACA,YAAa,EAChB,CAAC,CACE,GAAiC,EAAU,EAC3C,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,CAEhF,GAAsC,EAAU,EAGpD,eACI,CAAE,YAAW,aACb,CAAE,sBAAqB,QAAO,WAC1B,CACJ,EAAW,CACP,WAAY,aACZ,YACA,YACA,YAAa,EAChB,CAAC,CACE,GAAiC,EAAU,GACtC,GACD,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,CAEhF,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,EAGhF,GAAsB,EAAW,EAAsB,CAEnD,GACA,EAAa,EAAU,CAAC,UAAU,IAAI,cAAc,CAGxD,GAA+B,EAAW,CAAE,QAAO,CAAC,CACpD,GAAiB,EAAU,EAG/B,QAAQ,CAAE,aAAsB,CAAE,OAAM,QAAO,SAA+B,CAC1E,GAAS,wBAAyB,EAAU,CAC5C,GAAS,yBAAyB,IAAQ,EAAU,CAChD,IAAS,gBACT,EAAS,2BAA4B,EAAM,CAE3C,CAAC,IAAU,IAAS,gBAAkB,IAAS,iBAC/C,GAAoB,EAAW,EAAK,EAI5C,QAAQ,CAAE,aAA4B,CAClC,GAAiC,EAAW,EAAsB,IAAI,EAAU,kBAAkB,CAAC,EAE1G,EAGC,IAAY,EAAgB,IAA+B,CAC7D,IAAM,EAAI,EAAO,aAAa,CAC9B,EAAoB,EAAG,YAAY,KAAK,CAAC,CACzC,EACI,EACA,CACI,GAAI,EAAU,YACd,KAAM,EAAU,cACnB,CACD,YAAY,KAAK,CACpB,ECpIC,GAA2B,wBAEpB,IACT,EACA,EACA,IACO,QACP,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,GAAyB,CAAC,QAAS,GAA6C,CAC3F,GAAI,CACA,EAAoB,UAAU,EAAS,EAAU,EAAQ,OACpD,EAAO,CACZ,EAAS,gCAAgC,KAAK,UAAU,EAAM,GAAG,GAEvE,EAGO,GAAS,GAA+B,GAAc,EAAQ,CAE9D,OAAsB,IAAe,CAE5C,GAAiB,GAAgC,QACnD,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,GAAyB,CAAC,QAAS,GAA6C,CAC3F,EAAoB,MAAM,EAAQ,EACpC,EClCF,EAA8B,KAErB,IACT,EACA,EACA,IACC,CACD,IAAM,EAA0B,GAC5B,EAAU,sBAAsB,EAAU,KAAM,wBAAyB,EAAY,CAErF,GAAW,EAAU,SAAS,CAC9B,GAAU,EAAU,EAAU,CAAE,EAAwB,EAAK,CAEzD,IAAiB,EAAU,KAC3B,EAAuB,GAAK,CACrB,IAAiB,MAAQ,GAAqB,EAAU,EAAU,CAAC,EAC1E,EAAe,EAAU,KACzB,EAAuB,GAAK,EAE5B,EAAuB,GAAM,EAK5B,OAAoC,CAC7C,IAAS,CACT,EAAe,MAGN,GAAsC,GAAyB,CACxE,GAAM,EAAU,EAAU,CAAC,CAC3B,EAAe,EAAU,MAGvB,GAAc,IAAA,GAAA,KAAA,IAAA,GAA+B,EAAU,aAAa,IAAK,UAEzE,GAAwB,GACnB,CAAC,CAAC,GAAG,SAAS,qBAAqB,QAAQ,CAAC,CAAC,KAC/C,GAAU,CAAC,EAAM,QAAU,GAAoB,EAAS,EAAM,CAClE,CCjCQ,GAA6B,IAAuD,CAC7F,2BAA4B,CAAE,aAAsB,IAA4C,CAC5F,IAAM,EAAY,EAAa,EAAU,CACnC,EAAQ,IAAI,YACd,GACA,CACI,OAAQ,CAAE,iCAAkC,EAA2B,CAC1E,CACJ,CACD,EAAU,cAAc,EAAM,EAGlC,sBAAuB,CAAE,aAAsB,IAA+C,CAC1F,GAA4B,EAAW,GAAA,KAAW,EAAE,CAAb,EAAe,EAAI,EAG9D,yBAAkC,CAC9B,IAA6B,EAGjC,6BAA8B,CAAE,eAA+B,CAC3D,GAAmC,EAAU,EAEpD,EC/BY,GAAa,GAA+B,OACrD,IAAK,IAAM,MAAA,EAAS,GAAe,EAAa,GAAA,KAAA,IAAA,GAAA,EAAE,WAAY,EAAE,CAC5D,GAAI,GAAe,EAAM,CAAE,CACtB,EAAsB,OAAO,CAC9B,SAKC,GAAiB,GAA+B,CACzD,EAAoB,oCAAoC,CACxD,EAA6B,6CAA8C,EAAU,EAGnF,GAAkB,GACpB,SAAS,eAAe,EAAe,YAAY,CACjD,GAAkB,GACpB,EAAa,UAAY,KAAO,EAAa,UAAY,MCKhD,EAAgB,IACzB,GAAA,KAAA,IAAA,GAAO,EAAO,QAAS,GAAK,EAAM,OAAO,EAAM,OAAS,EAAE,GAAK,IAOtD,EAA+B,GACxC,EAAa,EAAM,CAAG,EAAQ,GAAG,SAAS,EAAM,CAAC,IC1BxC,IAAqB,EAAsB,IAAwB,CAC5E,EAAS,qCAAqC,CACzC,GAAsB,EAAU,EAErC,GAAgB,EAAW,EAAK,EAG9B,IAAmB,EAAsB,IAAiC,CAC5E,GAAI,CAAC,GAAc,EAAK,CAEpB,OADA,EAAS,WAAW,EAAK,MAAM,QAAQ,EAAK,OAAO,6BAA6B,EAAU,cAAc,GAAG,CACpG,GAGX,IAAM,EAAM,EAAa,EAAU,CAcnC,OAZI,GAAwB,EAAW,EAAK,GACxC,EAAI,MAAM,UAAY,EAA4B,EAAK,OAAO,EAG9D,EAAa,EAAK,OAAO,EAAI,EAAa,EAAK,MAAM,EACrD,EAAI,MAAM,MAAQ,EAA4B,EAAK,MAAM,CACzD,EAAI,MAAM,OAAS,EAA4B,EAAK,OAAO,GAE3D,EAAI,gBAAgB,QAAQ,CAC5B,EAAI,MAAM,YAAc,GAAG,SAAS,EAAK,MAAM,CAAC,KAAK,SAAS,EAAK,OAAO,IAGvE,IAGL,GAAiB,GAAiC,CACpD,IAAM,EAAS,EAA4B,EAAK,OAAO,CACjD,EAAQ,EAA4B,EAAK,MAAM,CAOrD,MALqB,CACjB,CAAE,MAAO,OAAQ,OAAQ,QAAS,CAClC,CAAE,MAAO,QAAS,OAAQ,QAAS,CACtC,CAEmB,KAAM,GAAgB,IAAW,EAAY,QAAU,IAAU,EAAY,MAAM,EAGrG,GAAyB,GAC3B,kBAAU,WAAa,uBAAA,EACtB,EAAU,qBAAA,KAAA,IAAA,GAAA,EAAoB,0BAA2B,qCACtD,GAAA,EAAC,EAAU,qBAAA,MAAA,EAAoB,0BACnC,EAAU,YAAc,KAEtB,IAA2B,EAAsB,IACnD,EAAU,WAAa,oBAAsB,EAAa,EAAK,MAAM,CC3C5D,GAAb,KAAqC,CACjC,YACI,EACA,EACF,CAFqB,KAAA,IAAA,EACZ,KAAA,GAAA,kBAGE,8BAEY,GACrB,GAAc,CACV,GAAI,EAAU,YACd,KAAM,EAAU,cACnB,CAAC,wBACe,GAAyB,oBAAU,EAAU,kBAAA,KAAmB,EAAU,kBAA7B,EAA+C,oBAElG,+BAOU,KAAO,IAAyB,CACrD,MAAM,EAA0B,EAAU,CAC1C,MAAM,GAAqB,EAAU,CAAC,KAAK,CACvC,GAAI,EAAU,YACd,KAAM,EAAU,cAChB,IAAK,EAAa,EAAU,CAC5B,WAAY,EAAU,WACzB,CAAC,qCAO0B,EAAsB,CAAE,eAA+B,CACnF,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,CAC5E,EAAkB,CAAE,YAAW,aAAc,KAAM,MAAO,KAAM,YAAW,CAAC,ICrCvE,GAAb,KAAiC,CAC7B,YAAY,EAAqD,YAA5C,KAAA,kBAAA,sBAMJ,MAAO,CAAE,UAA8C,CAOpE,GAAM,CAAE,UAAS,YAAW,WAAY,GAAA,KAAQ,EAAE,CAAV,EACnC,KAEL,GAAI,CACI,IAA2B,CAAC,GAAG,KAAK,CACpC,MAAM,GAAwB,CAC1B,cAAiB,CAAC,CAAC,SAAS,eAAe,EAAU,eAAe,CACpE,OAAQ,SAAY,MAAM,EAAK,QAAQ,EAAS,EAAW,EAAQ,CACtE,CAAC,CAEF,MAAM,EAAK,QAAQ,EAAS,EAAW,EAAQ,OAE9C,EAAI,CACT,EAAS,yBAAyB,EAAQ,KAAK,KAAK,UAAU,EAAQ,GAAI,EAAG,iBAIlE,EAA4B,EAAsB,IAA4C,CAC7G,IAAM,EAAkB,KAAK,kBAAkB,GAM/C,OALI,OAAO,GAAoB,YAC3B,GAAiB,EAAS,EAAU,CAC7B,QAAQ,QAAQ,EAAgB,EAAW,EAAQ,CAAC,EAGxD,QAAQ,SAAS,IAI1B,IAAoB,EAAiB,IAA+B,CACtE,IAAM,EAAS,aAAa,IAC5B,EAAoB,EAAO,CAC3B,EAA6B,EAAQ,CACjC,GAAI,EAAU,YACd,KAAM,EAAU,cACnB,CAAC,EC3DO,GAAb,KAA+B,CAC3B,YAAY,EAA8B,CAAd,KAAA,MAAA,wBAEN,EAAc,EAA8B,IAAa,CAC3E,IAAM,EAAQ,KAAK,MAAM,GAAM,YACzB,EAA2B,CACpB,UACH,OACT,CACD,EAAM,YAAY,EAAI,8BAGD,EAAc,EAAgB,IAAc,CACjE,IAAM,EAAU,CACZ,IAAK,EACC,OACT,CACD,KAAK,gBAAgB,EAAM,gBAAiB,EAAQ,IChB/C,IAAU,EAAc,IAClB,OAAO,GAAQ,YAA9B,GAA0C,OAAO,UAAU,eAAe,KAAK,EAAK,EAAI,CCEtF,GAA8D,IAAI,IAFlC,CAAC,MAAO,MAAM,CAEsD,CAsCpG,IAAiB,EAAe,IAClC,EAAK,MAAM,IAAI,CAAC,QAAiB,EAAK,IAAS,GAAO,EAAK,EAAI,CAAG,EAAI,GAAO,IAAA,GAAY,EAAK,CAsBrF,GACT,EACA,EACA,IACO,CACP,EAAK,iBAAiB,UAAW,MAAO,CAAE,UAAmE,CACzG,IAAA,GAAA,KAAA,IAAA,GAAI,EAAM,aAAc,EACxB,GAAI,CACA,IAAM,EAAK,GAAc,EAAM,EAAK,OAAiB,CACrD,GAAI,OAAO,GAAO,WAAY,CAC1B,IAAM,EAAe,CAAE,GAAG,EAAK,QAAS,YAAa,EAAM,CACtD,GAAyB,IAAI,EAAU,EACxC,GAAe,CACX,WAAY,aAAa,EAAU,GAAG,EAAK,SAC3C,YAAa,EACb,UAAW,EAAI,UAClB,CAAC,CAEN,MAAO,EAAe,EAAK,GAAG,EAAK,KAAK,QAEvC,EAAG,CACR,EAAS,mBAAmB,EAAU,GAAG,EAAK,SAAU,EAAE,GAEhE,ECrEO,GAAb,KAAsD,CAClD,YACI,EACA,EACA,EACA,EACA,EACA,EACF,YANW,KAAA,GAAA,EACA,KAAA,IAAA,EACQ,KAAA,WAAA,EACA,KAAA,QAAA,EACA,KAAA,QAAA,EACA,KAAA,UAAA,2BAGc,IAAI,0BAQX,EAAsB,IAAwC,CACtF,GAAI,CACA,KAAK,GAAG,MAAM,EAAU,MAAQ,CAC5B,YAAa,EAChB,OACI,EAAI,CACT,EAAS,4BAA4B,EAAU,WAAY,EAAG,0BAQzC,MACzB,EACA,EACA,IACgB,CAChB,MAAM,EAAK,oBAAoB,EAAuB,EAAU,2BAGrC,MAC3B,EACA,EACA,IACgB,CAChB,EAAK,EAAc,yBAA0B,EAAU,CAEvD,EAAK,gBAAgB,EAAW,EAAsB,CAEtD,GAAI,CACA,EAAa,EAAuB,SAAU,EAAK,WAAW,CAC9D,EAAa,EAAuB,MAAO,EAAK,QAAQ,CACxD,EAAa,EAAuB,MAAO,EAAK,QAAQ,CACxD,EAAa,EAAuB,QAAS,EAAK,UAAU,CAC5D,GAAsB,EAAK,GAAI,EAAW,EAAK,IAAI,OAC9C,EAAG,CAER,MADA,GAAkB,CAAE,YAAW,KAAM,aAAc,CAAC,CAC9C,MAUL,IAAyB,EAAiB,EAAsB,IAAmC,CAC5G,EAAG,MAAM,EAAU,MAAM,YAAY,UAAY,EAAI,gBC5F5C,GAAb,KAAyB,CACrB,YAAY,EAA+B,EAAE,CAAE,CAAnB,KAAA,MAAA,ICQnB,OAAoD,CAC7D,IAAM,EAAK,IAAI,GACT,EAAM,IAAI,GAAkB,EAAG,MAAM,CAE3C,OAAO,IAAI,GACP,EAFQ,IAAI,GAAoB,IAAI,GAAwB,EAAK,EAAG,CAAC,CAIrE,GAA2B,EAAI,CAC/B,GAAyB,CACzB,GAAyB,CACzB,GAA0B,EAAI,CACjC,ECZQ,OAAuC,CAChD,EAAK,EAAc,2BAA2B,CAC1C,QAAO,SAEX,EAAK,EAAc,gCAAgC,CACnD,OAAO,OAAS,IAA2B,GCV/C,MAA0B,IAA0B,CAAE,EAAU,+BAA+B,EAAE"}