{"version":3,"file":"ApeDLA-1.50.garynt0o.js","names":[],"sources":["../../../../src/js/components/perf.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/core.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/metrics.ts","../../../../src/js/components/state/page/pageState.ts","../../../../src/js/components/weblabs.ts","../../../../src/js/components/metrics/csaMetrics.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/logging.ts","../../../../src/js/components/metrics/emitErrorLog.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csa/latency.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/csm/latency.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/instrumentation/latency.ts","../../../../src/js/host/components/placement.ts","../../../../src/js/components/collapsePlacement.ts","../../../../../../../node_modules/throttle-debounce/esm/index.js","../../../../src/js/components/viewability.ts","../../../../src/js/components/executeWithDelay.ts","../../../../src/js/components/callbackRegistry.ts","../../../../src/js/light-ad/outbound/lightAdRepo.ts","../../../../src/js/light-ad/domain/service/lightAdService.ts","../../../../src/js/components/feedback.ts","../../../../src/js/light-ad/inbound/feedbackApi.ts","../../../../src/js/light-ad/domain/model/placement.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/domObstructions/getDOMObstructionPercentage.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/nativeObstructionsUtils.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/getObstructions.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/obstructionsEventListeners.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/nativeObstructions/getNativeObstructionPercentage.ts","../../../../../../../node_modules/@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.ts","../../../../src/js/components/intersectionObserver.ts","../../../../src/js/components/pixels/mrcObstructionViewPixel.ts","../../../../src/js/components/pixels/pixelIdentifiers.ts","../../../../src/js/components/state/placement/placementState.ts","../../../../src/js/components/state/placement/pixelState.ts","../../../../src/js/components/pixels/pixel.ts","../../../../src/js/components/pixels/viewPixelUtil.ts","../../../../src/js/components/pixels/services/viewabilityServiceImpl.ts","../../../../src/js/components/pixels/services/visibilityChangeService.ts","../../../../src/js/components/skadnetwork/skanAppAdsAttribution.ts","../../../../src/js/components/pixels/skanImpressionPixel.ts","../../../../src/js/components/pixels/skanViewPixel.ts","../../../../src/js/components/aax/aax.ts","../../../../src/js/components/urlQueryParams/addJSONQueryParamToURL.ts","../../../../src/js/components/util.ts","../../../../src/js/components/pixels/urlGenerators/btrPixelUrlGenerator.ts","../../../../src/js/components/pixels/urlGenerators/impressionPixelUrlGenerator.ts","../../../../src/js/components/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/executeWhenConditionMet.ts","../../../../src/js/light-ad/domain/helpers/getVideo.ts","../../../../src/js/components/pixels/services/videoFirePixelValidator.ts","../../../../../../../node_modules/@amzn/creative-rendering-monitor/src/btr.ts","../../../../../../../node_modules/@amzn/creative-rendering-monitor/src/creativeBTREvaluatorSync.ts","../../../../src/js/components/beginToRender.ts","../../../../src/js/components/viewRateExperimentUtil.ts","../../../../../../../node_modules/@amzn/grandprix-runtime/src/click-tracking.ts","../../../../src/js/components/clickTracking/replace.ts","../../../../src/js/light-ad/domain/service/click-tracking-service.ts","../../../../src/js/light-ad/domain/model/displayCreative.ts","../../../../src/js/components/homepage/homepageHerotator.ts","../../../../src/js/light-ad/domain/service/h1HerotatorService.ts","../../../../src/js/light-ad/domain/service/videoControlsVisibilityService.ts","../../../../src/js/light-ad/domain/service/videoLoadMetricsService.ts","../../../../src/js/components/homepage/homepageVideoOrchestrator.ts","../../../../src/js/light-ad/domain/service/videoOrchestratorService.ts","../../../../src/js/light-ad/domain/service/wd1AutoRotatorService.ts","../../../../src/js/light-ad/helpers/navigate.ts","../../../../src/js/light-ad/domain/model/videoCreative.ts","../../../../src/js/light-ad/inbound/mapper/creativeMapper.ts","../../../../src/js/light-ad/inbound/mapper/placementMapper.ts","../../../../src/js/light-ad/inbound/mapper/lightAdMapper.ts","../../../../src/js/light-ad/inbound/videoApi.ts","../../../../src/js/light-ad/inbound/lightAdApi.ts","../../../../src/js/light-ad/initLightAd.ts","../../../../src/js/light-ad/ApeDLA.ts"],"sourcesContent":["import type { AdDetails } from '@amzn/safeframe-model';\n\nexport const PERF_SF_HOST = 'perf:sf:host';\nexport const PERF_SF_CLIENT = 'perf:sf:client';\nexport const PERF_SF_GRANDPRIX = 'perf:sf:grandprix';\nexport const PERF_SF_SETUP = 'perf:sf:setup';\nexport const PERF_LA = 'perf:la';\n\n/** The only ad-identity field perf marks read. Any AdDetails-like shape (full, wire-slim, light-ad) satisfies it. */\ntype MarkAdDetails = Pick<AdDetails, 'placementName'>;\n\nexport const getMarkName = (scope: string, message: string, adDetails?: MarkAdDetails): string =>\n    `${scope}${adDetails ? `:${adDetails.placementName}` : ''} - ${message}`;\n\nexport const mark = (scope: string, message: string, adDetails?: MarkAdDetails): string => {\n    const markString = getMarkName(scope, message, adDetails);\n\n    performance?.mark?.(markString);\n\n    return markString;\n};\n\nexport interface LatencyTracker {\n    readonly startTime: number;\n    elapsed: () => number;\n}\n\nexport const createLatencyTracker = (): LatencyTracker => {\n    const startTime = performance.now();\n    return { startTime, elapsed: () => performance.now() - startTime };\n};\n","export const METRICS_SOURCE_GROUP = 'com.amazon.apm.stores.csa.metrics.prod';\nexport const LOGS_SOURCE_GROUP = 'com.amazon.apm.stores.csa.logs.prod';\nexport const NEXUS_SCHEMA_ID = 'com.amazon.apm.stores.ClientMetric.2';\nexport const NEXUS_PRODUCER_ID = 'apm-stores';\n\ntype LogCsaEventInput = {\n    sushiSourceGroup?: string;\n    producerId?: string;\n    data: Record<string, unknown>;\n};\n\n/**\n * Low-level transport: sends a single event to the CSA Events plugin.\n * Routes to either a Sushi source group or a Nexus producer depending on which\n * option is provided. Callers should use {@link emitCsaMetric} or {@link emitCsaLog} instead.\n *\n * @param sushiSourceGroup - Sushi source group to route the event to.\n * @param producerId - Nexus producer ID for the Nexus/Spektr emit path.\n * @param data - Arbitrary event payload.\n */\nexport const logCsaEvent = ({ sushiSourceGroup, producerId, data }: LogCsaEventInput): void =>\n    window.csa?.('Events', {\n        ...(producerId && { producerId }),\n        ...(sushiSourceGroup && { sushiSourceGroup }),\n    })?.('log', data, { ent: 'all' });\n","import { logCsaEvent, METRICS_SOURCE_GROUP, NEXUS_PRODUCER_ID, NEXUS_SCHEMA_ID } from './core.js';\n\nexport type CsaMetricInput = {\n    metricName: string;\n    metricValue: number;\n    timestamp?: Date;\n    dimensions: Record<string, string>;\n    weblabs?: Record<string, string>;\n};\n\n/**\n * Emits a CSA metric event to the metrics source group, which also routes to\n * the default CSA source group (Nexus → Spektr) for downstream analytics.\n *\n * Dual-emits: once to Sushi (full-precision metricValue, epoch ms timestamp) and once to\n * Nexus (rounded metricValue as int per the ClientMetric schema, ISO 8601 timestamp).\n *\n * @param metricName - Name of the metric to emit.\n * @param metricValue - Numeric value of the metric.\n * @param timestamp - When the metric was recorded. Defaults to now.\n * @param dimensions - Key-value pairs for metric dimensions.\n * @param weblabs - Active weblab treatments. Only included when provided.\n */\nexport const emitCsaMetric = ({\n    metricName,\n    metricValue,\n    timestamp = new Date(),\n    dimensions,\n    weblabs,\n}: CsaMetricInput): void => {\n    const base = { metricName, metricValue, dimensions };\n    logCsaEvent({\n        sushiSourceGroup: METRICS_SOURCE_GROUP,\n        data: { ...base, timestamp: timestamp.getTime(), ...(weblabs && { weblabs }) },\n    });\n    logCsaEvent({\n        producerId: NEXUS_PRODUCER_ID,\n        data: {\n            ...base,\n            metricValue: Math.round(metricValue),\n            timestamp: timestamp.toISOString(),\n            schemaId: NEXUS_SCHEMA_ID,\n        },\n    });\n};\n","type PageState = Record<string, Set<string>>;\n\ndeclare global {\n    interface Window {\n        AD_PLACEMENT: PageState;\n    }\n}\n\nconst getPageState = (): PageState => (window.AD_PLACEMENT ??= {});\n\nexport const getNamespace = (namespace: string): Set<string> => (getPageState()[namespace] ??= new Set());\n\nexport const createPageSet = (namespace: string) => {\n    const set = () => getNamespace(namespace);\n    return {\n        has: (key: string): boolean => set().has(key),\n        mark: (key: string): void => {\n            set().add(key);\n        },\n    };\n};\n\nexport const collapsedPlacements = createPageSet('collapsedPlacements');\nexport const emittedMetrics = createPageSet('loggedMetricNames');\nexport const feedbackState = createPageSet('feedback');\n","declare global {\n    // oxlint-disable-next-line\n    interface Window extends WeblabsWindow {}\n}\n\nexport type WeblabTreatment = `t${number}`;\n\nexport type AllWeblabTreatment = WeblabTreatment | 'c';\n\nexport interface WeblabsWindow {\n    renderingWeblabs?: { [key: string]: string };\n}\n\nexport interface Weblab {\n    is(treatment: WeblabTreatment): boolean;\n    isAssigned(): boolean;\n    isInTreatment(): boolean;\n    getTreatment(): AllWeblabTreatment;\n}\n\nexport const createWeblab = (weblabsWindow: WeblabsWindow, prefix: string): Weblab => {\n    const weblabTreatment = (): AllWeblabTreatment | undefined =>\n        weblabsWindow?.renderingWeblabs?.[prefix]?.toLowerCase() as AllWeblabTreatment;\n\n    return {\n        is(treatment: WeblabTreatment): boolean {\n            return weblabTreatment() === treatment;\n        },\n        isAssigned(): boolean {\n            return weblabTreatment() !== undefined;\n        },\n        isInTreatment(): boolean {\n            return !!weblabTreatment() && weblabTreatment() !== 'c';\n        },\n        getTreatment(): AllWeblabTreatment {\n            return weblabTreatment() ?? 'c';\n        },\n    };\n};\n\n/*\n * Used for gating IN art event styling\n * @link https://weblab.amazon.com/wl/ADPT_SF_HOMEPAGE_ART_THEMING_1298909\n */\nexport const ADPT_SF_HOMEPAGE_ART_THEMING = () => createWeblab(window, 'ADPT_SF_HOMEPAGE_ART_THEMING_1298909');\n\n/**\n * Used to enable new retail tracking with the JRS test painter.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_CLICK_TRACKING_PAINTER_TEST_1259727\n */\nexport const CLICK_TRACKING_PAINTER_TEST = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_CLICK_TRACKING_PAINTER_TEST_1259727');\n\n/**\n * Used to enable viewability-based impression pixel firing for CA, JP, and UK marketplaces.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_1289633\n */\nexport const VIEW_RATE_EXPERIMENT = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_1289633');\n\n/**\n * Used to control timeout for placement viewability of Stores View Rate experiment in ES and FR marketplaces.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_TIMEOUT_1373183\n */\nexport const VIEW_RATE_EXPERIMENT_TIMEOUT = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_TIMEOUT_1373183');\n\n/**\n * Used to disable user agent access for creatives\n * @link https://shepherd.a2z.com/issues/e4e8cd86-419a-4e1a-96ff-b20a6615b8b5\n */\nexport const DISABLE_USER_AGENT_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_USER_AGENT_1326744');\n\n/**\n * Used to enable new viewability tracker implementation\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_NEW_VIEWABILITY_TRACKER_1354300\n */\nexport const NEW_VIEWABILITY_TRACKER_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_NEW_VIEWABILITY_TRACKER_1354300');\n\n/**\n * Used to enable LightFrames on all eligible placement\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_ADS_EVERYWHERE_1362485\n */\nexport const LIGHT_ADS_EVERYWHERE_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_ADS_EVERYWHERE_1362485');\n\n/**\n * Used to disable window.top\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_POSTMESSAGE_1327371\n */\nexport const DISABLE_POSTMESSAGE_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_POSTMESSAGE_1327371');\n\n/**\n * Compares per-placement Light Ad assets with page-level loading at window load and at the first Light Ad placement.\n * @link https://app.weblab.amazon.dev/setup/APM_STORES_PAGE_LEVEL_LIGHT_AD_JS_1418728\n */\nexport const PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME = 'APM_STORES_PAGE_LEVEL_LIGHT_AD_JS_1418728';\nexport const PAGE_LEVEL_LIGHT_AD_JS_WEBLAB = () => createWeblab(window, PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME);\n","import { emitCsaMetric } from '@amzn/grandprix-runtime/src/instrumentation/csa/metrics.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emittedMetrics } from '@/components/state/page/pageState.js';\nimport { PAGE_LEVEL_LIGHT_AD_JS_WEBLAB, PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME } from '@/components/weblabs.js';\n\ntype LifecycleMetricName = 'event:start' | 'event:prewrite' | 'event:postwrite' | 'event:btr' | 'event:load';\ntype CoordinateMetricName = 'coordinate:x' | 'coordinate:y';\nexport type PixelMetricName =\n    | 'pixel:imp:cod'\n    | 'pixel:imp:cod:detail-btf-video'\n    | 'pixel:imp:btr'\n    | 'pixel:imp:btr:unknown'\n    | 'pixel:imp:btr:missing'\n    | 'pixel:imp:atf'\n    | 'pixel:view:iab'\n    | 'pixel:imp:skan'\n    | 'pixel:view:skan';\nexport type PixelErrorMetricName = `${PixelMetricName}:error`;\nexport type LightAdTimingMetricName = 'lightad:init:timing' | `${PixelMetricName}:timing`;\ntype MobileApiMetricName =\n    | 'sf:mobileapi:getPlacementInfo'\n    | 'sf:mobileapi:getUserAgentInfo'\n    | 'sf:mobileapi:getDocumentCookie'\n    | 'sf:mobileapi:getUserConnectionInfo';\n\ntype MashHandlerMetricName =\n    | 'sf:mash:openInApp3pBrowser'\n    | 'sf:mash:openInApp3pBrowser:success'\n    | 'sf:mash:openInApp3pBrowser:fail'\n    | 'sf:mash:openInExternalBrowser'\n    | 'sf:mash:showEmbeddedBrowser'\n    | 'sf:mash:isAUIAvailable';\nexport type CollapseMetricCode = 'creative' | 'client-setup' | 'host-setup' | 'client-error';\ntype CollapseMetricName = `placement:collapse:${CollapseMetricCode}` | 'placement:collapse';\n/**\n * Metric names emitted automatically by `bindReceiver` for every bridge call.\n * Csm and Csa are excluded since they are metric/logging channels themselves.\n *\n * If you add a method to a bridge interface, you MUST add the corresponding\n * metric name here — the test in bridgeMetricNames.test.ts will fail otherwise.\n */\nexport const BRIDGE_METRIC_NAMES = [\n    'sf:bridge:Video:updatePlayingTimeForVideo',\n    'sf:bridge:Video:requestVideoAutoplay',\n    'sf:bridge:Video:releaseVideoAutoplay',\n    'sf:bridge:Video:haveVideoAutoplayPermission',\n    'sf:bridge:Events:onSafeFrameReady',\n    'sf:bridge:Events:onPreCreativeWrite',\n    'sf:bridge:Events:onPostCreativeWrite',\n    'sf:bridge:Events:onCreativeBeginToRender',\n    'sf:bridge:Events:onCreativeLoad',\n    'sf:bridge:Events:onError',\n    'sf:bridge:Events:onClick',\n    'sf:bridge:SFClient:changeSize',\n    'sf:bridge:SFClient:collapseSlot',\n    'sf:bridge:SFClient:signalAdLoadedAndInteractive',\n    'sf:bridge:SFClient:feedbackLabelRendered',\n    'sf:bridge:SFClient:feedbackOpenModal',\n    'sf:bridge:SFClient:isOnAmazon',\n    'sf:bridge:CustomMessage:dispatch',\n    'sf:bridge:SafeFrameExt:populateSafeFrameExt',\n    'sf:bridge:SafeFrameExt:populateGeom',\n    'sf:bridge:Mash:openInApp3pBrowser',\n    'sf:bridge:Mash:openInApp3pBrowserReply',\n    'sf:bridge:MSFClient:onPageEvent',\n    'sf:bridge:MSFClient:onPageEventReply',\n    'sf:bridge:MSFClient:renderClickThroughAppAds',\n] as const;\nexport type BridgeMetricName = (typeof BRIDGE_METRIC_NAMES)[number];\n\n/** Client-local API metrics (not bridge calls, emitted directly by the client). */\ntype CustomMessageApiMetricName = 'sf:bridge:CustomMessage:registerCustomMessageListener';\n\ntype BlankAdMetricName = 'blank:ad:validation' | 'blank:ad:validation:error';\nexport type ObstructionMetricName = 'viewpixel:iab:obstruction' | 'viewpixel:iab:obstruction:recovered';\ntype DiagnosticMetricName =\n    | 'html:element:missing:placement'\n    | 'html:element:missing:iframe'\n    | 'asset:load:timing'\n    | 'intersection:observer:invalid:target'\n    | 'reporting-observer:heavy-ad-intervention'\n    | 'sf:useragent:access';\ntype ShepherdMetricName = 'shepherd:postmessage:parent';\ntype FeedbackMetricName = 'gpat:sponsored:label:rendered';\nexport type VideoMilestoneMetricName =\n    | 'lightad:video:canplay:duration'\n    | 'lightad:video:canplaythrough:duration'\n    | 'lightad:video:playing:duration';\ntype VideoMetricName =\n    | VideoMilestoneMetricName\n    | 'lightad:video:attach:duration'\n    | 'lightad:video:buffer:count'\n    | 'lightad:video:buffer:duration';\nexport type MetricName =\n    | LifecycleMetricName\n    | CoordinateMetricName\n    | PixelMetricName\n    | PixelErrorMetricName\n    | MobileApiMetricName\n    | MashHandlerMetricName\n    | CollapseMetricName\n    | BridgeMetricName\n    | CustomMessageApiMetricName\n    | BlankAdMetricName\n    | ObstructionMetricName\n    | DiagnosticMetricName\n    | ShepherdMetricName\n    | FeedbackMetricName\n    | VideoMetricName;\n\ninterface EmitPlacementMetricParams {\n    metricName: MetricName;\n    metricValue?: number;\n    adDetails: AdDetails | LightAdDetails;\n    timestamp?: Date;\n}\n\ninterface EmitMetricParams extends EmitPlacementMetricParams {\n    /** Low-cardinality dimensions to add without replacing canonical placement context. */\n    additionalDimensions?: Record<string, string>;\n    /** When set, emit at most once per metric and deduplication key on the page. */\n    deduplicationKey?: string;\n}\n\nexport const emitMetric = ({\n    metricName,\n    metricValue = 1,\n    adDetails: { logCxt },\n    timestamp,\n    additionalDimensions,\n    deduplicationKey,\n}: EmitMetricParams): void => {\n    if (deduplicationKey !== undefined) {\n        const key = `${metricName}:${deduplicationKey}`;\n        if (emittedMetrics.has(key)) return;\n        emittedMetrics.mark(key);\n    }\n\n    emitCsaMetric({\n        metricName,\n        metricValue,\n        timestamp,\n        dimensions: { ...additionalDimensions, ...logCxt },\n    });\n};\n\nexport const emitMetricOnce = (params: EmitPlacementMetricParams): void => {\n    if (emittedMetrics.has(params.metricName)) return;\n    emittedMetrics.mark(params.metricName);\n    emitMetric(params);\n};\n\nconst WEBLAB_METRIC_NAME = 'session:weblabs';\n\nconst emitWeblabMetricOnce = (adDetails: AdDetails | LightAdDetails): void => {\n    if (emittedMetrics.has(WEBLAB_METRIC_NAME)) return;\n    emittedMetrics.mark(WEBLAB_METRIC_NAME);\n\n    emitCsaMetric({\n        metricName: WEBLAB_METRIC_NAME,\n        metricValue: 1,\n        dimensions: { requestId: adDetails.logCxt.requestId },\n        weblabs: window.renderingWeblabs ?? {},\n    });\n};\n\nexport const emitWeblabMetric = (adDetails: AdDetails | LightAdDetails): void => {\n    emitWeblabMetricOnce(adDetails);\n};\n\ninterface EmitLightAdTimingMetricParams {\n    metricName: LightAdTimingMetricName;\n    metricValue: number;\n    adDetails: AdDetails | LightAdDetails;\n}\n\n/**\n * Emits milliseconds since time origin for Light Ad events.\n *\n * The metric is emitted only for page-level asset Weblab traffic, with its treatment attached to\n * the same event for direct Athena segmentation without a session-event join.\n */\nexport const emitLightAdTimingMetric = ({\n    metricName,\n    metricValue,\n    adDetails: { logCxt },\n}: EmitLightAdTimingMetricParams): void => {\n    const pageLevelWeblab = PAGE_LEVEL_LIGHT_AD_JS_WEBLAB();\n    if (logCxt.app !== 'LA' || !pageLevelWeblab.isAssigned()) return;\n\n    emitCsaMetric({\n        metricName,\n        metricValue,\n        dimensions: { ...logCxt },\n        weblabs: {\n            [PAGE_LEVEL_LIGHT_AD_JS_WEBLAB_NAME]: pageLevelWeblab.getTreatment().toUpperCase(),\n        },\n    });\n};\n","import { logCsaEvent, LOGS_SOURCE_GROUP } from './core.js';\n\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info';\n\nexport type CsaLogInput = {\n    level: LogLevel;\n    message: string;\n    errorType?: string;\n    stack?: string;\n    code?: string;\n    source?: string;\n    lineno?: number;\n    colno?: number;\n    timestamp?: Date;\n    dimensions: Record<string, string>;\n};\n\n/**\n * Emits a structured log event to the CSA logs source group (our logs pipeline →\n * CloudWatch Logs, searched via Logs Insights). Not routed to Nexus.\n *\n * The event also carries metric fields (`metricName: log:level:${level}`, `metricValue: 1`)\n * so this single emission can be sliced and counted as a metric downstream by the CSA metrics\n * Lambda (for error/fatal alarming) without the client emitting twice — Sushi fans the logs\n * source group out to both the logs and metrics sinks.\n *\n * @param level - Severity: fatal | error | warn | info. Also forms the metricName.\n * @param message - Log message.\n * @param errorType - Error class name, when derived from an Error.\n * @param stack - Error stack, when available.\n * @param code - Error code, when available.\n * @param source - Source file or module where the error originated.\n * @param lineno - Line number where the error occurred.\n * @param colno - Column number where the error occurred.\n * @param timestamp - When the log was recorded. Defaults to now.\n * @param dimensions - Key-value log dimensions; also the metric dimensions for slicing.\n */\nexport const emitCsaLog = ({\n    level,\n    message,\n    errorType,\n    stack,\n    code,\n    source,\n    lineno,\n    colno,\n    timestamp = new Date(),\n    dimensions,\n}: CsaLogInput): void =>\n    logCsaEvent({\n        sushiSourceGroup: LOGS_SOURCE_GROUP,\n        data: {\n            metricName: `log:level:${level}`,\n            metricValue: 1,\n            level,\n            errorType,\n            message,\n            stack,\n            code,\n            source,\n            lineno,\n            colno,\n            timestamp: timestamp.getTime(),\n            dimensions,\n        },\n    });\n","import { emitCsaLog } from '@amzn/grandprix-runtime/src/instrumentation/csa/logging.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\n// At least one of `message` or `error` must be provided.\ntype LogWithMessage = { message: string; error?: unknown };\ntype LogWithError = { message?: string; error: unknown };\ntype EmitErrorLogParams = {\n    adDetails: AdDetails | LightAdDetails;\n    code?: string;\n    source?: string;\n    lineno?: number;\n    colno?: number;\n} & (LogWithMessage | LogWithError);\n\n/**\n * Emits a structured client error log to the CSA logs source group (→ our logs pipeline →\n * CloudWatch Logs, searched via Logs Insights) for search and triage. The level is always\n * `error`. When an Error is provided, errorType/message/stack are derived from it.\n *\n * Only the log is emitted here — the client sends each event exactly once. Counts for alarming\n * (error/fatal volume) are derived downstream from the logs, not emitted by the client.\n *\n * @param input.message - Log message. Optional only when an Error is provided.\n * @param input.error - The caught value; normalized to an Error, from which errorType/message/stack\n *                      are derived. Accepts a non-Error throw so callers can pass what they caught.\n * @param input.adDetails - Ad context; logCxt becomes the log dimensions.\n * @param input.code - Error phase: 'client-setup' (during creative init) or 'client-error' (runtime).\n * @param input.source - Script URL or filename where the error occurred (from window.onerror).\n * @param input.lineno - Line number where the error occurred (from window.onerror).\n * @param input.colno - Column number where the error occurred (from window.onerror).\n */\nexport const emitErrorLog = ({ message, error, adDetails, code, source, lineno, colno }: EmitErrorLogParams): void => {\n    const err = toError(error);\n    emitCsaLog({\n        level: 'error',\n        errorType: err?.name,\n        message: message ?? err?.message ?? '',\n        stack: err?.stack,\n        code,\n        source,\n        lineno,\n        colno,\n        dimensions: { ...adDetails.logCxt },\n    });\n};\n\n/**\n * Normalizes a caught value into an Error. `undefined` stays `undefined`, so a message-only log emits\n * no errorType or stack. A non-Error object is JSON-serialized into the message so its properties\n * (e.g. a MashError's `code`) are not lost to `String()`'s \"[object Object]\"; anything else, and any\n * object JSON cannot serialize (circular refs), falls back to `String()`.\n */\nconst toError = (error: unknown): Error | undefined => {\n    if (error === undefined) return undefined;\n    if (error instanceof Error) return error;\n    if (typeof error === 'object') {\n        try {\n            return new Error(JSON.stringify(error));\n        } catch {\n            // Circular refs; fall through to String().\n        }\n    }\n    return new Error(String(error));\n};\n","import type { CsaLatencyMarker } from './window.js';\n\n/**\n * Records a CSA Content Latency marker for a placement element.\n * Timestamps are epoch-based (`Date.now()`), not `performance.now()`.\n * No-ops if CSA is unavailable.\n *\n * @param element - The placement DOM element to record latency for.\n * @param marker - The well-known latency marker name to record.\n * @param timestamp - Optional absolute timestamp. Defaults to now if omitted.\n *\n * @see {@link https://w.amazon.com/bin/view/ClientSideMetrics/UserDocs/CSA/Plugins/ContentInstrumentation/ContentLatency/}\n */\nexport const sendCsaLatencyMetric = (element: HTMLElement, marker: CsaLatencyMarker, timestamp?: Date): void => {\n    window.csa?.('Content', { element })('mark', marker, timestamp?.getTime());\n};\n","type UetLatencyEvent = 'bb' | 'be' | 'af' | 'cf';\ntype UexLatencyEvent = 'ld';\n\n/**\n * CSM widget latency marker events.\n *\n * Markers are recorded via `uet()` (timing) or `uex()` (timing + send).\n * All markers require a scope name and `{wb: 1}` flag.\n * Timestamps are epoch-based (`Date.now()`), not `performance.now()`.\n *\n * @remarks\n * **Firing order:**\n *\n * There is no enforced ordering between `bb`, `be`, `af`, and `cf` —\n * they simply record timestamps. However, the conventional order\n * that aligns with their semantic meaning is:\n *\n *\n\n * bb → af → cf → be → ld\n * │    │    │    │    └─ Must be last. Triggers postback.\n * │    │    │    └────── Widget HTML finished rendering\n * │    │    └─────────── Critical/useful content ready\n * │    └──────────────── Visible portion rendered\n * └───────────────────── Widget starts rendering\n *\n\n *\n * Only `bb` and `ld` are needed for minimal instrumentation.\n * Use `af`, `cf`, `be` when you need finer-grained breakdown.\n *\n * **Hard rules:**\n * 1. `'ld'` must always be the last marker fired — it sends all\n *    collected timestamps to the server.\n * 2. Every scope that logs `'bb'` must also log `'ld'`, or metrics\n *    for **all** widgets on the page will be blocked.\n *\n * - `'bb'` — Body Begin: Fire when your widget starts rendering.\n * - `'af'` — Above The Fold: Fire when the visible portion of your widget has rendered.\n * - `'cf'` — Critical Feature: Fire when the main/useful content of your widget has rendered.\n * - `'be'` — Body End: Fire when your widget's HTML finishes rendering.\n * - `'ld'` — Loaded (required): Fire when your widget is fully loaded.\n *   Triggers the postback to send all widget metrics to the server.\n *\n * @see {@link https://w.amazon.com/bin/view/ClientSideMetrics/UserDocs/Instrumentation/InstrumentingWidgets}\n */\nexport type LatencyEvent = UetLatencyEvent | UexLatencyEvent;\n\ndeclare global {\n    // https://code.amazon.com/packages/ClickstreamBrowserDataJavaScript/blobs/mainline/--/javascript/head-open.js\n    interface Window {\n        /** Records a timing marker for a given scope. Timestamp is epoch-based (`Date.now()`). */\n        uet?(\n            eventName: UetLatencyEvent,\n            scope?: string,\n            scopeOptions?: Record<string, unknown>,\n            timeOverride?: number,\n        ): void;\n        /** Records a timing marker and sends the postback to the server. */\n        uex?(\n            eventName: UexLatencyEvent,\n            scope?: string,\n            scopeOptions?: Record<string, unknown>,\n            timeOverride?: number,\n        ): void;\n    }\n}\n\nexport interface Placement {\n    id: string;\n    name: string;\n}\n\n/** Parameters for emitting a CSM widget latency metric. */\nexport interface LatencyMetric {\n    /** The latency marker to record. */\n    latencyEvent: LatencyEvent;\n    /** Optional key to further qualify the metric scope (e.g. `'SafeFrame'` or `'LightAd'`). */\n    scope?: string;\n    /** The ad placement to emit metrics for. */\n    placement: Placement;\n    /** Absolute timestamp to record. Defaults to now. Must be epoch-compatible (`Date`). */\n    timestamp?: Date;\n}\n\nconst csmName = (name: string) => name.replace(/_/g, ':');\n\n/**\n * Emits a single CSM widget latency marker for a given scope.\n * Routes to `uet()` for timing markers or `uex()` for `'ld'` (which triggers the server postback).\n * No-ops if the required window function is unavailable.\n */\nconst emitLatency = (event: LatencyEvent, scope: string, time: number): void => {\n    if (event === 'ld') window.uex?.(event, scope, { wb: 1 }, time);\n    else window.uet?.(event, scope, { wb: 1 }, time);\n};\n\n/**\n * Emits CSM latency metrics for an ad placement, keyed by both placement ID and name.\n * Each call produces two scoped metrics to allow lookup by either identifier.\n * Uses a consistent timestamp across both scopes to ensure aligned measurements.\n *\n * Metrics are published to PMET under `scope:adplacements:<scope?>:<placement>:<metricName>`.\n *\n * @example\n * ```ts\n * sendCsmLatencyMetric({ latencyEvent: 'bb', placement, scope: 'SF' });\n * // ... ad renders ...\n * sendCsmLatencyMetric({ latencyEvent: 'ld', placement, scope: 'LA' });\n *\n */\nexport const sendCsmLatencyMetric = ({ latencyEvent, scope, placement, timestamp }: LatencyMetric): void => {\n    const prefix = `adplacements:${scope ? `${csmName(scope)}:` : ''}`;\n    const time = timestamp?.getTime() ?? Date.now();\n\n    emitLatency(latencyEvent, prefix + placement.id, time);\n    emitLatency(latencyEvent, prefix + csmName(placement.name), time);\n};\n","import type { AdDetails, App, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { sendCsaLatencyMetric } from './csa/latency.js';\nimport type { CsaLatencyMarker } from './csa/window.js';\nimport type { LatencyEvent, Placement } from './csm/latency.js';\nimport { sendCsmLatencyMetric } from './csm/latency.js';\n\nexport interface AdLatencyMetric {\n    adDetails: AdDetails | LightAdDetails;\n    latencyEvent: LatencyEvent;\n    scope: App;\n    timestamp?: Date;\n}\n\nconst csaEvents: Partial<Record<LatencyEvent, CsaLatencyMarker[]>> = {\n    bb: ['t0', 'bodyBegin'],\n    af: ['aboveTheFold'],\n    cf: ['criticalFeature', 'functional'],\n    ld: ['loaded', 'feat_vl100'],\n};\n\nexport const sendLatencyMetric = ({ adDetails, latencyEvent, scope, timestamp }: AdLatencyMetric): void => {\n    const element = document.getElementById(adDetails.adUnitPlacementId) as HTMLElement;\n    const placement: Placement = { id: adDetails.placementId, name: adDetails.placementName };\n\n    sendCsmLatencyMetric({ latencyEvent, placement, scope, timestamp });\n    csaEvents[latencyEvent]?.forEach((marker) => sendCsaLatencyMetric(element, marker, timestamp));\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\n\n/** Any ad identity accepted by these DOM utilities. */\ntype AnyAdDetails = AdDetails | LightAdDetails;\n\nexport type PlacementLookupSource =\n    | 'safe-frame-ready'\n    | 'pre-creative-write'\n    | 'creative-btr'\n    | 'creative-load'\n    | 'click'\n    | 'collapse'\n    | 'video'\n    | 'change-size'\n    | 'msf-page-event'\n    | 'light-ad';\n\ninterface PlacementLookupOptions {\n    lookupSource: PlacementLookupSource;\n    adUnitPlacementId?: string;\n}\n\nconst isSafeFrame = (adDetails: AnyAdDetails): adDetails is AdDetails => 'adUnitIframeId' in adDetails;\n\nconst getPageAgeBucket = (pageAgeMs: number): string => {\n    if (pageAgeMs < 1_000) return 'lt-1s';\n    if (pageAgeMs < 10_000) return '1s-10s';\n    if (pageAgeMs < 60_000) return '10s-1m';\n    if (pageAgeMs < 300_000) return '1m-5m';\n    return 'gte-5m';\n};\n\nexport const getWrapper = (adDetails: AnyAdDetails): HTMLElement | null => {\n    if (isSafeFrame(adDetails)) {\n        return adDetails.adUnitWrapperId ? document.getElementById(adDetails.adUnitWrapperId) : null;\n    }\n\n    return document.getElementById(adDetails.adUnitPlacementId)?.parentElement ?? null;\n};\n\nexport const getPlacement = (\n    adDetails: AnyAdDetails,\n    { lookupSource, adUnitPlacementId = adDetails.adUnitPlacementId }: PlacementLookupOptions,\n): HTMLDivElement => {\n    const placement = document.getElementById(adUnitPlacementId);\n\n    if (!placement) {\n        emitMetric({\n            metricName: 'html:element:missing:placement',\n            adDetails,\n            additionalDimensions: {\n                abpAcceptable: adDetails.abpAcceptable,\n                abpStatus: adDetails.abpStatus ?? '-1',\n                lookupSource,\n                pageAgeBucket: getPageAgeBucket(performance.now()),\n            },\n            deduplicationKey: adDetails.placementId,\n        });\n    }\n\n    return placement as HTMLDivElement;\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric, type CollapseMetricCode } from '@/components/metrics/csaMetrics.js';\nimport { collapsedPlacements } from '@/components/state/page/pageState.js';\nimport { getPlacement, getWrapper } from '@/host/components/placement.js';\n\ninterface CollapsePlacementParams {\n    adDetails: AdDetails | LightAdDetails;\n    code?: CollapseMetricCode;\n}\n\nconst hide = (element: HTMLElement | null): void => {\n    if (element) {\n        element.style.display = 'none';\n    }\n};\n\n/**\n * Hides a placement once per page. A placement can be asked to collapse from several directions, so\n * the first request wins and later ones are ignored rather than re-counted.\n */\nexport const collapsePlacement = ({ adDetails, code }: CollapsePlacementParams): void => {\n    if (collapsedPlacements.has(adDetails.adUnitPlacementId)) {\n        return;\n    }\n\n    hide(getWrapper(adDetails));\n    hide(getPlacement(adDetails, { lookupSource: 'collapse' }));\n\n    emitMetric({ metricName: 'placement:collapse', adDetails });\n    if (code) {\n        emitMetric({ metricName: `placement:collapse:${code}`, adDetails });\n    }\n\n    collapsedPlacements.mark(adDetails.adUnitPlacementId);\n};\n","/* 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","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 type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\nimport { throttle } from 'throttle-debounce';\n\nimport type {} from '@/components/amznJQ/index.d.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { findDistanceFromViewport } from '@/components/viewability.js';\n\n/*\n    Helper method to implement JIT execution\n    It will execute callback after `elem` is `offset` pixels below the viewport.\n*/\n/**\n *\n * @deprecated Replace this with delayUntil\n */\nconst executeJustInTime = (callback: () => void, offset: number, elem: HTMLElement) => {\n    let callbackExecuted = false;\n    const isReadyToExecute = () => {\n        const distance = findDistanceFromViewport(elem);\n        return distance && distance <= offset;\n    };\n\n    const positionTracker = () => {\n        if (isReadyToExecute()) {\n            callback();\n            callbackExecuted = true;\n        }\n    };\n\n    const throttledPositionTracker = throttle(20, () => {\n        positionTracker();\n\n        if (callbackExecuted) {\n            window.removeEventListener('scroll', throttledPositionTracker);\n            window.removeEventListener('resize', throttledPositionTracker);\n        }\n    });\n\n    positionTracker();\n    if (!callbackExecuted) {\n        window.addEventListener('scroll', throttledPositionTracker);\n        window.addEventListener('resize', throttledPositionTracker);\n    }\n};\n\nexport interface ExecuteAfterDelay {\n    callback: () => void;\n    errorCallback?: () => void;\n    adDetails: AdDetails | LightAdDetails;\n    delayConfig?: string;\n    placementDiv: HTMLDivElement;\n    siteName?: string;\n}\n\n/**\n * Execute a function after a particular event\n * Supported events: https://w.amazon.com/bin/view/Ad_Placements/SafeFrame/#Lazyload_logic\n */\nexport const executeWithDelay = ({\n    callback,\n    errorCallback,\n    adDetails,\n    delayConfig,\n    placementDiv,\n    siteName,\n}: ExecuteAfterDelay): void => {\n    const callbackToExecute = () => {\n        try {\n            callback();\n        } catch (ex) {\n            emitErrorLog({ message: 'delayLoad failed', error: ex, adDetails });\n            errorCallback?.();\n        }\n    };\n\n    if (delayConfig?.trim().match(/^\\d{1,4}px$/g)) {\n        /**\n         * JIT loading - execute the callback function when the user has scrolled to X pixels above the placement div.\n         * X will be an adjustable variable based on the regex above.\n         */\n        executeJustInTime(callbackToExecute, parseInt(delayConfig, 10), placementDiv);\n    } else if (delayConfig === 'inView' && siteName === 'amazon.in') {\n        // TODO: remove inView, after view based billing support: https://sim.amazon.com/issues/CPP-42945\n        // Execute callback when ad div enters viewport\n        const observer = new IntersectionObserver(\n            (entries) => {\n                // Use intersectionRatio > 0 to determine visibility\n                for (const entry of entries) {\n                    if (entry.intersectionRatio > 0) {\n                        callbackToExecute();\n                        observer.unobserve(placementDiv);\n                        break;\n                    }\n                }\n            },\n            { threshold: [0, 0.01] },\n        );\n        observer.observe(placementDiv);\n    } else {\n        // including loadAfter:'clickTracking' for placements with enableClickTracking=true\n        callbackToExecute();\n    }\n};\n","/**\n * Registry for managing callbacks that wait for keys to become ready.\n * Uses observer pattern to notify callbacks when keys are ready.\n */\nexport interface ReadyRegistry {\n    /**\n     * Register a callback to be executed when a key becomes ready.\n     *\n     * @param key - Unique identifier for the value\n     * @param callback - Function to execute when key is ready\n     */\n    onReady(key: string, callback: () => void): void;\n\n    /**\n     * Notify that a key is ready and execute all pending callbacks for that key.\n     *\n     * @param key - Unique identifier for the value\n     */\n    notifyReady(key: string): void;\n}\n\n/**\n * Creates a new ready registry instance.\n * Each instance maintains its own callback storage.\n */\nexport const createReadyRegistry = (): ReadyRegistry => {\n    const callbacks = new Map<string, (() => void)[]>();\n\n    return {\n        onReady: (key: string, callback: () => void): void => {\n            const existingCallbacks = callbacks.get(key) || [];\n            existingCallbacks.push(callback);\n            callbacks.set(key, existingCallbacks);\n        },\n\n        notifyReady: (key: string): void => {\n            const keyCallbacks = callbacks.get(key);\n            if (keyCallbacks) {\n                keyCallbacks.forEach((cb) => cb());\n                callbacks.delete(key);\n            }\n        },\n    };\n};\n\n/**\n * A one-shot registry for values parked while a call awaits its reply, keyed by a replyKey it mints.\n *\n * `take` removes the entry before returning it, which is what makes a duplicate or late reply a\n * no-op instead of running a creative's callback twice, and makes an unknown key indistinguishable\n * from an already-settled one. Both surface as `undefined`.\n */\nexport interface ReplyRegistry<T> {\n    park(value: T): string;\n    take(replyKey: string): T | undefined;\n}\n\n/**\n * Creates a new reply registry instance.\n * Each instance maintains its own storage and its own replyKey counter.\n */\nexport const createReplyRegistry = <T>(): ReplyRegistry<T> => {\n    const parked = new Map<string, T>();\n\n    /**\n     * Source of replyKeys. A key only has to tell this registry's pending calls apart, so a counter\n     * is enough: it never leaves the realm, is not a secret, and unlike crypto.randomUUID it needs no\n     * secure context and no minimum Safari version.\n     */\n    let callCount = 0;\n\n    return {\n        park: (value: T): string => {\n            const replyKey = String(++callCount);\n            parked.set(replyKey, value);\n            return replyKey;\n        },\n        take: (replyKey: string): T | undefined => {\n            const value = parked.get(replyKey);\n            parked.delete(replyKey);\n            return value;\n        },\n    };\n};\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { createReadyRegistry } from '@/components/callbackRegistry.js';\nimport type { Placement } from '@/light-ad/domain/model/placement.js';\n\ndeclare global {\n    // oxlint-disable-next-line\n    interface Window extends LightAdWindow {}\n}\n\nexport type LightAdEntity = {\n    lightAdDetails: LightAdDetails;\n    placement: Placement;\n    processedTimestamp?: number;\n};\n\nexport interface LightAdWindow {\n    lightAds: { [key: string]: LightAdEntity };\n}\n\nexport interface LightAdRepo {\n    get(placementDiv: HTMLElement): Promise<LightAdEntity>;\n    save(lightAdEntity: LightAdEntity): void;\n}\n\nconst ensureLightAds = (window: LightAdWindow): void => {\n    if (!window.lightAds) {\n        window.lightAds = {};\n    }\n};\n\nconst readyRegistry = createReadyRegistry();\nconst getEntityReadyKey = (placementDivId: string): string => `la-entity-ready-${placementDivId}`;\n\nexport const lightAdRepo = (lightAdWindow: LightAdWindow = window): LightAdRepo => {\n    ensureLightAds(lightAdWindow);\n\n    return {\n        get: (placementDiv: HTMLElement): Promise<LightAdEntity> => {\n            const entity = lightAdWindow.lightAds[placementDiv.id];\n            if (entity) return Promise.resolve(entity);\n\n            return new Promise((resolve) => {\n                readyRegistry.onReady(getEntityReadyKey(placementDiv.id), () => {\n                    resolve(lightAdWindow.lightAds[placementDiv.id]);\n                });\n            });\n        },\n\n        save: (lightAdEntity: LightAdEntity): void => {\n            const placementId = lightAdEntity.placement.div.id;\n            lightAdWindow.lightAds[placementId] = lightAdEntity;\n            readyRegistry.notifyReady(getEntityReadyKey(placementId));\n        },\n    };\n};\n","import { sendLatencyMetric } from '@amzn/grandprix-runtime/src/instrumentation/latency.js';\n\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport { executeWithDelay } from '@/components/executeWithDelay.js';\nimport { emitMetric, emitWeblabMetric } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { mark, PERF_LA } from '@/components/perf.js';\nimport type { LightAd } from '@/light-ad/domain/model/LightAd.js';\nimport { lightAdRepo } from '@/light-ad/outbound/lightAdRepo.js';\n\nexport const processLightAd = (lightAd: LightAd): void => {\n    markLightAdProcessed(lightAd);\n    mark(PERF_LA, 'markLightAdProcessed');\n    processLightAdHelper(lightAd);\n};\n\nconst processLightAdHelper = async ({ placement, lightAdDetails }: LightAd): Promise<void> => {\n    mark(PERF_LA, 'processLightAdHelper');\n    try {\n        sendLatencyMetric({ adDetails: lightAdDetails, latencyEvent: 'af', scope: 'LA' });\n        emitMetric({ metricName: 'event:start', adDetails: lightAdDetails });\n        emitWeblabMetric(lightAdDetails);\n\n        const renderPromise = placement.render();\n\n        executeWithDelay({\n            callback: async () => {\n                placement.firePreRenderImpression();\n                sendLatencyMetric({ adDetails: lightAdDetails, latencyEvent: 'cf', scope: 'LA' });\n                emitMetric({ metricName: 'event:btr', adDetails: lightAdDetails });\n                await renderPromise;\n                mark(PERF_LA, 'renderComplete');\n                sendLatencyMetric({ adDetails: lightAdDetails, latencyEvent: 'ld', scope: 'LA' });\n                emitMetric({ metricName: 'event:load', adDetails: lightAdDetails });\n                placement.track();\n            },\n            adDetails: lightAdDetails,\n            delayConfig: lightAdDetails.firePixelsAfter,\n            placementDiv: placement.div,\n            siteName: lightAdDetails.siteName,\n        });\n    } catch (error) {\n        collapsePlacement({ adDetails: lightAdDetails });\n        emitErrorLog({ message: 'Unable to process Light Ad', error, adDetails: lightAdDetails });\n    }\n};\n\nconst markLightAdProcessed = ({ placement, lightAdDetails }: LightAd): void => {\n    lightAdRepo().save({\n        processedTimestamp: performance.now(),\n        placement: placement,\n        lightAdDetails: lightAdDetails,\n    });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { feedbackState } from '@/components/state/page/pageState.js';\n\nexport const openModal = (parentHtmlId: string): void => {\n    for (const child of getFeedbackDiv(parentHtmlId)?.children || []) {\n        if (isFeedbackLink(child)) {\n            (child as HTMLElement).click();\n            return;\n        }\n    }\n};\n\nexport const labelRendered = (adDetails: AdDetails | LightAdDetails): void => {\n    if (feedbackState.has(adDetails.adUnitPlacementId)) return;\n    feedbackState.mark(adDetails.adUnitPlacementId);\n    emitMetric({ metricName: 'gpat:sponsored:label:rendered', adDetails });\n};\n\nconst getFeedbackDiv = (parentHtmlId: string): HTMLElement | null =>\n    document.getElementById(parentHtmlId + '_Feedback');\nconst isFeedbackLink = (childElement: Element): boolean =>\n    childElement.tagName === 'A' || childElement.tagName === 'DIV';\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { labelRendered, openModal } from '@/components/feedback.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { lightAdRepo } from '@/light-ad/outbound/lightAdRepo.js';\n\nexport interface FeedbackApi {\n    /**\n     * Notifies that the feedback label has been rendered.\n     * You must call this method after inserting your own SL into the DOM.\n     * @param elementId - ID of the placement div or any child element within it\n     * @param element - Optional element within the placement div, such as the label itself. When passed, it identifies\n     * the placement and `elementId` is only used for logging.\n     */\n    labelRendered(elementId: string, element?: Element): Promise<void>;\n\n    /**\n     * Opens the ad feedback modal.\n     * @param elementId - ID of the placement div or any child element within it\n     * @param element - Optional element within the placement div, such as the clicked label. When passed, it\n     * identifies the placement and `elementId` is only used for logging.\n     */\n    openModal(elementId: string, element?: Element): Promise<void>;\n}\n\nexport class FeedbackApiImpl implements FeedbackApi {\n    async labelRendered(elementId: string, element?: Element): Promise<void> {\n        const placementDiv = getPlacementDiv(elementId, element, pickNextUnclaimedPlacementDiv);\n        claimedPlacementDivs.add(placementDiv);\n        const lightAdDetails = await getAdDetails(placementDiv);\n        try {\n            labelRendered(lightAdDetails);\n        } catch (err) {\n            emitErrorLog({\n                message: `Light ad - labelRendered failed for '${sanitizeForLog(elementId)}'`,\n                error: err,\n                adDetails: lightAdDetails,\n            });\n        }\n    }\n\n    async openModal(elementId: string, element?: Element): Promise<void> {\n        // Resolved before awaiting: which render was clicked is only known while the click is dispatching.\n        const placementDiv = getPlacementDiv(elementId, element, pickClickedPlacementDiv);\n        const lightAdDetails = await getAdDetails(placementDiv);\n        try {\n            openModal(placementDiv.parentElement!.id);\n        } catch (err) {\n            emitErrorLog({\n                message: `Light ad - openModal failed for '${sanitizeForLog(elementId)}'`,\n                error: err,\n                adDetails: lightAdDetails,\n            });\n        }\n    }\n}\n\nconst getAdDetails = async (placementDiv: HTMLElement): Promise<LightAdDetails> => {\n    const entity = await lightAdRepo().get(placementDiv);\n    return entity.lightAdDetails;\n};\n\ntype PickLegacyMatch = (matches: HTMLElement[]) => HTMLElement | undefined;\n\nconst getPlacementDiv = (\n    elementId: string,\n    element: Element | undefined,\n    pickLegacyMatch: PickLegacyMatch,\n): HTMLElement => {\n    const found =\n        element ?? document.getElementById(elementId) ?? pickLegacyMatch(findPlacementDivsByLegacyId(elementId));\n\n    if (!found) {\n        throw new Error(`Element '${elementId}' doesn't exist`);\n    }\n\n    if (found.classList.contains('ape-placement')) {\n        return found as HTMLElement;\n    }\n\n    const placementDiv = found.closest('.ape-placement');\n\n    if (!placementDiv) {\n        throw new Error(`No placement div found for element '${elementId}'`);\n    }\n\n    return placementDiv as HTMLElement;\n};\n\n/**\n * Creatives that render their own Sponsored label build the placement id from the documented pattern\n * `ape_{placementName}_placement`. Unique rendering ids (APM_STORES_UNIQUE_RENDERING_ID_1470123) add the rendering id\n * to the div id, so that pattern names no element, but the wrapper still carries the placement name. A placement that\n * renders more than once matches once per render, in page order. SafeFrame renders share the wrapper markup but have\n * no Light Ad, so only Light Ad placements match.\n */\nconst findPlacementDivsByLegacyId = (elementId: string): HTMLElement[] =>\n    Array.from(\n        document.querySelectorAll<HTMLElement>('[data-placement-name] > .ape-placement[class~=\"text/x-APE-lightAds\"]'),\n    ).filter((placementDiv) => `ape_${placementDiv.parentElement!.dataset.placementName}_placement` === elementId);\n\nconst claimedPlacementDivs = new WeakSet<HTMLElement>();\n\n/**\n * Creatives report their label from a `load` listener registered as the page parses, so reports arrive in page order,\n * one per render. A report by legacy id takes the next unclaimed render, and every report claims its render however it\n * was identified. Claims are kept here, synchronously, because the label state is only marked once the Light Ad\n * resolves. Surplus reports fall back to the first render, where they dedupe.\n */\nconst pickNextUnclaimedPlacementDiv: PickLegacyMatch = (matches) =>\n    matches.find((match) => !claimedPlacementDivs.has(match)) ?? matches[0];\n\n/**\n * The label's click handler calls openModal while the click is dispatching, so prefer the render that was clicked.\n * `window.event` is deprecated, but every browser still sets it during dispatch, and it is the only way to reach the\n * click when the handler passes an id without the element.\n */\nconst pickClickedPlacementDiv: PickLegacyMatch = (matches) => {\n    const target = window.event?.target;\n    return matches.find((match) => target instanceof Node && match.contains(target)) ?? matches[0];\n};\n\n/**\n * Sanitizes input for logging by removing newline and carriage return characters.\n * Prevents CWE-117 log injection attacks where malicious input could inject fake log entries.\n */\nconst sanitizeForLog = (input: string): string => input.replace(/[\\r\\n]/g, '');\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { getPlacement } from '@/host/components/placement.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\n\nexport class Placement {\n    constructor(\n        public readonly id: string,\n        public readonly name: string,\n        public readonly divId: string,\n        public readonly creative: Creative,\n        public readonly deviceType: string,\n        public readonly lightAdDetails: LightAdDetails,\n    ) {}\n\n    render = async (): Promise<void> => {\n        await this.creative.render(this);\n    };\n\n    firePreRenderImpression = (): void => {\n        this.creative.firePreRenderImpression(this);\n    };\n\n    track = (): void => {\n        this.creative.track(this);\n    };\n\n    public get div(): HTMLDivElement {\n        return getPlacement(this.lightAdDetails, {\n            lookupSource: 'light-ad',\n            adUnitPlacementId: this.divId,\n        });\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 type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { setupIntersectionObserver } from '@/components/intersectionObserver.js';\nimport { emitMetric, type ObstructionMetricName } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport type { VisibilityChangeService } from '@/components/pixels/services/visibilityChangeService.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\n\nexport class MRCObstructionViewPixel implements ViewPixel, FirePixel {\n    private viewTimerTimeoutId?: NodeJS.Timeout;\n    private obstructionCheckIntervalId?: NodeJS.Timeout;\n    private shouldFirePixelIntervalId?: NodeJS.Timeout;\n    private metricsLogged: Set<string> = new Set();\n    private wasObstructed: boolean = false;\n\n    constructor(\n        private readonly pixel: FirePixel,\n        readonly viewabilityStandard: ViewabilityStandard,\n        readonly visibilityChangeService: VisibilityChangeService,\n        private readonly viewabilityService: ViewabilityService,\n        private readonly videoPixelValidator: FirePixelValidator | undefined,\n        private readonly adDetails: AdDetails | LightAdDetails,\n    ) {}\n\n    postPixelFireCleanup(observer: IntersectionObserver, placement: Placement) {\n        observer.unobserve(placement.div);\n        clearTimeout(this.viewTimerTimeoutId);\n        clearInterval(this.obstructionCheckIntervalId);\n        this.visibilityChangeService.removeVisibilityChangeDetection();\n        this.emitObstructionRecoveryMetrics();\n        this.viewabilityService.cleanup();\n    }\n\n    postPlacementExitsViewportCleanup() {\n        clearTimeout(this.viewTimerTimeoutId);\n        clearInterval(this.obstructionCheckIntervalId);\n        clearInterval(this.shouldFirePixelIntervalId);\n        this.visibilityChangeService.removeVisibilityChangeDetection();\n    }\n\n    fireInObserver(observer: IntersectionObserver, placement: Placement): void {\n        this.fire(placement);\n        this.postPixelFireCleanup(observer, placement);\n    }\n\n    startInViewTimer(observer: IntersectionObserver, placement: Placement) {\n        // set view timer for threshold time\n        this.viewTimerTimeoutId = setTimeout(\n            () => this.fireInObserver(observer, placement),\n            this.viewabilityStandard.thresholdTimeVisibleMs,\n        );\n\n        this.performContinuousObstructionCheck(observer, placement);\n        this.visibilityChangeService.setupVisibilityChangeDetection(this.viewTimerTimeoutId, observer, placement);\n    }\n\n    // Start continously checking for obstruction every 100ms. Resets timeouts and intervals if viewability obstruction occurs\n    performContinuousObstructionCheck(observer: IntersectionObserver, placement: Placement) {\n        const intervalMs: number = 100;\n        this.obstructionCheckIntervalId = setInterval(() => {\n            try {\n                const isViewabilityObstructed = this.viewabilityService.isViewabilityObstructed(\n                    placement,\n                    this.viewabilityStandard.thresholdPercentage,\n                );\n                if (isViewabilityObstructed) {\n                    this.wasObstructed = true;\n                    clearTimeout(this.viewTimerTimeoutId);\n                    clearInterval(this.obstructionCheckIntervalId);\n                    this.startInViewTimer(observer, placement);\n                }\n            } catch (error: any) {\n                emitErrorLog({ message: error?.message, error, adDetails: this.adDetails });\n                clearInterval(this.obstructionCheckIntervalId);\n            }\n        }, intervalMs);\n    }\n\n    track(placement: Placement): void {\n        setupIntersectionObserver({\n            target: placement.div,\n            onIntersection: (observer) => this.startInViewTimer(observer, placement),\n            onExit: () => this.postPlacementExitsViewportCleanup(),\n            options: { threshold: this.viewabilityStandard.thresholdPercentage },\n            adDetails: this.adDetails,\n        });\n    }\n\n    async fire(placement: Placement): Promise<void> {\n        if (this.videoPixelValidator && !this.videoPixelValidator.shouldFirePixel()) {\n            await this.waitUntilShouldFirePixel();\n        }\n\n        this.pixel.fire(placement);\n    }\n\n    private waitUntilShouldFirePixel(): Promise<void> {\n        return new Promise((resolve) => {\n            this.shouldFirePixelIntervalId = setInterval(() => {\n                if (this.videoPixelValidator && this.videoPixelValidator.shouldFirePixel()) {\n                    clearInterval(this.shouldFirePixelIntervalId);\n                    resolve();\n                }\n            }, 100);\n        });\n    }\n\n    emitObstructionRecoveryMetrics = (): void => {\n        if (this.wasObstructed) {\n            this.logMetrics('viewpixel:iab:obstruction:recovered');\n        }\n    };\n\n    logMetrics = (metricName: ObstructionMetricName): void => {\n        if (!this.metricsLogged.has(metricName)) {\n            emitMetric({ metricName, adDetails: this.adDetails });\n            this.metricsLogged.add(metricName);\n        }\n    };\n}\n","import type { PixelMetricName } from '@/components/metrics/csaMetrics.js';\n\nexport type PixelIdentifier = {\n    readonly testId: string;\n    readonly metricName: PixelMetricName;\n};\n\nexport const BTR_IDENTIFIER: PixelIdentifier = { testId: 'ape_btr_impression', metricName: 'pixel:imp:btr' } as const;\nexport const IMPRESSION_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_impression',\n    metricName: 'pixel:imp:cod',\n} as const;\nexport const MEASURABILITY_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_measurability',\n    metricName: 'pixel:imp:atf',\n} as const;\nexport const IAB_VIEWABILITY_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_viewability_iab',\n    metricName: 'pixel:view:iab',\n} as const;\n","/**\n * Generic WeakMap-based state per placement DOM element.\n * Entries are garbage-collected when the element is removed from the DOM.\n */\nconst placementState = new WeakMap<HTMLElement, Map<string, string>>();\n\nexport const getState = <K extends string = string, V extends string = string>(\n    placementDiv: HTMLElement,\n    key: K,\n): V | undefined => placementState.get(placementDiv)?.get(key) as V | undefined;\n\nexport const setState = <K extends string = string, V extends string = string>(\n    placementDiv: HTMLElement,\n    key: K,\n    value: V,\n): void => {\n    const state = placementState.get(placementDiv);\n    if (state) {\n        state.set(key, value);\n    } else {\n        placementState.set(placementDiv, new Map([[key, value]]));\n    }\n};\n","import type { PixelMetricName } from '@/components/metrics/csaMetrics.js';\nimport { getState, setState } from '@/components/state/placement/placementState.js';\n\n/** Short string values to minimize bundle size (string literals are not minified). */\nconst FIRED = '0';\nconst ERROR = '1';\n\ntype PixelState = typeof FIRED | typeof ERROR;\n\nconst setPixelState = (div: HTMLElement, key: PixelMetricName, value: PixelState) =>\n    setState<PixelMetricName, PixelState>(div, key, value);\n\nexport const hasPixelFired = (div: HTMLElement, key: PixelMetricName): boolean =>\n    getState<PixelMetricName, PixelState>(div, key) === FIRED;\n\nexport const markPixelFired = (div: HTMLElement, key: PixelMetricName): void => setPixelState(div, key, FIRED);\n\nexport const markPixelError = (div: HTMLElement, key: PixelMetricName): void => setPixelState(div, key, ERROR);\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric, emitMetric } from '@/components/metrics/csaMetrics.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport { IMPRESSION_IDENTIFIER, type PixelIdentifier } from '@/components/pixels/pixelIdentifiers.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/state/placement/pixelState.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\n\nconst requestOptions: RequestInit = { keepalive: true, mode: 'no-cors' } as const;\nconst DETAIL_PAGE = 'detail';\nconst BTF_SLOT = 'btf';\nconst DETAIL_BTF_VIDEO_IMPRESSION_METRIC = 'pixel:imp:cod:detail-btf-video';\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            const pixelUrl = this.generatePixelUrl(this.url, placement);\n            const firedAt = performance.now();\n            const request = fetch(pixelUrl, requestOptions);\n            emitLightAdTimingMetric({\n                metricName: `${this.pixelIdentifier.metricName}:timing`,\n                metricValue: firedAt,\n                adDetails: this.adDetails,\n            });\n            await request;\n        } catch (e) {\n            markPixelError(placement.div, this.pixelIdentifier.metricName);\n            emitMetric({ metricName: `${this.pixelIdentifier.metricName}:error`, adDetails: this.adDetails });\n            throw e;\n        }\n        placement.div.appendChild(this.pixel(placement));\n        emitMetric({ metricName: this.pixelIdentifier.metricName, adDetails: this.adDetails });\n        if (this.isDetailBtfVideoLightAdImpression()) {\n            emitMetric({ metricName: DETAIL_BTF_VIDEO_IMPRESSION_METRIC, adDetails: this.adDetails });\n        }\n\n        // Do not await for 3P URLs as rendering the ad doesn't depend on successful firing\n        this.urls3p.forEach((url3p) => fetch(url3p, requestOptions));\n    }\n\n    private isDetailBtfVideoLightAdImpression = (): boolean => {\n        if (this.adDetails.logCxt.app !== 'LA') return false;\n\n        const lightAdDetails = this.adDetails as LightAdDetails;\n        return (\n            this.pixelIdentifier.metricName === IMPRESSION_IDENTIFIER.metricName &&\n            lightAdDetails.pageType === DETAIL_PAGE &&\n            lightAdDetails.slotName === BTF_SLOT &&\n            Boolean(lightAdDetails.videoCreative)\n        );\n    };\n\n    /**\n     * This pixel is used by the UI Tests\n     * No src is set, as the pixel is fired by a fetch\n     */\n    private pixel = (placement: Placement): HTMLImageElement => {\n        const pixel = document.createElement('img');\n        pixel.id = `${this.pixelIdentifier.testId}_${placement.name}`;\n        pixel.style.display = 'none';\n        pixel.setAttribute('pixel-url', this.generatePixelUrl(this.url, placement));\n        return pixel;\n    };\n}\n","/**\n * Calculates what percentage of the element is within the viewport\n * @param elementDOMRect - The element's bounding rectangle\n * @returns a number between 0 and 1\n */\nexport const getVisiblePercentageInViewport = (elementDOMRect: DOMRect): number => {\n    const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n    const windowWidth = window.innerWidth || document.documentElement.clientWidth;\n\n    const visibleRect = {\n        top: Math.max(0, elementDOMRect.top),\n        left: Math.max(0, elementDOMRect.left),\n        bottom: Math.min(windowHeight, elementDOMRect.bottom),\n        right: Math.min(windowWidth, elementDOMRect.right),\n    };\n\n    if (\n        elementDOMRect.top >= windowHeight ||\n        elementDOMRect.left >= windowWidth ||\n        elementDOMRect.bottom <= 0 ||\n        elementDOMRect.right <= 0 ||\n        elementDOMRect.width <= 0 ||\n        elementDOMRect.height <= 0\n    ) {\n        return 0;\n    }\n\n    const visibleArea = (visibleRect.right - visibleRect.left) * (visibleRect.bottom - visibleRect.top);\n    const totalArea = elementDOMRect.width * elementDOMRect.height;\n    const visiblePercentage = visibleArea / totalArea;\n    return visiblePercentage;\n};\n","import type { ObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionService.js';\nimport type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric, type ObstructionMetricName } from '@/components/metrics/csaMetrics.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport { getVisiblePercentageInViewport } from '@/components/pixels/viewPixelUtil.js';\n\nexport const createViewabilityService = (\n    obstructionDetectionService: ObstructionDetectionService,\n    adDetails: AdDetails | LightAdDetails,\n): ViewabilityService => {\n    const metricsLogged: Set<string> = new Set();\n\n    const logMetrics = (metricName: ObstructionMetricName): void => {\n        if (!metricsLogged.has(metricName)) {\n            emitMetric({ metricName, adDetails });\n            metricsLogged.add(metricName);\n        }\n    };\n\n    const isViewabilityObstructed = (placement: Placement, threshold: number): boolean => {\n        const placementDOMRect = placement.div.getBoundingClientRect();\n        const visiblePercentageInViewport = getVisiblePercentageInViewport(placementDOMRect);\n        const obstructionPercentage = obstructionDetectionService.getObstructionPercentage({\n            element: placement.div,\n            elementDOMRectOverride: placementDOMRect,\n        });\n\n        const isViewabilityObstructed = visiblePercentageInViewport - obstructionPercentage < threshold;\n        if (isViewabilityObstructed) {\n            logMetrics('viewpixel:iab:obstruction');\n        }\n        return isViewabilityObstructed;\n    };\n\n    return {\n        isViewabilityObstructed(placement: Placement, threshold: number): boolean {\n            return isViewabilityObstructed(placement, threshold);\n        },\n        cleanup(): void {\n            obstructionDetectionService.cleanup();\n        },\n    };\n};\n","import type { Placement } from '@/components/pixels/pixel.js';\n\nexport interface VisibilityChangeService {\n    activeVisChangeHandler?: EventListenerOrEventListenerObject;\n    removeVisibilityChangeDetection(): void;\n    setupVisibilityChangeDetection: (\n        timeoutId: NodeJS.Timeout,\n        observer: IntersectionObserver,\n        placement: Placement,\n    ) => void;\n}\n\nexport const createVisibiltyChangeService = (): VisibilityChangeService => {\n    const visibilityChangeEventHandler = (\n        timeoutId: NodeJS.Timeout,\n        observer: IntersectionObserver,\n        placement: Placement,\n    ) => {\n        if (document.hidden) {\n            clearTimeout(timeoutId);\n            observer.unobserve(placement.div);\n        } else {\n            observer.observe(placement.div);\n        }\n    };\n\n    return {\n        removeVisibilityChangeDetection(): void {\n            if (this.activeVisChangeHandler) {\n                document.removeEventListener('visibilitychange', this.activeVisChangeHandler);\n                this.activeVisChangeHandler = undefined;\n            }\n        },\n\n        setupVisibilityChangeDetection(\n            timeoutId: NodeJS.Timeout,\n            observer: IntersectionObserver,\n            placement: Placement,\n        ): void {\n            this.removeVisibilityChangeDetection();\n            this.activeVisChangeHandler = () => visibilityChangeEventHandler(timeoutId, observer, placement);\n            document.addEventListener('visibilitychange', this.activeVisChangeHandler);\n        },\n    };\n};\n","import type { SKAdNetwork } from '@amzn/safeframe-model';\n\n/**\n * Wrapper functions for MASH Extension API - SKAN App Ads Plugin\n * https://tiny.amazon.com/rrn9ljkr\n */\ntype SkanAttributePluginCommand = {\n    skAdNetwork: SKAdNetwork;\n};\n\ntype SkanAttributeClickCommand = {\n    skAdNetwork: SKAdNetwork;\n    fallbackUrl: string;\n};\n\nexport type SkanAttributePlugin = {\n    startAttributeViewThroughAppAds: (command: SkanAttributePluginCommand) => void;\n    endAttributeViewThroughAppAds: (command: SkanAttributePluginCommand) => void;\n    renderClickThroughAppAds: (command: SkanAttributeClickCommand) => void;\n};\n\nexport const skanAttributePluginName = 'AppAdsMshopIOSPlugin';\n\n/**\n * @func startAttributeViewThroughAppAds\n * @desc Wrapper function for MASH Extension API - SKAN App Ads Plugin, handles startImpression attribution for App Ads with SKAdNetwork.\n *       This function is called when the ad is rendered.\n * @param skAdNetwork object is using  call SKAN API.\n */\nexport const startAttributeViewThroughAppAds = (skAdNetwork: SKAdNetwork): void => {\n    window.P?.when(skanAttributePluginName).execute((skanAttributePlugin: SkanAttributePlugin) => {\n        skanAttributePlugin.startAttributeViewThroughAppAds({ skAdNetwork: skAdNetwork });\n    });\n};\n\n/**\n * @func endAttributeViewThroughAppAds\n * @desc Wrapper function for MASH Extension API - SKAN App Ads Plugin, handles endImpression attribution for App Ads with SKAdNetwork.\n *       This function is called when the ad is viewed continuously for 2 secs\n *       (https://developer.apple.com/documentation/storekit/skadnetwork/endimpression(_:completionhandler:)?language=objc).\n * @param skAdNetwork {object} SKAdNetwork object pass to MASH API for app ads\n */\nexport const endAttributeViewThroughAppAds = (skAdNetwork: SKAdNetwork): void => {\n    window.P?.when(skanAttributePluginName).execute((skanAttributePlugin: SkanAttributePlugin) => {\n        skanAttributePlugin.endAttributeViewThroughAppAds({ skAdNetwork: skAdNetwork });\n    });\n};\n\n/**\n * @func renderClickThroughAppAds\n * @desc Wrapper function for MASH Extension API - SKAN App Ads Plugin, handles click-through attribution for App Ads with SKAdNetwork\n * @param skAdNetwork {?object} SK Ad Network object pass to MASH API for app ads click-through store-kit render\n * @param url {string} The fallback url used to pass to MASH API\n */\nexport const renderClickThroughAppAds = (skAdNetwork: SKAdNetwork, url: string): void => {\n    window.P?.when(skanAttributePluginName).execute((skanAttributePlugin: SkanAttributePlugin) => {\n        skanAttributePlugin.renderClickThroughAppAds({ skAdNetwork: skAdNetwork, fallbackUrl: url });\n    });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric, emitMetric } from '@/components/metrics/csaMetrics.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { startAttributeViewThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.js';\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/state/placement/pixelState.js';\n\nconst METRIC_NAME = 'pixel:imp:skan' as const;\n\nexport class SkanImpressionPixel implements FirePixel {\n    constructor(private readonly adDetails: AdDetails | LightAdDetails) {}\n\n    async fire(placement: Placement): Promise<void> {\n        if (hasPixelFired(placement.div, METRIC_NAME)) {\n            return;\n        }\n        markPixelFired(placement.div, METRIC_NAME);\n        const firedAt = performance.now();\n        try {\n            startAttributeViewThroughAppAds(this.adDetails.skAdNetwork!);\n        } catch (e) {\n            markPixelError(placement.div, METRIC_NAME);\n            throw e;\n        }\n        emitLightAdTimingMetric({\n            metricName: `${METRIC_NAME}:timing`,\n            metricValue: firedAt,\n            adDetails: this.adDetails,\n        });\n        emitMetric({ metricName: METRIC_NAME, adDetails: this.adDetails });\n    }\n}\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric, emitMetric } from '@/components/metrics/csaMetrics.js';\nimport type { FirePixel } from '@/components/pixels/firePixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { endAttributeViewThroughAppAds } from '@/components/skadnetwork/skanAppAdsAttribution.js';\nimport { hasPixelFired, markPixelError, markPixelFired } from '@/components/state/placement/pixelState.js';\n\nconst METRIC_NAME = 'pixel:view:skan' as const;\n\nexport class SkanViewPixel implements FirePixel {\n    constructor(private readonly adDetails: AdDetails | LightAdDetails) {}\n\n    async fire(placement: Placement): Promise<void> {\n        if (hasPixelFired(placement.div, METRIC_NAME)) {\n            return;\n        }\n        markPixelFired(placement.div, METRIC_NAME);\n        const firedAt = performance.now();\n        try {\n            endAttributeViewThroughAppAds(this.adDetails.skAdNetwork!);\n        } catch (e) {\n            markPixelError(placement.div, METRIC_NAME);\n            throw e;\n        }\n        emitLightAdTimingMetric({\n            metricName: `${METRIC_NAME}:timing`,\n            metricValue: firedAt,\n            adDetails: this.adDetails,\n        });\n        emitMetric({ metricName: METRIC_NAME, adDetails: this.adDetails });\n    }\n}\n","export const ATF_URL_KEY = 'atf' as const;\nexport const VIEW_PIXEL_URL_KEY = 'v' as const;\nexport const BTR_JSON_KEY = 'c' as const;\nexport const aaxTypeMacro = /\\${AAX_TYPE}/;\nexport const aaxPayloadMacro = /\\${AAX_PAYLOAD}/;\n","const EMPTY_OBJECT_STRINGIFIED = '{}' as const;\nconst EMPTY_STRING = '' as const;\n\n/**\n * This function adds a query parameter to the given URL where the value is a JSON.\n * The most common use-case is addition of `publisherJSON` to AAX URLs. eg: https://evergreen.corp.amazon.com/aax-hub/apis/bid-api/xsp/#impression\n * If the existing URL already contains this parameter key, the two JSONs are merged based on the top-level keys.\n * In case of a conflict, priority is given to the new JSON.\n *\n * eg:\n * 1. If url contains json {\"key1\": \"value1\"}, and queryParamValueObject contains {\"key1\":\"value2\"}, priority is given to queryParamValueObject.\n *    Final json is {\"key1\":\"value2\"}\n * 2. If url contains json {\"key1\": \"value1\"}, and queryParamValueObject contains {\"key2\":\"value2\"}, JSONs are merged.\n *    Final json is {\"key1\":\"value1\", \"key2\":\"value2\"}\n *\n * @param {string} url - URL where query param needs to be added.\n * @param {string} queryParamKey - key of query param that needs to be added.\n * @param {Object} queryParamValueObject - value of query param that needs to be added.\n * @returns {string} URL with query param added.\n * @throws Error if invalid inputs are provided.\n **/\nexport const addJSONQueryParamToURL = (\n    url: string,\n    queryParamKey: string,\n    queryParamValueObject: { [key: string]: any },\n): string => {\n    if (queryParamKey === EMPTY_STRING) {\n        throw new Error(\n            'Invalid queryParamKey input to addJSONQueryParamToURL: ' +\n                JSON.stringify({ queryParamKey: queryParamKey }),\n        );\n    }\n    const urlObject = new URL(url);\n    const pk = urlObject.searchParams.get(queryParamKey);\n    const existingJSONString = pk ? pk : EMPTY_OBJECT_STRINGIFIED;\n    const existingJSONObject = JSON.parse(existingJSONString);\n    const mergedJSONObject = Object.assign(existingJSONObject, queryParamValueObject);\n    urlObject.searchParams.set(queryParamKey, JSON.stringify(mergedJSONObject));\n    return urlObject.toString();\n};\n","export const safeFunctionWrapper = (\n    handler: (...safeArgs: any[]) => void,\n    errorHandler?: (msg: string, ex?: any) => void,\n    errorMessage?: string,\n): any => {\n    return (...args: any[]) => {\n        try {\n            handler(...args);\n        } catch (ex) {\n            errorHandler?.(errorMessage ? errorMessage : 'Error in handler', ex);\n        }\n    };\n};\n\n// Below code is for utf_8 compliant versions of atob/btoa\n//M DN https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8\n\nexport const utf_8_atob = (base64: string): string => b64_to_utf8(base64);\nexport const utf_8_btoa = (js_text: string): string => utf8_to_b64(js_text);\n\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 { BTR_JSON_KEY } from '@/components/aax/aax.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { addJSONQueryParamToURL } from '@/components/urlQueryParams/addJSONQueryParamToURL.js';\nimport { removeAAXPayloadFromUrl } from '@/components/util.js';\n\n/** btr = Begin to render: Creative assets are loaded and begin to render */\nexport const BEGIN_TO_RENDER_CLIENT = 'btr_client' as const;\n\nexport const generateBtrPixelUrl: PixelUrlGenerator = (url: string): string =>\n    // Remove removeAAXPayloadFromUrl when https://issues.amazon.com/issues/V1533734779 is resolved.\n    addJSONQueryParamToURL(removeAAXPayloadFromUrl(url), BTR_JSON_KEY, {\n        measurementMethod: BEGIN_TO_RENDER_CLIENT,\n    });\n","import type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\n\nexport const generateImpressionPixelUrl: PixelUrlGenerator = (url: string): string => url;\n","import { aaxPayloadMacro, aaxTypeMacro, ATF_URL_KEY } from '@/components/aax/aax.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { getAtfInfo } from '@/components/viewability.js';\n\nexport const generateMeasurabilityPixelUrl: PixelUrlGenerator = (url: string, params: Placement): string => {\n    const payloadObj = { atf: getAtfInfo(params.div) };\n    const encodedUrlPayload = encodeURIComponent(JSON.stringify(payloadObj));\n    return url.replace(aaxTypeMacro, ATF_URL_KEY).replace(aaxPayloadMacro, encodedUrlPayload);\n};\n","import type { Placement } from '@/components/pixels/pixel.js';\n\nexport const btr = {\n    set: (placement: Placement, value: boolean): void => {\n        placement.div.dataset.isBtr = String(value);\n    },\n    get: (placement: Placement): boolean => {\n        return placement.div.dataset.isBtr === String(true);\n    },\n};\n","import type { ViewableInfo } from '@amzn/safe-frame-client-amzn';\n\nimport { aaxPayloadMacro, aaxTypeMacro, VIEW_PIXEL_URL_KEY } from '@/components/aax/aax.js';\nimport '@/components/pixels/pageTimings.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport type { PixelUrlGenerator } from '@/components/pixels/pixelUrlGenerator.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\n\nexport interface PixelUrlParams {\n    placement: Placement;\n    definition: string;\n    thresholdPercentage: number;\n    thresholdTimeVisibleMs: number;\n    isBtr: boolean;\n    adStartTime: number;\n}\n\n// https://w.amazon.com/bin/view/AdPT/ACS/SupplyQuality/VUE/CSM/PixelPayloadFormat/\nexport const pixelUrlParameters = (pixelUrlParams: PixelUrlParams): ViewableInfo => {\n    const placementDivRect = pixelUrlParams.placement.div.getBoundingClientRect();\n    return {\n        v: {\n            def: pixelUrlParams.definition,\n            p: pixelUrlParams.thresholdPercentage,\n            t: pixelUrlParams.thresholdTimeVisibleMs,\n            ib: pixelUrlParams.isBtr,\n        },\n        wh: window.innerHeight || document.documentElement.clientHeight,\n        ww: window.innerWidth || document.documentElement.clientWidth,\n        sx: window.scrollX,\n        sy: window.scrollY,\n        ah: placementDivRect.height,\n        aw: placementDivRect.width,\n        top: placementDivRect.top,\n        left: placementDivRect.left,\n        ptv: (new Date().getTime() - (window.aPageStart ?? 0)) / 1000,\n        ttv: (new Date().getTime() - pixelUrlParams.adStartTime) / 1000,\n    };\n};\n\nexport const generateMrcObstructionViewPixelUrl = (viewabilityStandard: ViewabilityStandard): PixelUrlGenerator => {\n    const adStartTime = new Date().getTime();\n    return (url: string, placement: Placement): string => {\n        const pixelUrlParams: PixelUrlParams = {\n            placement: placement,\n            definition: viewabilityStandard.definition,\n            thresholdPercentage: viewabilityStandard.thresholdPercentage,\n            thresholdTimeVisibleMs: viewabilityStandard.thresholdTimeVisibleMs,\n            isBtr: btr.get(placement),\n            adStartTime,\n        };\n\n        const encodedUrlPayload = encodeURIComponent(JSON.stringify(pixelUrlParameters(pixelUrlParams)));\n\n        return url.replace(aaxTypeMacro, VIEW_PIXEL_URL_KEY).replace(aaxPayloadMacro, encodedUrlPayload);\n    };\n};\n","export type ViewabilityStandard = {\n    definition: string;\n    thresholdPercentage: number;\n    thresholdTimeVisibleMs: number;\n};\n\nconst IAB_VIDEO: ViewabilityStandard = {\n    definition: 'iab',\n    thresholdPercentage: 0.5,\n    thresholdTimeVisibleMs: 2000,\n} as const;\n\nconst IAB_LARGE_DISPLAY: ViewabilityStandard = {\n    definition: 'iab',\n    thresholdPercentage: 0.3,\n    thresholdTimeVisibleMs: 1000,\n} as const;\n\nconst IAB_DISPLAY: ViewabilityStandard = {\n    definition: 'iab',\n    thresholdPercentage: 0.5,\n    thresholdTimeVisibleMs: 1000,\n} as const;\n\nconst SKAN: ViewabilityStandard = {\n    definition: 'skan',\n    thresholdPercentage: 0.5,\n    thresholdTimeVisibleMs: 2000,\n} as const;\n\nexport const VIEWABILITY_STANDARDS = {\n    IAB_VIDEO,\n    IAB_LARGE_DISPLAY,\n    IAB_DISPLAY,\n    SKAN,\n} as const satisfies Record<string, ViewabilityStandard>;\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { setupIntersectionObserver } from '@/components/intersectionObserver.js';\nimport { emitMetric } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport type { Pixel, Placement } from '@/components/pixels/pixel.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\n\ntype Cleanup = () => void;\ntype State = { wasObstructed: boolean };\n\n/**\n * Creates a MRC-compliant viewability tracker that fires pixels when viewability thresholds are met.\n * Monitors viewport intersection, obstruction, and document visibility to ensure accurate viewability measurement.\n */\nexport const createViewabilityTracker = (\n    pixels: Pixel[],\n    viewabilityStandard: ViewabilityStandard,\n    viewabilityService: ViewabilityService,\n    firePixelValidators: FirePixelValidator[],\n    adDetails: AdDetails | LightAdDetails,\n): ViewPixel => {\n    /**\n     * Starts tracking viewability for the given placement.\n     * Sets up an intersection observer to monitor when the placement meets the visibility threshold.\n     * This ensures we only poll when the placement is relevant (meets threshold visibility).\n     */\n    const track = (placement: Placement): void => {\n        let cleanup: Cleanup | undefined;\n        // State must be an object to persist across multiple startViewTimer calls (viewport exit/re-entry)\n        const state: State = { wasObstructed: false };\n\n        setupIntersectionObserver({\n            target: placement.div,\n            onIntersection: (observer) => (cleanup = startViewTimer(placement, observer, state)),\n            onExit: () => cleanup?.(), // May be undefined on initial callback if placement starts below threshold\n            options: { threshold: viewabilityStandard.thresholdPercentage },\n            adDetails,\n        });\n    };\n\n    /**\n     * Starts the viewability timer when placement enters viewport.\n     * Checks every 100ms if the placement is viewable and fires pixel when threshold is met.\n     *\n     * The timer operates in three states:\n     * 1. If obstructed or hidden: marks for reset on next check (defers reset to avoid counting obstructed time)\n     * 2. If needs reset: resets the visible start time to current time (starts fresh count when unobstructed)\n     * 3. If visible and threshold met: fires pixel and cleans up\n     *\n     * The two-step reset ensures we don't count time while obstructed, and only start counting\n     * from the first unobstructed check after obstruction ends.\n     *\n     * @returns cleanup function to clear the interval and remove listeners\n     */\n    const startViewTimer = (placement: Placement, observer: IntersectionObserver, state: State): Cleanup => {\n        let visibleStartTime = performance.now();\n        let needsReset = false;\n\n        const intervalId = setInterval(() => {\n            // State 1: Obstruction detected - mark for reset to avoid counting obstructed time.\n            // isHidden() (a cheap document.hidden read) is checked first so it short-circuits the\n            // expensive obstruction hit-test (~10 elementFromPoint + getComputedStyle) on hidden tabs.\n            if (isHidden() || isObstructed(placement)) {\n                state.wasObstructed = true;\n                needsReset = true;\n            }\n            // State 2: Reset timer after obstruction cleared - start fresh count\n            else if (needsReset) {\n                visibleStartTime = performance.now();\n                needsReset = false;\n            }\n            // State 3: Threshold met and validators pass - fire pixel and cleanup\n            else if (\n                hasMetThreshold(visibleStartTime, viewabilityStandard.thresholdTimeVisibleMs) &&\n                shouldFirePixel(firePixelValidators)\n            ) {\n                pixels.forEach((pixel) => pixel.fire(placement));\n                cleanup(state.wasObstructed);\n                observer.unobserve(placement.div);\n            }\n        }, IAB_WAIT_INTERVAL_MS);\n\n        const cleanup = (wasObstructed = false): void => {\n            if (wasObstructed) {\n                logObstructionRecovery(adDetails);\n            }\n            clearInterval(intervalId);\n            viewabilityService.cleanup();\n        };\n\n        return cleanup;\n    };\n\n    /**\n     * Checks if the placement is obstructed by other elements.\n     * @returns true if obstructed, false otherwise or on error\n     */\n    const isObstructed = (placement: Placement): boolean => {\n        try {\n            return viewabilityService.isViewabilityObstructed(placement, viewabilityStandard.thresholdPercentage);\n        } catch (error: any) {\n            emitErrorLog({ message: error?.message, error, adDetails });\n            return false; // Treat errors as unobstructed to continue tracking\n        }\n    };\n\n    return { track, viewabilityStandard };\n};\n\n/**\n * Maximum allowed interval for checking viewability status per IAB standard.\n * Checks must occur at least every 100ms to accurately measure continuous viewable time.\n */\nconst IAB_WAIT_INTERVAL_MS = 100 as const;\n\n/**\n * Checks if the document is hidden (tab is not visible).\n * @returns true if document is hidden\n */\nconst isHidden = (): boolean => document.hidden;\n\n/**\n * Checks if the placement has been continuously visible for the required threshold time.\n * @param visibleStartTime - The timestamp when visibility started\n * @param thresholdTimeVisibleMs - The required threshold time in milliseconds\n * @returns true if threshold time has been met\n */\nconst hasMetThreshold = (visibleStartTime: number, thresholdTimeVisibleMs: number): boolean =>\n    performance.now() - visibleStartTime >= thresholdTimeVisibleMs;\n\n/**\n * Checks if all pixel validators allow firing the pixel.\n * @param validators - Array of validators to check\n * @returns true if all validators pass\n */\nconst shouldFirePixel = (validators: FirePixelValidator[]): boolean => validators.every((v) => v.shouldFirePixel());\n\n/**\n * Logs metrics when pixel fires after recovering from obstruction.\n */\nconst logObstructionRecovery = (adDetails: AdDetails | LightAdDetails): void => {\n    emitMetric({ metricName: 'viewpixel:iab:obstruction:recovered', adDetails });\n};\n","import { createObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.js';\nimport type { AdDetails, DeviceType, LightAdDetails, MediaType } from '@amzn/safeframe-model';\n\nimport { MRCObstructionViewPixel } from '@/components/pixels/mrcObstructionViewPixel.js';\nimport { Pixel } from '@/components/pixels/pixel.js';\nimport {\n    BTR_IDENTIFIER,\n    IAB_VIEWABILITY_IDENTIFIER,\n    IMPRESSION_IDENTIFIER,\n    MEASURABILITY_IDENTIFIER,\n} from '@/components/pixels/pixelIdentifiers.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.ts';\nimport { createViewabilityService } from '@/components/pixels/services/viewabilityServiceImpl.js';\nimport { createVisibiltyChangeService } from '@/components/pixels/services/visibilityChangeService.js';\nimport { SkanImpressionPixel } from '@/components/pixels/skanImpressionPixel.js';\nimport { SkanViewPixel } from '@/components/pixels/skanViewPixel.js';\nimport { generateBtrPixelUrl } from '@/components/pixels/urlGenerators/btrPixelUrlGenerator.js';\nimport { generateImpressionPixelUrl } from '@/components/pixels/urlGenerators/impressionPixelUrlGenerator.js';\nimport { generateMeasurabilityPixelUrl } from '@/components/pixels/urlGenerators/measurabilityPixelUrlGenerator.js';\nimport { generateMrcObstructionViewPixelUrl } from '@/components/pixels/urlGenerators/mrcObstructionViewPixelUrlGenerator.js';\nimport type { ViewabilityStandard } from '@/components/pixels/viewabilityStandards.js';\nimport { VIEWABILITY_STANDARDS } from '@/components/pixels/viewabilityStandards.js';\nimport { createViewabilityTracker } from '@/components/pixels/viewabilityTrackerImpl.js';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\nimport { NEW_VIEWABILITY_TRACKER_WEBLAB } from '@/components/weblabs.js';\n\nexport const mapToBtrPixel = (adDetails: AdDetails | LightAdDetails): Pixel | undefined => {\n    return adDetails.btrPixelUrl\n        ? new Pixel(adDetails.btrPixelUrl, generateBtrPixelUrl, BTR_IDENTIFIER, adDetails)\n        : undefined;\n};\n\nexport const mapToImpressionPixel = (adDetails: AdDetails | LightAdDetails, imp3pUrls: string[] = []): Pixel =>\n    new Pixel(adDetails.aaxImpPixelUrl, generateImpressionPixelUrl, IMPRESSION_IDENTIFIER, adDetails, imp3pUrls);\n\nexport const mapToMeasurabilityPixel = (adDetails: AdDetails | LightAdDetails): Pixel =>\n    new Pixel(adDetails.aaxInstrPixelUrl, generateMeasurabilityPixelUrl, MEASURABILITY_IDENTIFIER, adDetails);\n\nexport const createIabViewPixel = async (\n    mediaType: MediaType,\n    htmlElement: HTMLElement,\n    adDetails: AdDetails | LightAdDetails,\n    firePixelValidator: () => Promise<FirePixelValidator>,\n): Promise<ViewPixel> => {\n    if (mediaType === 'V') {\n        return createMrcViewPixel(adDetails, VIEWABILITY_STANDARDS.IAB_VIDEO, await firePixelValidator());\n    } else if (isDesktop(adDetails.deviceType) && isLargeAd(htmlElement)) {\n        return createMrcViewPixel(adDetails, VIEWABILITY_STANDARDS.IAB_LARGE_DISPLAY);\n    } else {\n        return createMrcViewPixel(adDetails, VIEWABILITY_STANDARDS.IAB_DISPLAY);\n    }\n};\n\nconst isDesktop = (deviceType: DeviceType): boolean => deviceType === 'DESKTOP';\n\n/**\n * Large IAB view pixel is used to measure the time the ad is visible on the screen.\n * An ad can be considered a large ad if it is of 242,500 pixels are larger\n * @link https://www.iab.com/wp-content/uploads/2015/06/MRC-Viewable-Ad-Impression-Measurement-Guideline.pdf\n */\nconst isLargeAd = (htmlElement: HTMLElement): boolean => getSizeOfElementInTotalPixels(htmlElement) >= 242500;\n\nconst getSizeOfElementInTotalPixels = (htmlElement: HTMLElement): number =>\n    htmlElement.getBoundingClientRect().height * htmlElement.getBoundingClientRect().width;\n\nconst createMrcViewPixel = (\n    adDetails: AdDetails | LightAdDetails,\n    standard: ViewabilityStandard,\n    validator?: FirePixelValidator,\n): ViewPixel => {\n    const pixel = new Pixel(\n        adDetails.aaxInstrPixelUrl,\n        generateMrcObstructionViewPixelUrl(standard),\n        IAB_VIEWABILITY_IDENTIFIER,\n        adDetails,\n    );\n\n    if (NEW_VIEWABILITY_TRACKER_WEBLAB().is('t1')) {\n        return createViewabilityTracker(\n            [pixel],\n            standard,\n            createViewabilityService(createObstructionDetectionService(), adDetails),\n            validator ? [validator] : [],\n            adDetails,\n        );\n    } else {\n        return new MRCObstructionViewPixel(\n            pixel,\n            standard,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService(), adDetails),\n            validator,\n            adDetails,\n        );\n    }\n};\n\nexport const mapToSkanImpressionPixel = (adDetails: AdDetails | LightAdDetails): SkanImpressionPixel | undefined => {\n    return adDetails.skAdNetwork ? new SkanImpressionPixel(adDetails) : undefined;\n};\n\nexport const mapToSkanViewPixel = (adDetails: AdDetails | LightAdDetails): ViewPixel | undefined => {\n    if (adDetails.skAdNetwork) {\n        const skanPixel = new SkanViewPixel(adDetails);\n        return new MRCObstructionViewPixel(\n            skanPixel,\n            VIEWABILITY_STANDARDS.SKAN,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService(), adDetails),\n            undefined,\n            adDetails,\n        );\n    }\n    return undefined;\n};\n","/**\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 { executeWhenConditionMet } from '@/components/executeWhenConditionMet.js';\n\nconst VJS_CLASSES = ['video-js', 'vjs-tech'] as const;\n\n/** How long to wait for a usable `<video>`. CBC's comes from a lazily loaded homepage card. */\nconst MAX_WAIT_MS = 15_000;\n\nconst isVjsManaged = (video: HTMLVideoElement): boolean => VJS_CLASSES.some((cls) => video.classList.contains(cls));\n\nconst findReadyVideo = (placementDiv: HTMLElement): HTMLVideoElement | null => {\n    const video = placementDiv.querySelector<HTMLVideoElement>('video');\n    if (!video) return null;\n    if (isVjsManaged(video) && !video.src) return null;\n    return video;\n};\n\nexport const getVideo = async (placementDiv: HTMLElement): Promise<HTMLVideoElement> => {\n    const existing = findReadyVideo(placementDiv);\n    if (existing) return existing;\n\n    let video: HTMLVideoElement | null = null;\n    try {\n        await executeWhenConditionMet({\n            condition: () => {\n                video = findReadyVideo(placementDiv);\n                return video !== null;\n            },\n            action: async () => {},\n            maxWaitMs: MAX_WAIT_MS,\n        });\n    } catch (e) {\n        const error = e as Error;\n        throw new Error(`No <video> element found inside #${placementDiv.id}: ${error.message}`);\n    }\n    return video!;\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","export const btr = {\n    set: (element: HTMLElement, value: boolean): void => {\n        element.dataset.isBtr = String(value);\n    },\n    get: (element: HTMLElement): boolean => {\n        return element.dataset.isBtr === String(true);\n    },\n};\n","/**\n * Possible status codes indicating the evaluation result of a creative's rendering.\n */\nimport { btr } from './btr.js';\n\nexport type Code = 'BEGIN_TO_RENDER' | 'ERROR' | 'NO_CREATIVE';\n\n/**\n * Represents the response structure for evaluating whether a creative has begun to render.\n */\nexport interface CreativeBeginToRenderResponse {\n    /** Indicates whether the creative has begun to render successfully. */\n    success: boolean;\n\n    /** The status code indicating the result of the evaluation. */\n    code: Code;\n}\n\n/**\n * Evaluates whether a creative inside the provided container has begun to render.\n * This is determined by checking the BTR dataset flag or if any visible images within the container have loaded.\n *\n * @param creativeContainer - The HTML element containing the creative.\n * @returns A response indicating whether rendering has begun.\n */\nexport const evaluateCreativeBeginToRender = (creativeContainer: HTMLElement): CreativeBeginToRenderResponse => {\n    if (btr.get(creativeContainer)) {\n        return { success: true, code: 'BEGIN_TO_RENDER' };\n    }\n\n    const images = Array.from(creativeContainer.querySelectorAll('img')).filter(\n        (x) => getComputedStyle(x).display !== 'none',\n    );\n    return evaluateAnyImageLoaded(images);\n};\n\n/**\n * Evaluates whether any image in the provided list has successfully loaded.\n *\n * The function checks if at least one image is fully loaded (i.e., it is marked as complete\n * and has non-zero dimensions). If no images are present, it returns `NO_CREATIVE`.\n * If at least one image loads successfully, it returns `BEGIN_TO_RENDER`.\n * If all images fail to load, it returns `ERROR`.\n *\n * @param images - An array of HTML image elements to evaluate.\n * @returns A response indicating whether rendering has begun, no creative was found, or an error occurred.\n */\nconst evaluateAnyImageLoaded = (images: HTMLImageElement[]): CreativeBeginToRenderResponse => {\n    if (images.length === 0) {\n        return { success: false, code: 'NO_CREATIVE' };\n    }\n\n    return images.some((img) => img.complete && img.naturalWidth > 0 && img.naturalHeight > 0)\n        ? { success: true, code: 'BEGIN_TO_RENDER' }\n        : { success: false, code: 'ERROR' };\n};\n","import { evaluateCreativeBeginToRender } from '@amzn/creative-rendering-monitor/src/creativeBTREvaluatorSync.js';\n\nexport interface BtrState {\n    isBtr: boolean;\n    isBtrUnknown: boolean;\n}\n\nexport const waitForBeginToRender = async (element: HTMLElement = document.body): Promise<boolean> => {\n    const btrEvaluationWaitTime = 75;\n    let elapsedTime = 0;\n    const intervalMs = 5;\n\n    // setInterval never fires at t=0, so an already-rendered creative otherwise pays a wasted first\n    // tick before onCreativeLoad/onCreativeBeginToRender can fire. evaluateCreativeBeginToRender is a\n    // pure synchronous DOM read, so evaluate it once up front and skip the poll entirely when it passes.\n    if (evaluateCreativeBeginToRender(element).success) {\n        return true;\n    }\n\n    return new Promise<boolean>((resolve) => {\n        const intervalId = setInterval(() => {\n            elapsedTime += intervalMs;\n\n            const response = evaluateCreativeBeginToRender(element);\n            if (response.success) {\n                clearInterval(intervalId);\n                resolve(true);\n            } else if (elapsedTime >= btrEvaluationWaitTime) {\n                clearInterval(intervalId);\n                resolve(false);\n            }\n        }, intervalMs);\n    });\n};\n\n/**\n * True when the document contains a nested iframe. The BTR evaluator can't see into a cross-origin\n * inner iframe, so begin-to-render can never be detected for such creatives.\n */\nexport const hasInnerIframe = (element: HTMLElement = document.body): boolean =>\n    element.querySelector('iframe') !== null;\n\n/**\n * Resolves begin-to-render state for a creative. A creative in a cross-origin inner iframe can\n * never resolve BTR, so skip the futile wait and mark it unknown so the BTR rate can be offset\n * downstream. Otherwise begin-to-render is detected exactly as before.\n */\nexport const evaluateBtr = async (\n    btrPixelUrl: string | undefined,\n    element: HTMLElement = document.body,\n): Promise<BtrState> => {\n    const isBtrUnknown = Boolean(btrPixelUrl) && hasInnerIframe(element);\n    const isBtr = !isBtrUnknown && btrPixelUrl ? await waitForBeginToRender(element) : false;\n    return { isBtr, isBtrUnknown };\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","const DATA_ATTRIBUTE_NAME = 'data-val';\n\n/**\n * Reads the click-tracking parameters populated by Percolate for a placement.\n */\nexport const getClickTrackingParam = (placementDivId: string): string | '' => {\n    const targetId = `${placementDivId}_ClickTracking`;\n    const element = document.getElementById(targetId);\n    return element?.getAttribute?.(DATA_ATTRIBUTE_NAME) ?? '';\n};\n","const PLACEHOLDER_DEFAULT = '&pd_rd_plhdr=t';\n\n/**\n *  HTML entity examples:\n *      Symbols\n *          shortest: &lt;\n *          longest: &Omicron;\n *\n *      Numbers\n *          (0-31 are control characters)\n *          shortest: &#32;\n *          longest: &#8721;\n *\n *  Regular Expressions\n *      Entity Numbers: (&#(0-){2};)|(&#(a-z){3};)|(&#(a-z){4};)\n *      Entity Symbols: (&(a-z){2};)|(&(a-z){3};)|(&(a-z){4};)|(&(a-z){5};)|(&(a-z){6};)|(&(a-z){7};)\n */\nconst REGEX_MATCH = new RegExp(\n    /((&#\\d{2,4};)|(&[a-z]{2};)|(&[a-z]{3,7};)|(%[a-fA-F0-9]{2})|(\\W))pd_rd_plhdr(=|%3D)t((&#\\d{2,4};)|(&[a-z]{2,7};)|(%[a-fA-F0-9]{2})|(\\W))/,\n);\n\n/**\n * Indices must be updated if RegEx groups are modified.\n * Each left and right group has 10 subgroups.\n * String.prototype.match() call will return the results of 22 groups.\n * Main result of the left matching group will be at index 1, while\n * the primary result of the right group is stored at index 12.\n */\nconst LEFT_GROUP_INDEX = 1;\nconst MIDDLE_GROUP_INDEX = 7;\nconst RIGHT_GROUP_INDEX = 8;\nconst LEFT_GROUP_VALUE = '$' + LEFT_GROUP_INDEX;\nconst RIGHT_GROUP_VALUE = '$' + RIGHT_GROUP_INDEX;\n\n/**\n * Replaces placeholders in HTML content with a specified click tracker value.\n *\n * This function substitutes the placeholder `PLACEHOLDER_DEFAULT` (`&pd_rd_plhdr=t`) in the provided\n * HTML content with the given click tracker value. It handles cases where the placeholder is surrounded\n * by HTML entities or URL encoding, ensuring that the replacement respects the format of the surrounding content.\n *\n * @param {string} clickTracker - The replacement value for the placeholder.\n *   - If the value matches the default placeholder or is empty/whitespace, no replacement is performed.\n *   - HTML entities in the value are escaped (e.g., `&` becomes `&amp;`) when appropriate.\n * @param {string} htmlContent - The HTML content where the placeholder should be replaced.\n * @returns {string} The updated HTML content with placeholders replaced.\n */\nexport const replaceForHtml = (clickTracker: string, htmlContent: string): string => {\n    let content = htmlContent,\n        replacement = clickTracker;\n\n    if (clickTracker === PLACEHOLDER_DEFAULT || clickTracker.trim() === '') {\n        return content;\n    }\n\n    replacement = replacement.replace(/&amp;/g, '&').replace(/^&+/, '').replace(/&+$/, '');\n\n    try {\n        let match;\n        let executions = 0;\n        do {\n            executions++;\n            match = content.match(REGEX_MATCH);\n\n            if (!match) {\n                break;\n            }\n\n            const left = match[LEFT_GROUP_INDEX]; // Match of main left group - not subgroups\n            const right = match[RIGHT_GROUP_INDEX]; // Match of main right group - not subgroups\n            const middle = match[MIDDLE_GROUP_INDEX]; // Match middle group (equals sign)\n\n            const hasHtmlEntity =\n                (left.startsWith('&') && left.endsWith(';')) || (right.startsWith('&') && right.endsWith(';'));\n            const hasUrlEncoding = left.startsWith('%') && right.startsWith('%') && middle === '%3D';\n\n            if (hasHtmlEntity) {\n                content = content.replace(\n                    REGEX_MATCH,\n                    LEFT_GROUP_VALUE + replacement.replace(/&/g, '&amp;') + RIGHT_GROUP_VALUE,\n                );\n            } else if (hasUrlEncoding) {\n                content = content.replace(\n                    REGEX_MATCH,\n                    LEFT_GROUP_VALUE + encodeURIComponent(replacement) + RIGHT_GROUP_VALUE,\n                );\n            } else {\n                content = content.replace(REGEX_MATCH, LEFT_GROUP_VALUE + replacement + RIGHT_GROUP_VALUE);\n            }\n        } while (match && executions < 10);\n    } catch (_ex) {\n        return htmlContent;\n    }\n\n    return content;\n};\n\n/**\n * Replaces placeholders in a URL with a specified click tracker value.\n *\n * This function searches for occurrences of the placeholder `pd_rd_plhdr=t` in the given URL\n * and replaces them with the specified click tracker value. It also trims leading or trailing\n * ampersands (`&` or `&amp;`) from the replacement value to avoid introducing malformed URLs.\n *\n * @param {string} clickTracker - The replacement value for the placeholder.\n *   - If the value matches the default placeholder or is empty/whitespace, no replacement is performed.\n * @param {string} url - The URL where the placeholder should be replaced.\n * @returns {string} The updated URL with placeholders replaced.\n */\nexport const replaceForUrl = (clickTracker: string, url: string): string => {\n    if (clickTracker === PLACEHOLDER_DEFAULT || clickTracker.trim() === '') {\n        return url;\n    }\n\n    const URL_PLACEHOLDER_REGEX = /pd_rd_plhdr=t/g;\n    const trimAmpersands = (clickTracker: string): string => {\n        return clickTracker.trim().replace(/^(&amp;|&)+|(&amp;|&)+$/g, '');\n    };\n\n    return url.replace(URL_PLACEHOLDER_REGEX, trimAmpersands(clickTracker));\n};\n","import { getClickTrackingParam } from '@amzn/grandprix-runtime/src/click-tracking.js';\n\nimport { replaceForUrl } from '@/components/clickTracking/replace.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\n\nexport const replaceClickTrackingParamForDisplayCreative = async (placement: Placement): Promise<void> => {\n    const clickTrackingParam = getClickTrackingParam(placement.div.id);\n    if (!clickTrackingParam) return;\n\n    for (const a of placement.div.querySelectorAll('a')) {\n        a.href = replaceForUrl(clickTrackingParam, a.href);\n    }\n};\n","import { createObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.js';\nimport type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { waitForBeginToRender } from '@/components/beginToRender.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport { createViewabilityService } from '@/components/pixels/services/viewabilityServiceImpl.js';\nimport { isViewRateExperimentEnabled, trackViewRateExperiment } from '@/components/viewRateExperimentUtil.js';\nimport { CLICK_TRACKING_PAINTER_TEST, LIGHT_ADS_EVERYWHERE_WEBLAB } from '@/components/weblabs.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\nimport type { Pixels } from '@/light-ad/domain/model/pixels.js';\nimport { replaceClickTrackingParamForDisplayCreative } from '@/light-ad/domain/service/click-tracking-service.js';\n\nexport const createDisplayCreative = (\n    placementDivId: string,\n    pixels: Pixels,\n    adProgramId: number,\n    adDetails: LightAdDetails,\n): Creative => {\n    let _isBtr = false;\n\n    return {\n        async render(placement: Placement): Promise<void> {\n            _isBtr = await (LIGHT_ADS_EVERYWHERE_WEBLAB().is('t1')\n                ? tryWaitForBTRLightAds(placement.div)\n                : waitForBeginToRender(placement.div));\n\n            if (!CLICK_TRACKING_PAINTER_TEST().isInTreatment()) {\n                replaceClickTrackingParamForDisplayCreative(placement);\n            }\n        },\n\n        firePreRenderImpression(placement: Placement): void {\n            fireCODImpression(placement, pixels, adProgramId);\n        },\n\n        track(placement: Placement): void {\n            fireImpressions(placement, pixels, _isBtr, adProgramId, adDetails);\n            trackViewability(placement, pixels);\n        },\n    };\n};\n\nconst fireCODImpression = (placement: Placement, pixels: Pixels, adProgramId: number): void => {\n    if (isViewRateExperimentEnabled(adProgramId)) {\n        // Do Nothing: delay firing of the COD impression pixel\n    } else {\n        pixels.impressionPixel.fire(placement);\n    }\n};\n\nexport const fireImpressions = (\n    placement: Placement,\n    pixels: Pixels,\n    isBtr: boolean,\n    adProgramId: number,\n    adDetails: LightAdDetails,\n): void => {\n    btr.set(placement, isBtr);\n    const obstructionDetectionService = createObstructionDetectionService();\n    if (isViewRateExperimentEnabled(adProgramId)) {\n        trackViewRateExperiment(\n            placement,\n            {\n                impressionPixel: pixels.impressionPixel,\n                btrPixel: pixels.btrPixel,\n                measurabilityPixel: pixels.measurabilityPixel,\n            },\n            createViewabilityService(obstructionDetectionService, adDetails),\n            adDetails,\n        );\n        return;\n    }\n\n    if (btr.get(placement)) {\n        pixels.btrPixel?.fire(placement);\n    }\n    pixels.measurabilityPixel.fire(placement);\n    pixels.skanImpressionPixel?.fire(placement).then(() => pixels.skanTrackingPixel?.track(placement));\n};\n\nconst trackViewability = (placement: Placement, pixels: Pixels): void => {\n    pixels.iabViewPixel.track(placement);\n};\n\n/**\n * Wrapper for tryWaitForBTR to handle Intermediate Light Ads scenarios.\n */\nconst tryWaitForBTRLightAds = async (element: HTMLElement): Promise<boolean> =>\n    waitForBeginToRender(getTargetElementForBTR(element));\n\n/**\n * Attempts to retrieve the correct target element for BTR evaluation. If the given element has a shadow root, use that.\n * If the element given has an iframe, access its inner body and return that. Otherwise, return the original element.\n */\nconst getTargetElementForBTR = (element: HTMLElement): HTMLElement => {\n    // Check for Shadow DOM\n    if (element.shadowRoot) {\n        // TODO(@calwlai): update evaluateCreativeBeginToRender() to accept ParentNode instead of HTMLElement, since\n        // ShadowRoot satisifies .querySelectorAll(), but is not an HTMLElement.\n        return element.shadowRoot as unknown as HTMLElement;\n    }\n\n    return element;\n};\n","/**\n * Wrapper functions for Homepage Video Orchestrator\n * https://quip-amazon.com/2p4vAbdbNDVg/AmazonHomepage-Herotator-resources\n * https://code.amazon.com/packages/AmazonGatewayHerotatorJS/blobs/mainline/--/src/herotator-controller.js\n */\n\nexport type GwHerotator = {\n    pause: () => void;\n    resume: () => void;\n    addObserver: (type: string, listener: () => void) => void;\n    removeObserver: (type: string, listener: () => void) => void;\n};\n\nconst gwDesktopHerotatorPName = 'gw-desktop-herotator';\n\nexport const pauseHerotator = (): void => {\n    window.P?.when(gwDesktopHerotatorPName).execute((gwHerotator: GwHerotator): void => {\n        gwHerotator.pause();\n    });\n};\n\nexport const resumeHerotator = (): void => {\n    window.P?.when(gwDesktopHerotatorPName).execute((gwHerotator: GwHerotator): void => {\n        gwHerotator.resume();\n    });\n};\n\nexport const addObserverHerotator = (type: string, listener: () => void): void => {\n    window.P?.when(gwDesktopHerotatorPName).execute((gwHerotator: GwHerotator): void => {\n        gwHerotator.addObserver(type, listener);\n    });\n};\n\nexport const removeObserverHerotator = (type: string, listener: () => void): void => {\n    window.P?.when(gwDesktopHerotatorPName).execute((gwHerotator: GwHerotator): void => {\n        gwHerotator.removeObserver(type, listener);\n    });\n};\n","import { addObserverHerotator, pauseHerotator, resumeHerotator } from '@/components/homepage/homepageHerotator.js';\n\nexport const setupH1Herotator = (video: HTMLVideoElement): void => {\n    addObserverHerotator('page_changed', () => (video.currentTime = 0));\n\n    // When video starts playing, pause Herotator\n    if (!video.paused) {\n        pauseHerotator();\n    }\n    video.addEventListener('play', () => pauseHerotator());\n    video.addEventListener('timeupdate', () => {\n        if (!video.paused) pauseHerotator();\n    });\n\n    // User pauses video, rotator resumes\n    video.addEventListener('pause', () => resumeHerotator());\n\n    // Video finishes, rotator resumes\n    video.addEventListener('ended', () => resumeHerotator());\n};\n","export const setupVideoControlsVisibility = (placementDivId: string, video: HTMLVideoElement): void => {\n    setupPlayPauseControls(\n        video,\n        getControl(placementDivId, 'play') ?? getControl(placementDivId, 'replay'),\n        getControl(placementDivId, 'pause'),\n    );\n    setupMuteControls(video, getControl(placementDivId, 'muted'), getControl(placementDivId, 'audio'));\n    setupCcControls(getControl(placementDivId, 'cc_on'), getControl(placementDivId, 'cc_off'));\n};\n\nconst setupPlayPauseControls = (\n    video: HTMLVideoElement,\n    playReplayControl: HTMLElement | null,\n    pauseControl: HTMLElement | null,\n): void => {\n    video.paused\n        ? toggleVisibility(playReplayControl, pauseControl)\n        : toggleVisibility(pauseControl, playReplayControl);\n    video.addEventListener('play', () => toggleVisibility(pauseControl, playReplayControl));\n    video.addEventListener('pause', () => toggleVisibility(playReplayControl, pauseControl));\n    video.addEventListener('ended', () => toggleVisibility(playReplayControl, pauseControl));\n};\n\nconst setupMuteControls = (\n    video: HTMLVideoElement,\n    mutedControl: HTMLElement | null,\n    audioControl: HTMLElement | null,\n): void => {\n    video.muted ? toggleVisibility(mutedControl, audioControl) : toggleVisibility(audioControl, mutedControl);\n    video.addEventListener('mute', () => toggleVisibility(mutedControl, audioControl));\n    video.addEventListener('unmute', () => toggleVisibility(audioControl, mutedControl));\n};\n\nconst setupCcControls = (ccEnableControl: HTMLElement | null, ccDisableControl: HTMLElement | null): void => {\n    toggleVisibility(ccEnableControl, ccDisableControl);\n    ccEnableControl?.addEventListener('click', () => toggleVisibility(ccDisableControl, ccEnableControl));\n    ccDisableControl?.addEventListener('click', () => toggleVisibility(ccEnableControl, ccDisableControl));\n};\n\nconst hide = (el: HTMLElement | null) => el?.style.setProperty('display', 'none');\nconst show = (el: HTMLElement | null) => el?.style.removeProperty('display');\nconst toggleVisibility = (toShow: HTMLElement | null, toHide: HTMLElement | null): void => {\n    show(toShow);\n    hide(toHide);\n};\n\nconst CONTROL_PREFIX = '_h1_control_';\nconst getControl = (id: string, suffix: string) => document.getElementById(`${id}${CONTROL_PREFIX}${suffix}`);\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitMetric, type VideoMilestoneMetricName } from '@/components/metrics/csaMetrics.js';\nimport { createLatencyTracker, type LatencyTracker } from '@/components/perf.js';\n\n/** `readyState` HAVE_FUTURE_DATA: enough data to start playback, matching `canplay`. */\nconst HAVE_FUTURE_DATA = 3;\n/** `readyState` HAVE_ENOUGH_DATA: enough data to play through, matching `canplaythrough`. */\nconst HAVE_ENOUGH_DATA = 4;\n/** Seconds of playback past a frozen `currentTime` that count as playback resuming. */\nconst PROGRESS_EPSILON_SECONDS = 0.1;\n\n/** Events that end a stall without a duration, since none of them represent recovered playback. */\nconst STALL_CANCEL_EVENTS = ['pause', 'ended', 'error', 'seeking'] as const;\n\n/**\n * Emits client-side load and buffering metrics for a Light Ad video.\n *\n * Durations are measured from `tracker`, which is created before the path-specific `getVideo` poll.\n *\n * Each load milestone is emitted at most once per video. Upstream markup owns the `<video>`, so\n * fetching usually starts before these listeners attach and a milestone event may already have\n * fired; every milestone therefore falls back to the equivalent media state observed at setup.\n *\n * `video:buffer:count` and `video:buffer:duration` cover stalls after first playback only. The\n * initial wait for playback is already reported by `video:playing:duration`.\n */\nexport const setupVideoLoadMetrics = (\n    video: HTMLVideoElement,\n    adDetails: AdDetails | LightAdDetails,\n    tracker: LatencyTracker,\n): void => {\n    emitMetric({\n        metricName: 'lightad:video:attach:duration',\n        metricValue: tracker.elapsed(),\n        adDetails,\n        additionalDimensions: {\n            readyState: String(video.readyState),\n            networkState: String(video.networkState),\n        },\n    });\n\n    measureMilestone(video, adDetails, tracker, {\n        metricName: 'lightad:video:canplay:duration',\n        event: 'canplay',\n        reachedAtSetup: video.readyState >= HAVE_FUTURE_DATA,\n    });\n    measureMilestone(video, adDetails, tracker, {\n        metricName: 'lightad:video:canplaythrough:duration',\n        event: 'canplaythrough',\n        reachedAtSetup: video.readyState >= HAVE_ENOUGH_DATA,\n    });\n    measureMilestone(video, adDetails, tracker, {\n        metricName: 'lightad:video:playing:duration',\n        event: 'playing',\n        reachedAtSetup: video.currentTime > 0,\n    });\n\n    setupBufferMetrics(video, adDetails);\n};\n\ninterface Milestone {\n    metricName: VideoMilestoneMetricName;\n    event: string;\n    reachedAtSetup: boolean;\n}\n\n/**\n * Emits a milestone once, either from its setup state or from its first event.\n */\nconst measureMilestone = (\n    video: HTMLVideoElement,\n    adDetails: AdDetails | LightAdDetails,\n    tracker: LatencyTracker,\n    { metricName, event, reachedAtSetup }: Milestone,\n): void => {\n    const emit = () => emitMetric({ metricName, metricValue: tracker.elapsed(), adDetails });\n\n    if (reachedAtSetup) {\n        emit();\n        return;\n    }\n\n    video.addEventListener(event, emit, { once: true });\n};\n\n/**\n * Counts and times post-playback stalls.\n *\n * The count is emitted when the stall begins and the duration only once playback actually\n * progresses, so abandoned stalls stay visible as a count without a duration.\n */\nconst setupBufferMetrics = (video: HTMLVideoElement, adDetails: AdDetails | LightAdDetails): void => {\n    let hasPlayed = video.currentTime > 0;\n    let stallTracker: LatencyTracker | null = null;\n    let stallPosition = 0;\n\n    video.addEventListener('playing', () => (hasPlayed = true));\n\n    video.addEventListener('waiting', () => {\n        if (!hasPlayed || stallTracker || video.seeking) return;\n\n        stallTracker = createLatencyTracker();\n        stallPosition = video.currentTime;\n        emitMetric({ metricName: 'lightad:video:buffer:count', metricValue: 1, adDetails });\n    });\n\n    video.addEventListener('timeupdate', () => {\n        // `currentTime` is frozen while stalled, so any advance past the epsilon is real progress.\n        if (!stallTracker || video.currentTime <= stallPosition + PROGRESS_EPSILON_SECONDS) return;\n\n        emitMetric({ metricName: 'lightad:video:buffer:duration', metricValue: stallTracker.elapsed(), adDetails });\n        stallTracker = null;\n    });\n\n    for (const event of STALL_CANCEL_EVENTS) {\n        video.addEventListener(event, () => (stallTracker = null));\n    }\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\n/**\n * Wrapper functions for Homepage Video Orchestrator\n * https://quip-amazon.com/A20AAkbGNjbX/Video-Orchestrator\n * https://code.amazon.com/packages/AmazonHomepageCardAssets/blobs/mainline/--/src/gw-video-orchestrator.js\n */\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\n\ntype GwVideoOrchestrator = {\n    subscribe: (element: HTMLElement, callback: SubscribeCallback, options?: GwVideoOrchestratorOptions) => void;\n    elect: (element?: HTMLElement) => void;\n};\n\ntype SubscribeCallback = (isLeader: boolean) => void;\n\nexport type GwVideoOrchestratorOptions = {\n    minVisiblePercentForLeader?: number; // number 0 to 1. The percentage of an element in the view which is bigger than this threshold is considered onScreen. Default is 0.5.\n    priority?: number; // number 0 to 100. Highest priority wins. HERO should subscribe with 100. Default is 50.\n};\n\nconst gwVideoOrchestratorPName = 'gw-video-orchestrator';\n\nexport const subscribe = (\n    element: HTMLElement,\n    callback: SubscribeCallback,\n    adDetails: AdDetails | LightAdDetails,\n    options?: GwVideoOrchestratorOptions,\n): void => {\n    window.P?.when(gwVideoOrchestratorPName).execute((gwVideoOrchestrator: GwVideoOrchestrator) => {\n        try {\n            gwVideoOrchestrator.subscribe(element, callback, options);\n        } catch (error) {\n            emitErrorLog({\n                error,\n                message: 'Failed to subscribe to video orchestrator',\n                adDetails,\n            });\n        }\n    });\n};\n\nexport const elect = (element: HTMLElement): void => homepageElect(element);\n\nexport const unelect = (): void => homepageElect();\n\nconst homepageElect = (element?: HTMLElement): void => {\n    window.P?.when(gwVideoOrchestratorPName).execute((gwVideoOrchestrator: GwVideoOrchestrator) => {\n        gwVideoOrchestrator.elect(element);\n    });\n};\n","import type { AdDetails, LightAdDetails } from '@amzn/safeframe-model';\n\nimport { elect, subscribe, unelect } from '@/components/homepage/homepageVideoOrchestrator.js';\n\nexport const videosUserPaused = new Set<string>();\n\nconst subscribeToVideoOrchestrator = (video: HTMLVideoElement, adDetails: AdDetails | LightAdDetails): void => {\n    subscribe(\n        video,\n        (isLeader) => {\n            if (isLeader && video.paused && !videosUserPaused.has(video.id)) {\n                video.play();\n            } else if (!isLeader && !video.paused) {\n                video.pause();\n            }\n        },\n        adDetails,\n        {\n            priority: 100,\n        },\n    );\n};\n\nconst handlePauseOrEnd = (video: HTMLVideoElement) => {\n    videosUserPaused.add(video.id);\n    unelect();\n};\n\nexport const setupVideoOrchestrator = (video: HTMLVideoElement, adDetails: AdDetails | LightAdDetails): void => {\n    subscribeToVideoOrchestrator(video, adDetails);\n    video.addEventListener('user-play', () => {\n        videosUserPaused.delete(video.id);\n        elect(video);\n    });\n    video.addEventListener('user-pause', () => handlePauseOrEnd(video));\n    video.addEventListener('ended', () => handlePauseOrEnd(video));\n};\n","export const setupWD1AutoRotation = async (placement: HTMLElement, video: HTMLVideoElement): Promise<void> => {\n    await autorotationOrchestratorReady();\n\n    if (!video.paused) {\n        placement.dispatchEvent(createEvent(placement, 'painterAttentionStart'));\n    }\n\n    video.addEventListener('play', () => placement.dispatchEvent(createEvent(placement, 'painterAttentionStart')));\n    video.addEventListener('pause', () => placement.dispatchEvent(createEvent(placement, 'painterAttentionEnd')));\n    video.addEventListener('ended', () => placement.dispatchEvent(createEvent(placement, 'painterAttentionEnd')));\n};\n\nconst createEvent = (placement: HTMLElement, eventType: string): Event =>\n    new CustomEvent(eventType, {\n        bubbles: true,\n        detail: {\n            painterInstanceId: placement.id,\n        },\n    });\n\nconst autorotationOrchestratorReady = async (): Promise<void> => {\n    return new Promise<void>((resolve) => {\n        window.P?.when('gw-wd-autorotation-orchestrator').execute(() => {\n            resolve();\n        });\n    });\n};\n","/**\n * This is a simplified version of\n * https://code.amazon.com/packages/D16GCreativeComponents/blobs/5c7fa05b8acbbaaea446a4489279db7c154a5294/--/src/modules/click-events/navigate.js\n *\n * The current target for OLV is endemic ad linking to Amazon page, so we only have limited support for external landing page: open in new window,\n * once we support non-endemic ad, we would need to handle external browser and prime now scenarios in mShop.\n */\n\nconst AMAZON_DOMAIN_REGEX = /^((https?:)?\\/\\/)(.*\\.)?amazon\\./;\nconst IN_SAME_WINDOW = '_top';\nconst IN_NEW_WINDOW = '_blank';\nconst CLICK_TO_NAVIGATION_DELAY_IN_MS = 150;\n\nexport const navigate = (url: string) => {\n    if (AMAZON_DOMAIN_REGEX.test(url)) {\n        setTimeout(() => {\n            window.open(url, IN_SAME_WINDOW);\n        }, CLICK_TO_NAVIGATION_DELAY_IN_MS);\n    } else {\n        window.open(url, IN_NEW_WINDOW);\n    }\n};\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { collapsePlacement } from '@/components/collapsePlacement.js';\nimport type { LatencyTracker } from '@/components/perf.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport { getVideo } from '@/light-ad/domain/helpers/getVideo.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\nimport type { Pixels } from '@/light-ad/domain/model/pixels.js';\nimport type { Placement } from '@/light-ad/domain/model/placement.js';\nimport { setupH1Herotator } from '@/light-ad/domain/service/h1HerotatorService.js';\nimport { setupVideoControlsVisibility } from '@/light-ad/domain/service/videoControlsVisibilityService.js';\nimport { setupVideoLoadMetrics } from '@/light-ad/domain/service/videoLoadMetricsService.js';\nimport { setupVideoOrchestrator } from '@/light-ad/domain/service/videoOrchestratorService.js';\nimport { setupWD1AutoRotation } from '@/light-ad/domain/service/wd1AutoRotatorService.js';\nimport { navigate } from '@/light-ad/helpers/navigate.js';\n\nexport const CCTrackMode = {\n    DISABLED: 'disabled',\n    ENABLED: 'showing',\n    ENABLED_BUT_HIDDEN: 'hidden',\n} as const;\n\nconst pixelsFired = new Set<string>();\n\nexport const createVideoCreative = (\n    pixels: Pixels,\n    trackingEvents: TrackingEvents,\n    adDetails: LightAdDetails,\n    loadTracker: LatencyTracker,\n    setupVideoPlayer: boolean = true,\n): Creative => {\n    const waitForAdToLoad = (video: HTMLVideoElement): Promise<void> => {\n        return new Promise((resolve, reject) => {\n            video.addEventListener('canplaythrough', () => resolve());\n            video.addEventListener('error', (e) => reject(e));\n            if (video.readyState >= 3) resolve();\n        });\n    };\n\n    return {\n        async render(placement: Placement): Promise<void> {\n            const video = await getVideo(placement.div);\n            setupVideoLoadMetrics(video, adDetails, loadTracker);\n            if (setupVideoPlayer) {\n                rewindVideoOnEnded(video);\n                setupH1Herotator(video);\n                setupWD1AutoRotation(placement.div, video);\n                setupVideoOrchestrator(video, adDetails);\n                setupVideoControlsVisibility(placement.div.id, video);\n                setupVideoClosedCaptions(placement.div.id, video);\n            }\n            await waitForAdToLoad(video);\n        },\n\n        firePreRenderImpression(_: Placement): void {},\n\n        async track(placement: Placement): Promise<void> {\n            const video = await getVideo(placement.div);\n            fireImpressions(video, placement, pixels, trackingEvents);\n            trackViewability(pixels, placement);\n            trackVastEvents(video, placement, trackingEvents, setupVideoPlayer);\n        },\n    };\n};\n\nconst rewindVideoOnEnded = (video: HTMLVideoElement): void => {\n    video.addEventListener('ended', () => (video.currentTime = 0));\n};\n\n// We only support VTTCue for now (.vtt files)\nconst enableCcOverlay = (cue: VTTCue, overlay: HTMLElement) => {\n    overlay.textContent = cue.text;\n    overlay.style.removeProperty('display');\n};\n\nconst disableCcOverlay = (overlay: HTMLElement) => {\n    overlay.textContent = '';\n    overlay.style.setProperty('display', 'none');\n};\n\nconst updateCcOverlay = (track: TextTrack, overlay: HTMLElement) => {\n    const cue = track.activeCues && (track.activeCues[0] as VTTCue);\n    if (cue?.text) {\n        // if there is an active cue, update its text and show it\n        enableCcOverlay(cue, overlay);\n    } else {\n        // if there is no active cue, set text to blank and hide the overlay\n        disableCcOverlay(overlay);\n    }\n};\n\nconst isCcDisabled = (track: TextTrack) => track.mode === CCTrackMode.DISABLED;\nconst isCcEnabled = (track: TextTrack) => track.mode === CCTrackMode.ENABLED_BUT_HIDDEN;\n\nconst setupVideoClosedCaptions = (placementDivId: string, video: HTMLVideoElement) => {\n    const ccOverlay = document.getElementById(`${placementDivId}_h1_overlay_cc`);\n\n    // Add custom subtitle handling if the cc overlay exists\n    if (ccOverlay && video.textTracks && video.textTracks.length > 0) {\n        const track = video.textTracks[0];\n\n        // cc is disabled by default\n        track.mode = CCTrackMode.DISABLED;\n\n        // custom event fired when track.mode is changed manually by the user\n        track.addEventListener('modechange', () => {\n            const cueChangeHandler = () => updateCcOverlay(track, ccOverlay);\n\n            if (isCcDisabled(track)) {\n                disableCcOverlay(ccOverlay);\n                track.removeEventListener('cuechange', cueChangeHandler);\n            } else if (isCcEnabled(track)) {\n                updateCcOverlay(track, ccOverlay);\n                track.addEventListener('cuechange', cueChangeHandler);\n            }\n        });\n    }\n};\n\nconst fireImpressions = (\n    video: HTMLVideoElement,\n    placement: Placement,\n    pixels: Pixels,\n    trackingEvents: TrackingEvents,\n): void => {\n    if (video.paused) {\n        video.addEventListener(\n            'playing',\n            () => {\n                btr.set(placement, true);\n                pixels.impressionPixel.fire(placement);\n                pixels.btrPixel?.fire(placement);\n                pixels.measurabilityPixel.fire(placement);\n                firePixels(trackingEvents.impressions);\n            },\n            { once: true },\n        );\n    } else {\n        btr.set(placement, true);\n        pixels.impressionPixel.fire(placement);\n        pixels.btrPixel?.fire(placement);\n        pixels.measurabilityPixel.fire(placement);\n        firePixels(trackingEvents.impressions);\n    }\n};\n\nconst trackViewability = (pixels: Pixels, placement: Placement): void => {\n    pixels.iabViewPixel.track(placement);\n};\n\nconst trackEvent = (video: HTMLVideoElement, event: string, pixels: string[]): void => {\n    video.addEventListener(event, () => firePixels(pixels));\n};\n\nconst trackVastEvents = (\n    video: HTMLVideoElement,\n    placement: Placement,\n    trackingEvents: TrackingEvents,\n    setupVideoPlayer: boolean,\n): void => {\n    trackErrorEvent(video, placement, trackingEvents);\n    trackStartEvent(video, trackingEvents);\n    trackProgressEvents(video, trackingEvents);\n    trackEvent(video, 'ended', trackingEvents.complete);\n    trackEvent(video, 'pause', trackingEvents.pause);\n    trackRewindEvent(video, trackingEvents);\n    trackResumeEvent(video, trackingEvents);\n    if (setupVideoPlayer) {\n        trackEvent(video, 'mute', trackingEvents.mute);\n        trackEvent(video, 'unmute', trackingEvents.unmute);\n        trackVideoClickEvent(video, trackingEvents);\n    } else {\n        trackVolumeChangeEvents(video, trackingEvents);\n    }\n};\n\nconst trackErrorEvent = async (\n    video: HTMLVideoElement,\n    placement: Placement,\n    trackingEvents: TrackingEvents,\n): Promise<void> => {\n    if (video.error) {\n        collapsePlacement({ adDetails: placement.lightAdDetails });\n        trackingEvents.error && firePixel(trackingEvents.error);\n    } else {\n        video.addEventListener('error', async () => {\n            collapsePlacement({ adDetails: placement.lightAdDetails });\n            trackingEvents.error && firePixel(trackingEvents.error);\n        });\n    }\n};\n\nconst trackStartEvent = (video: HTMLVideoElement, trackingEvents: TrackingEvents): void => {\n    if (video.paused) {\n        video.addEventListener('play', () => firePixels(trackingEvents.start));\n    } else {\n        firePixels(trackingEvents.start);\n    }\n};\n\nconst trackProgressEvents = (video: HTMLVideoElement, trackingEvents: TrackingEvents): void => {\n    video.addEventListener('timeupdate', () => {\n        const progress = video.currentTime / video.duration;\n        if (progress >= 0.25) firePixels(trackingEvents.firstQuartile);\n        if (progress >= 0.5) firePixels(trackingEvents.midpoint);\n        if (progress >= 0.75) firePixels(trackingEvents.thirdQuartile);\n    });\n};\n\nconst trackRewindEvent = (video: HTMLVideoElement, trackingEvents: TrackingEvents): void => {\n    let previousCurrentTime = -1;\n    video.addEventListener('timeupdate', () => {\n        if (video.currentTime < previousCurrentTime) {\n            firePixels(trackingEvents.rewind);\n        }\n        previousCurrentTime = video.currentTime;\n    });\n};\n\nconst trackResumeEvent = (video: HTMLVideoElement, trackingEvents: TrackingEvents): void => {\n    let isPaused = false;\n    video.addEventListener('pause', () => (isPaused = true));\n    video.addEventListener('play', () => isPaused && firePixels(trackingEvents.resume));\n};\n\nconst trackVideoClickEvent = (video: HTMLVideoElement, trackingEvents: TrackingEvents): void => {\n    video.addEventListener('click', (e) => {\n        e.preventDefault();\n        firePixels(trackingEvents.clickTracking);\n        trackingEvents.clickThrough && navigate(trackingEvents.clickThrough);\n    });\n};\n\nconst trackVolumeChangeEvents = (video: HTMLVideoElement, trackingEvents: TrackingEvents): void => {\n    let wasMuted = video.muted;\n    video.addEventListener('volumechange', () => {\n        if (video.muted === wasMuted) return;\n        wasMuted = video.muted;\n        firePixels(video.muted ? trackingEvents.mute : trackingEvents.unmute);\n    });\n};\n\nconst firePixels = async (pixelUrls: string[]): Promise<void> => {\n    for (const pixelUrl of pixelUrls) {\n        await firePixel(pixelUrl);\n    }\n};\n\nconst firePixel = async (pixelUrl: string): Promise<void> => {\n    if (pixelsFired.has(pixelUrl)) {\n        return;\n    }\n\n    pixelsFired.add(pixelUrl);\n\n    await fetch(pixelUrl, {\n        keepalive: true,\n        mode: 'no-cors',\n        priority: 'low',\n    } as RequestInit);\n};\n\nexport type TrackingEvents = {\n    impressions: string[];\n    error?: string;\n    start: string[];\n    firstQuartile: string[];\n    midpoint: string[];\n    thirdQuartile: string[];\n    complete: string[];\n    mute: string[];\n    unmute: string[];\n    pause: string[];\n    rewind: string[];\n    resume: string[];\n    clickThrough?: string;\n    clickTracking: string[];\n};\n","import type { LightAdDetails, VideoCreativeDTO } from '@amzn/safeframe-model';\n\nimport { createLatencyTracker } from '@/components/perf.js';\nimport {\n    createIabViewPixel,\n    mapToBtrPixel,\n    mapToImpressionPixel,\n    mapToMeasurabilityPixel,\n    mapToSkanImpressionPixel,\n    mapToSkanViewPixel,\n} from '@/components/pixels/pixelMapper.js';\nimport { createLightAdVideoFirePixelValidator } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport type { Creative } from '@/light-ad/domain/model/creative.js';\nimport { createDisplayCreative } from '@/light-ad/domain/model/displayCreative.js';\nimport type { TrackingEvents } from '@/light-ad/domain/model/videoCreative.js';\nimport { createVideoCreative } from '@/light-ad/domain/model/videoCreative.js';\n\nexport const mapToCreative = (lightAdDetails: LightAdDetails): Promise<Creative> =>\n    lightAdDetails.videoCreative ? mapToVideoCreative(lightAdDetails) : mapToDisplayCreative(lightAdDetails);\n\nconst mapToDisplayCreative = async (lightAdDetails: LightAdDetails): Promise<Creative> =>\n    createDisplayCreative(\n        lightAdDetails.adUnitPlacementId,\n        await mapToPixels(lightAdDetails),\n        Number(lightAdDetails.adCreativeMetaData.adProgramId),\n        lightAdDetails,\n    );\n\nconst mapToVideoCreative = async (lightAdDetails: LightAdDetails): Promise<Creative> => {\n    const loadTracker = createLatencyTracker();\n    const videoCreativeDto = lightAdDetails.videoCreative!;\n    return createVideoCreative(\n        await mapToPixels(lightAdDetails),\n        mapToTrackingEvents(videoCreativeDto),\n        lightAdDetails,\n        loadTracker,\n        videoCreativeDto.setupVideoPlayer ?? true,\n    );\n};\n\nconst mapToPixels = async (lightAdDetails: LightAdDetails) => {\n    const htmlElement = document.getElementById(lightAdDetails.adUnitPlacementId) as HTMLDivElement;\n    const mediaType = lightAdDetails.videoCreative ? 'V' : 'D';\n    const videoFirePixelValidator = () => createLightAdVideoFirePixelValidator(htmlElement);\n    return {\n        impressionPixel: mapToImpressionPixel(lightAdDetails, lightAdDetails.imp3pUrls),\n        measurabilityPixel: mapToMeasurabilityPixel(lightAdDetails),\n        iabViewPixel: await createIabViewPixel(mediaType, htmlElement, lightAdDetails, videoFirePixelValidator),\n        skanImpressionPixel: mapToSkanImpressionPixel(lightAdDetails),\n        skanTrackingPixel: mapToSkanViewPixel(lightAdDetails),\n        btrPixel: mapToBtrPixel(lightAdDetails),\n    };\n};\n\nconst mapToTrackingEvents = (videoCreativeDto: VideoCreativeDTO): TrackingEvents => ({\n    impressions: videoCreativeDto.impressions,\n    error: videoCreativeDto.error,\n    start: videoCreativeDto.trackingEvents.start ?? [],\n    firstQuartile: videoCreativeDto.trackingEvents.firstQuartile ?? [],\n    midpoint: videoCreativeDto.trackingEvents.midpoint ?? [],\n    thirdQuartile: videoCreativeDto.trackingEvents.thirdQuartile ?? [],\n    complete: videoCreativeDto.trackingEvents.complete ?? [],\n    mute: videoCreativeDto.trackingEvents.mute ?? [],\n    unmute: videoCreativeDto.trackingEvents.unmute ?? [],\n    pause: videoCreativeDto.trackingEvents.pause ?? [],\n    rewind: videoCreativeDto.trackingEvents.rewind ?? [],\n    resume: videoCreativeDto.trackingEvents.resume ?? [],\n    clickThrough: videoCreativeDto.videoClicks?.clickThrough,\n    clickTracking: videoCreativeDto.videoClicks?.clickTracking ?? [],\n});\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { Placement } from '@/light-ad/domain/model/placement.js';\nimport { mapToCreative } from '@/light-ad/inbound/mapper/creativeMapper.js';\n\nexport const mapToPlacement = async (lightAdDetails: LightAdDetails): Promise<Placement> => {\n    return new Placement(\n        lightAdDetails.placementId,\n        lightAdDetails.placementName,\n        lightAdDetails.adUnitPlacementId,\n        await mapToCreative(lightAdDetails),\n        lightAdDetails.deviceType,\n        lightAdDetails,\n    );\n};\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport type { LightAd } from '@/light-ad/domain/model/LightAd.js';\nimport { mapToPlacement } from '@/light-ad/inbound/mapper/placementMapper.js';\n\nexport const fromLightAdDetails = async (lightAdDetails: LightAdDetails): Promise<LightAd> => {\n    const placement = await mapToPlacement(lightAdDetails);\n    return {\n        placement,\n        lightAdDetails: lightAdDetails,\n    };\n};\n","import { getVideo } from '@/light-ad/domain/helpers/getVideo.js';\nimport { CCTrackMode } from '@/light-ad/domain/model/videoCreative.js';\n\nexport interface VideoApi {\n    replay: (placementDivId: string) => Promise<void>;\n    play: (placementDivId: string) => Promise<void>;\n    pause: (placementDivId: string) => Promise<void>;\n    mute: (placementDivId: string) => Promise<void>;\n    unmute: (placementDivId: string) => Promise<void>;\n    enableCc: (placementDivId: string) => Promise<void>;\n    disableCc: (placementDivId: string) => Promise<void>;\n    visibilityChange: (controlsToDisplay: string[], controlsToHide: string[]) => void;\n}\n\nexport class VideoApiImpl implements VideoApi {\n    async replay(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        video.currentTime = 0;\n        await this.play(placementDivId);\n    }\n\n    async play(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        video.play();\n        video.dispatchEvent(new CustomEvent('user-play'));\n    }\n\n    async pause(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        video.pause();\n        video.dispatchEvent(new CustomEvent('user-pause'));\n    }\n\n    async mute(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        video.muted = true;\n        video.dispatchEvent(new CustomEvent('mute'));\n    }\n\n    async unmute(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        video.muted = false;\n        video.dispatchEvent(new CustomEvent('unmute'));\n    }\n\n    /**\n     * Enables closed-captions for our video by setting the text track to 'hidden', which means the track will still\n     * fire events like 'cuechange' and will not display the captions natively. If there's currently an active cue,\n     * immediately populate our closed captions overlay and show it.\n     */\n    async enableCc(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        const ccOverlay = document.getElementById(`${placementDivId}_h1_overlay_cc`);\n        const track = video?.textTracks?.[0];\n\n        if (!video || !ccOverlay || !track) {\n            return;\n        }\n\n        // hidden means the text tracks will still fire events and we can populate our overlay\n        track.mode = CCTrackMode.ENABLED_BUT_HIDDEN;\n        track.dispatchEvent(new CustomEvent('modechange'));\n    }\n\n    /**\n     * Disables closed captions for our video by setting the text track to 'disabled'. It will stop firing events on the\n     * track. We de-populate our closed captions overlay and hide it.\n     */\n    async disableCc(placementDivId: string): Promise<void> {\n        const video = await getVideoElement(placementDivId);\n        const ccOverlay = document.getElementById(`${placementDivId}_h1_overlay_cc`);\n        const track = video?.textTracks?.[0];\n\n        if (!video || !ccOverlay || !track) {\n            return;\n        }\n\n        track.mode = CCTrackMode.DISABLED;\n        track.dispatchEvent(new CustomEvent('modechange'));\n    }\n\n    visibilityChange(controlsToDisplay: string[], controlsToHide: string[]): void {\n        controlsToDisplay.forEach((control) => {\n            document.getElementById(control)?.style.removeProperty('display');\n        });\n        controlsToHide.forEach((control) => {\n            document.getElementById(control)?.style.setProperty('display', 'none');\n        });\n    }\n}\n\nconst getVideoElement = async (placementDivId: string): Promise<HTMLVideoElement> => {\n    const placementDiv = document.getElementById(placementDivId)!;\n    return getVideo(placementDiv);\n};\n","import type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport { emitLightAdTimingMetric } from '@/components/metrics/csaMetrics.js';\nimport { emitErrorLog } from '@/components/metrics/emitErrorLog.js';\nimport { mark, PERF_LA } from '@/components/perf.js';\nimport { processLightAd } from '@/light-ad/domain/service/lightAdService.js';\nimport type { FeedbackApi } from '@/light-ad/inbound/feedbackApi.js';\nimport { FeedbackApiImpl } from '@/light-ad/inbound/feedbackApi.js';\nimport { fromLightAdDetails } from '@/light-ad/inbound/mapper/lightAdMapper.js';\nimport type { VideoApi } from '@/light-ad/inbound/videoApi.js';\nimport { VideoApiImpl } from '@/light-ad/inbound/videoApi.js';\n\nexport interface LightAdApi {\n    init(lightAdDetails: LightAdDetails): Promise<void>;\n\n    feedback: FeedbackApi;\n\n    video: VideoApi;\n}\n\nexport class LightAdApiImpl implements LightAdApi {\n    /**\n     * Initializes and processes a light ad with the provided details.\n     * Called from GrandPrixAdTemplates light-ad.ftl template.\n     * @see https://code.amazon.com/packages/GrandPrixAdTemplates/blobs/mainline/--/templates/amazon/light-ad.ftl\n     * @param lightAdDetails - The light ad configuration and content details\n     */\n    init = async (lightAdDetails: LightAdDetails) => {\n        const initializedAt = performance.now();\n        mark(PERF_LA, 'init');\n        emitLightAdTimingMetric({\n            metricName: 'lightad:init:timing',\n            metricValue: initializedAt,\n            adDetails: lightAdDetails,\n        });\n        try {\n            processLightAd(await fromLightAdDetails(lightAdDetails));\n        } catch (err) {\n            emitErrorLog({ message: 'Error LightAdApi.init', error: err, adDetails: lightAdDetails });\n        }\n    };\n\n    feedback = new FeedbackApiImpl();\n\n    video = new VideoApiImpl();\n}\n","import { mark, PERF_LA } from '@/components/perf.js';\nimport type { LightAdApi } from '@/light-ad/inbound/lightAdApi.js';\nimport { LightAdApiImpl } from '@/light-ad/inbound/lightAdApi.js';\n\ndeclare global {\n    interface Window {\n        APE_LA: LightAdApi;\n    }\n}\n\nexport const LIGHT_AD_API_READY_EVENT = 'LIGHT_AD_API_READY_EVENT';\n\nexport const initLightAd = (): void => {\n    if (window.APE_LA) {\n        return;\n    }\n\n    mark(PERF_LA, 'create LightAdApiImpl');\n    window.APE_LA = new LightAdApiImpl();\n    window.dispatchEvent(new CustomEvent(LIGHT_AD_API_READY_EVENT));\n};\n","/**\n * Entry point for Desktop version of light ad client-side script\n */\nimport { initLightAd } from '@/light-ad/initLightAd.js';\n\ninitLightAd();\n"],"x_google_ignoreList":[1,2,6,8,9,10,13,22,23,24,25,26,27,54,55,58],"mappings":"YAMA,IAAa,EAAU,UAKV,GAAe,EAAe,EAAiB,IACxD,GAAG,IAAQ,EAAY,IAAI,EAAU,gBAAkB,GAAG,KAAK,IAEtD,GAAQ,EAAe,EAAiB,IAAsC,SACvF,IAAM,EAAa,EAAY,EAAO,EAAS,EAAU,CAIzD,OAFA,EAAA,cAAA,OAAA,EAAA,EAAa,OAAA,MAAA,EAAA,KAAA,EAAO,EAAW,CAExB,GAQE,MAA6C,CACtD,IAAM,EAAY,YAAY,KAAK,CACnC,MAAO,CAAE,YAAW,YAAe,YAAY,KAAK,CAAG,EAAW,EC7BzD,EAAuB,yCACvB,EAAoB,sCACpB,EAAkB,uCAClB,EAAoB,aAiBpB,GAAe,CAAE,mBAAkB,aAAY,UACxD,+BAAO,MAAA,OAAA,EAAA,EAAA,KAAA,EAAM,SAAU,CACnB,GAAI,GAAc,CAAE,aAAY,CAChC,GAAI,GAAoB,CAAE,mBAAkB,CAC/C,CAAC,GAAA,KAAA,IAAA,GAAA,EAAA,KAAA,EAAG,MAAO,EAAM,CAAE,IAAK,MAAO,CAAC,ECDxB,GAAiB,CAC1B,aACA,cACA,YAAY,IAAI,KAChB,aACA,aACwB,CACxB,IAAM,EAAO,CAAE,aAAY,cAAa,aAAY,CACpD,EAAY,CACR,iBAAkB,EAClB,KAAM,CAAE,GAAG,EAAM,UAAW,EAAU,SAAS,CAAE,GAAI,GAAW,CAAE,UAAS,CAAG,CACjF,CAAC,CACF,EAAY,CACR,WAAY,EACZ,KAAM,CACF,GAAG,EACH,YAAa,KAAK,MAAM,EAAY,CACpC,UAAW,EAAU,aAAa,CAClC,SAAU,EACb,CACJ,CAAC,ECnCA,MAAiC,6BAAO,eAAA,KAAA,EAAA,aAAiB,EAAE,CAAnB,GAEjC,EAAgB,GAAoC,wBAAc,EAAC,KAAA,KAAA,EAAA,GAAe,IAAI,IAAnB,GAEnE,EAAiB,GAAsB,CAChD,IAAM,MAAY,EAAa,EAAU,CACzC,MAAO,CACH,IAAM,GAAyB,GAAK,CAAC,IAAI,EAAI,CAC7C,KAAO,GAAsB,CACzB,GAAK,CAAC,IAAI,EAAI,EAErB,EAGQ,EAAsB,EAAc,sBAAsB,CAC1D,EAAiB,EAAc,oBAAoB,CACnD,EAAgB,EAAc,WAAW,CCJzC,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,YAAsB,CAClB,OAAO,GAAiB,GAAK,IAAA,IAEjC,eAAyB,CACrB,MAAO,CAAC,CAAC,GAAiB,EAAI,GAAiB,GAAK,KAExD,cAAmC,OAC/B,OAAA,EAAO,GAAiB,GAAA,KAAI,IAAJ,GAE/B,EAaQ,OACT,EAAa,OAAQ,mEAAmE,CAM/E,OACT,EAAa,OAAQ,4DAA4D,CAMxE,OACT,EAAa,OAAQ,oEAAoE,CAahF,OACT,EAAa,OAAQ,+DAA+D,CAM3E,OACT,EAAa,OAAQ,4DAA4D,CAaxE,GAAqC,4CACrC,OAAsC,EAAa,OAAQ,GAAmC,CCyB9F,GAAc,CACvB,aACA,cAAc,EACd,UAAW,CAAE,UACb,YACA,uBACA,sBAC0B,CAC1B,GAAI,IAAqB,IAAA,GAAW,CAChC,IAAM,EAAM,GAAG,EAAW,GAAG,IAC7B,GAAI,EAAe,IAAI,EAAI,CAAE,OAC7B,EAAe,KAAK,EAAI,CAG5B,EAAc,CACV,aACA,cACA,YACA,WAAY,CAAE,GAAG,EAAsB,GAAG,EAAQ,CACrD,CAAC,EASA,EAAqB,kBAErB,GAAwB,GAAgD,OACtE,EAAe,IAAI,EAAmB,GAC1C,EAAe,KAAK,EAAmB,CAEvC,EAAc,CACV,WAAY,EACZ,YAAa,EACb,WAAY,CAAE,UAAW,EAAU,OAAO,UAAW,CACrD,SAAA,EAAS,OAAO,mBAAA,KAAoB,EAAE,CAAtB,EACnB,CAAC,GAGO,GAAoB,GAAgD,CAC7E,GAAqB,EAAU,EAetB,GAA2B,CACpC,aACA,cACA,UAAW,CAAE,aAC0B,CACvC,IAAM,EAAkB,IAA+B,CACnD,EAAO,MAAQ,MAAQ,CAAC,EAAgB,YAAY,EAExD,EAAc,CACV,aACA,cACA,WAAY,CAAE,GAAG,EAAQ,CACzB,QAAS,EACJ,IAAqC,EAAgB,cAAc,CAAC,aAAa,CACrF,CACJ,CAAC,ECjKO,IAAc,CACvB,QACA,UACA,YACA,QACA,OACA,SACA,SACA,QACA,YAAY,IAAI,KAChB,gBAEA,EAAY,CACR,iBAAkB,EAClB,KAAM,CACF,WAAY,aAAa,IACzB,YAAa,EACb,QACA,YACA,UACA,QACA,OACA,SACA,SACA,QACA,UAAW,EAAU,SAAS,CAC9B,aACH,CACJ,CAAC,CClCO,GAAgB,CAAE,UAAS,QAAO,YAAW,OAAM,SAAQ,SAAQ,WAAsC,OAClH,IAAM,EAAM,GAAQ,EAAM,CAC1B,GAAW,CACP,MAAO,QACP,UAAA,GAAA,KAAA,IAAA,GAAW,EAAK,KAChB,SAAA,EAAS,GAAA,KAAA,GAAA,KAAA,IAAA,GAAW,EAAK,QAAhB,IAAgB,KAAW,GAAX,EACzB,MAAA,GAAA,KAAA,IAAA,GAAO,EAAK,MACZ,OACA,SACA,SACA,QACA,WAAY,CAAE,GAAG,EAAU,OAAQ,CACtC,CAAC,EASA,GAAW,GAAsC,CAC/C,OAAU,IAAA,GACd,IAAI,aAAiB,MAAO,OAAO,EACnC,GAAI,OAAO,GAAU,SACjB,GAAI,CACA,OAAW,MAAM,KAAK,UAAU,EAAM,CAAC,SACnC,EAIZ,OAAW,MAAM,OAAO,EAAM,CAAC,GCjDtB,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,ECuExE,GAAW,GAAiB,EAAK,QAAQ,KAAM,IAAI,CAOnD,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,GAAQ,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,GAAQ,EAAU,KAAK,CAAE,EAAK,ECtG/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,OACvG,IAAM,EAAU,SAAS,eAAe,EAAU,kBAAkB,CAGpE,GAAqB,CAAE,eAAc,UAFR,CAAE,GAAI,EAAU,YAAa,KAAM,EAAU,cAAe,CAEzC,QAAO,YAAW,CAAC,EACnE,EAAA,GAAU,KAAA,MAAA,EAAe,QAAS,GAAW,GAAqB,EAAS,EAAQ,EAAU,CAAC,ECF5F,GAAe,GAAoD,mBAAoB,EAEvF,GAAoB,GAClB,EAAY,IAAc,QAC1B,EAAY,IAAe,SAC3B,EAAY,IAAe,SAC3B,EAAY,IAAgB,QACzB,SAGE,GAAc,GAAgD,SAKvE,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,IACT,EACA,CAAE,eAAc,oBAAoB,EAAU,qBAC7B,CACjB,IAAM,EAAY,SAAS,eAAe,EAAkB,CAE5D,GAAI,CAAC,EAAW,OACZ,EAAW,CACP,WAAY,iCACZ,YACA,qBAAsB,CAClB,cAAe,EAAU,cACzB,WAAA,EAAW,EAAU,YAAA,KAAa,KAAb,EACrB,eACA,cAAe,GAAiB,YAAY,KAAK,CAAC,CACrD,CACD,iBAAkB,EAAU,YAC/B,CAAC,CAGN,OAAO,GCnDL,GAAQ,GAAsC,CAC5C,IACA,EAAQ,MAAM,QAAU,SAQnB,GAAqB,CAAE,YAAW,UAA0C,CACjF,EAAoB,IAAI,EAAU,kBAAkB,GAIxD,GAAK,GAAW,EAAU,CAAC,CAC3B,GAAK,GAAa,EAAW,CAAE,aAAc,WAAY,CAAC,CAAC,CAE3D,EAAW,CAAE,WAAY,qBAAsB,YAAW,CAAC,CACvD,GACA,EAAW,CAAE,WAAY,sBAAsB,IAAQ,YAAW,CAAC,CAGvE,EAAoB,KAAK,EAAU,kBAAkB,GCXzD,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,EC/HT,IAAa,OACF,OAAO,aAAe,SAAS,gBAAgB,aAM7C,OACF,OAAO,YAAc,SAAS,gBAAgB,YAO5C,GAA4B,GAChB,EAAK,uBAAuB,CAC7B,IAAM,IAAc,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,GAAsB,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,GAAmB,EAAK,CAClC,EAAK,IAAc,CACnB,EAAK,IAAa,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,CC5ErG,IAAM,IAAqB,EAAsB,EAAgB,IAAsB,CACnF,IAAI,EAAmB,GACjB,MAAyB,CAC3B,IAAM,EAAW,GAAyB,EAAK,CAC/C,OAAO,GAAY,GAAY,GAG7B,MAAwB,CACtB,GAAkB,GAClB,GAAU,CACV,EAAmB,KAIrB,EAA2B,GAAS,OAAU,CAChD,GAAiB,CAEb,IACA,OAAO,oBAAoB,SAAU,EAAyB,CAC9D,OAAO,oBAAoB,SAAU,EAAyB,GAEpE,CAEF,GAAiB,CACZ,IACD,OAAO,iBAAiB,SAAU,EAAyB,CAC3D,OAAO,iBAAiB,SAAU,EAAyB,GAiBtD,IAAoB,CAC7B,WACA,gBACA,YACA,cACA,eACA,cAC2B,CAC3B,IAAM,MAA0B,CAC5B,GAAI,CACA,GAAU,OACL,EAAI,CACT,EAAa,CAAE,QAAS,mBAAoB,MAAO,EAAI,YAAW,CAAC,CACnE,GAAA,MAAA,GAAiB,GAIzB,GAAA,GAAA,MAAI,EAAa,MAAM,CAAC,MAAM,eAAe,CAKzC,GAAkB,EAAmB,SAAS,EAAa,GAAG,CAAE,EAAa,SACtE,IAAgB,UAAY,IAAa,YAAa,CAG7D,IAAM,EAAW,IAAI,qBAChB,GAAY,CAET,IAAK,IAAM,KAAS,EAChB,GAAI,EAAM,kBAAoB,EAAG,CAC7B,GAAmB,CACnB,EAAS,UAAU,EAAa,CAChC,QAIZ,CAAE,UAAW,CAAC,EAAG,IAAK,CAAE,CAC3B,CACD,EAAS,QAAQ,EAAa,MAG9B,GAAmB,EC3Ed,OAA2C,CACpD,IAAM,EAAY,IAAI,IAEtB,MAAO,CACH,SAAU,EAAa,IAA+B,CAClD,IAAM,EAAoB,EAAU,IAAI,EAAI,EAAI,EAAE,CAClD,EAAkB,KAAK,EAAS,CAChC,EAAU,IAAI,EAAK,EAAkB,EAGzC,YAAc,GAAsB,CAChC,IAAM,EAAe,EAAU,IAAI,EAAI,CACnC,IACA,EAAa,QAAS,GAAO,GAAI,CAAC,CAClC,EAAU,OAAO,EAAI,GAGhC,ECjBC,GAAkB,GAAgC,CAC/C,EAAO,WACR,EAAO,SAAW,EAAE,GAItB,EAAgB,IAAqB,CACrC,GAAqB,GAAmC,mBAAmB,IAEpE,IAAe,EAA+B,UACvD,GAAe,EAAc,CAEtB,CACH,IAAM,GAAsD,CACxD,IAAM,EAAS,EAAc,SAAS,EAAa,IAGnD,OAFI,EAAe,QAAQ,QAAQ,EAAO,CAEnC,IAAI,QAAS,GAAY,CAC5B,EAAc,QAAQ,GAAkB,EAAa,GAAG,KAAQ,CAC5D,EAAQ,EAAc,SAAS,EAAa,IAAI,EAClD,EACJ,EAGN,KAAO,GAAuC,CAC1C,IAAM,EAAc,EAAc,UAAU,IAAI,GAChD,EAAc,SAAS,GAAe,EACtC,EAAc,YAAY,GAAkB,EAAY,CAAC,EAEhE,EC5CQ,GAAkB,GAA2B,CACtD,GAAqB,EAAQ,CAC7B,EAAK,EAAS,uBAAuB,CACrC,GAAqB,EAAQ,EAG3B,GAAuB,MAAO,CAAE,YAAW,oBAA6C,CAC1F,EAAK,EAAS,uBAAuB,CACrC,GAAI,CACA,EAAkB,CAAE,UAAW,EAAgB,aAAc,KAAM,MAAO,KAAM,CAAC,CACjF,EAAW,CAAE,WAAY,cAAe,UAAW,EAAgB,CAAC,CACpE,GAAiB,EAAe,CAEhC,IAAM,EAAgB,EAAU,QAAQ,CAExC,GAAiB,CACb,SAAU,SAAY,CAClB,EAAU,yBAAyB,CACnC,EAAkB,CAAE,UAAW,EAAgB,aAAc,KAAM,MAAO,KAAM,CAAC,CACjF,EAAW,CAAE,WAAY,YAAa,UAAW,EAAgB,CAAC,CAClE,MAAM,EACN,EAAK,EAAS,iBAAiB,CAC/B,EAAkB,CAAE,UAAW,EAAgB,aAAc,KAAM,MAAO,KAAM,CAAC,CACjF,EAAW,CAAE,WAAY,aAAc,UAAW,EAAgB,CAAC,CACnE,EAAU,OAAO,EAErB,UAAW,EACX,YAAa,EAAe,gBAC5B,aAAc,EAAU,IACxB,SAAU,EAAe,SAC5B,CAAC,OACG,EAAO,CACZ,EAAkB,CAAE,UAAW,EAAgB,CAAC,CAChD,EAAa,CAAE,QAAS,6BAA8B,QAAO,UAAW,EAAgB,CAAC,GAI3F,IAAwB,CAAE,YAAW,oBAAoC,CAC3E,IAAa,CAAC,KAAK,CACf,mBAAoB,YAAY,KAAK,CAC1B,YACK,iBACnB,CAAC,EC/CO,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,GAAgD,CACtE,EAAc,IAAI,EAAU,kBAAkB,GAClD,EAAc,KAAK,EAAU,kBAAkB,CAC/C,EAAW,CAAE,WAAY,gCAAiC,YAAW,CAAC,GAGpE,GAAkB,GACpB,SAAS,eAAe,EAAe,YAAY,CACjD,GAAkB,GACpB,EAAa,UAAY,KAAO,EAAa,UAAY,MCEhD,GAAb,KAAoD,CAChD,MAAM,cAAc,EAAmB,EAAkC,CACrE,IAAM,EAAe,GAAgB,EAAW,EAAS,GAA8B,CACvF,GAAqB,IAAI,EAAa,CACtC,IAAM,EAAiB,MAAM,GAAa,EAAa,CACvD,GAAI,CACA,GAAc,EAAe,OACxB,EAAK,CACV,EAAa,CACT,QAAS,wCAAwC,GAAe,EAAU,CAAC,GAC3E,MAAO,EACP,UAAW,EACd,CAAC,EAIV,MAAM,UAAU,EAAmB,EAAkC,CAEjE,IAAM,EAAe,GAAgB,EAAW,EAAS,GAAwB,CAC3E,EAAiB,MAAM,GAAa,EAAa,CACvD,GAAI,CACA,GAAU,EAAa,cAAe,GAAG,OACpC,EAAK,CACV,EAAa,CACT,QAAS,oCAAoC,GAAe,EAAU,CAAC,GACvE,MAAO,EACP,UAAW,EACd,CAAC,IAKR,GAAe,KAAO,KACT,MAAM,IAAa,CAAC,IAAI,EAAa,EACtC,eAKZ,IACF,EACA,EACA,IACc,OACd,IAAM,GAAA,EACF,GAAA,KAAW,SAAS,eAAe,EAAU,CAA7C,IAA6C,KAAI,EAAgB,GAA4B,EAAU,CAAC,CAA3D,EAEjD,GAAI,CAAC,EACD,MAAU,MAAM,YAAY,EAAU,iBAAiB,CAG3D,GAAI,EAAM,UAAU,SAAS,gBAAgB,CACzC,OAAO,EAGX,IAAM,EAAe,EAAM,QAAQ,iBAAiB,CAEpD,GAAI,CAAC,EACD,MAAU,MAAM,uCAAuC,EAAU,GAAG,CAGxE,OAAO,GAUL,GAA+B,GACjC,MAAM,KACF,SAAS,iBAA8B,uEAAuE,CACjH,CAAC,OAAQ,GAAiB,OAAO,EAAa,cAAe,QAAQ,cAAc,cAAgB,EAAU,CAE5G,GAAuB,IAAI,QAQ3B,GAAkD,GACpD,kBAAQ,KAAM,GAAU,CAAC,GAAqB,IAAI,EAAM,CAAC,GAAA,KAAI,EAAQ,GAAZ,GAOvD,GAA4C,GAAY,SAC1D,IAAM,GAAA,EAAS,OAAO,QAAA,KAAA,IAAA,GAAA,EAAO,OAC7B,OAAA,EAAO,EAAQ,KAAM,GAAU,aAAkB,MAAQ,EAAM,SAAS,EAAO,CAAC,GAAA,KAAI,EAAQ,GAAZ,GAO9E,GAAkB,GAA0B,EAAM,QAAQ,UAAW,GAAG,CCzHjE,GAAb,KAAuB,CACnB,YACI,EACA,EACA,EACA,EACA,EACA,EACF,YANkB,KAAA,GAAA,EACA,KAAA,KAAA,EACA,KAAA,MAAA,EACA,KAAA,SAAA,EACA,KAAA,WAAA,EACA,KAAA,eAAA,cAGX,SAA2B,CAChC,MAAM,EAAK,SAAS,OAAO,EAAK,mCAGE,CAClC,KAAK,SAAS,wBAAwB,KAAK,iBAG3B,CAChB,KAAK,SAAS,MAAM,KAAK,EAG7B,IAAW,KAAsB,CAC7B,OAAO,GAAa,KAAK,eAAgB,CACrC,aAAc,WACd,kBAAmB,KAAK,MAC3B,CAAC,GCxBG,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,IAA6B,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,GCxBE,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,2CA8FY,CACrC,KAAK,eACL,KAAK,WAAW,sCAAsC,kBAIhD,GAA4C,CACjD,KAAK,cAAc,IAAI,EAAW,GACnC,EAAW,CAAE,aAAY,UAAW,KAAK,UAAW,CAAC,CACrD,KAAK,cAAc,IAAI,EAAW,GA5F1C,qBAAqB,EAAgC,EAAsB,CACvE,EAAS,UAAU,EAAU,IAAI,CACjC,aAAa,KAAK,mBAAmB,CACrC,cAAc,KAAK,2BAA2B,CAC9C,KAAK,wBAAwB,iCAAiC,CAC9D,KAAK,gCAAgC,CACrC,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,CAAE,QAAA,GAAA,KAAA,IAAA,GAAS,EAAO,QAAS,QAAO,UAAW,KAAK,UAAW,CAAC,CAC3E,cAAc,KAAK,2BAA2B,GAf3B,IAiBb,CAGlB,MAAM,EAA4B,CAC9B,GAA0B,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,GCtGG,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,CCfK,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,EChB3D,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,CCRxG,GAA8B,CAAE,UAAW,GAAM,KAAM,UAAW,CAClE,GAAc,SACd,GAAW,MACX,GAAqC,iCAc9B,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,6CA+BsC,CACvD,GAAI,KAAK,UAAU,OAAO,MAAQ,KAAM,MAAO,GAE/C,IAAM,EAAiB,KAAK,UAC5B,OACI,KAAK,gBAAgB,aAAe,GAAsB,YAC1D,EAAe,WAAa,IAC5B,EAAe,WAAa,IAC5B,EAAQ,EAAe,0BAQd,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,GAjDX,MAAa,KAAK,EAAqC,YAC/C,MAAc,EAAU,IAAK,EAAK,gBAAgB,WAAW,CACjE,GAAe,EAAU,IAAK,EAAK,gBAAgB,WAAW,CAC9D,GAAI,CACA,IAAM,EAAW,EAAK,iBAAiB,EAAK,IAAK,EAAU,CACrD,EAAU,YAAY,KAAK,CAC3B,EAAU,MAAM,EAAU,GAAe,CAC/C,EAAwB,CACpB,WAAY,GAAG,EAAK,gBAAgB,WAAW,SAC/C,YAAa,EACb,UAAW,EAAK,UACnB,CAAC,CACF,MAAM,QACD,EAAG,CAGR,MAFA,EAAe,EAAU,IAAK,EAAK,gBAAgB,WAAW,CAC9D,EAAW,CAAE,WAAY,GAAG,EAAK,gBAAgB,WAAW,QAAS,UAAW,EAAK,UAAW,CAAC,CAC3F,EAEV,EAAU,IAAI,YAAY,EAAK,MAAM,EAAU,CAAC,CAChD,EAAW,CAAE,WAAY,EAAK,gBAAgB,WAAY,UAAW,EAAK,UAAW,CAAC,CAClF,EAAK,mCAAmC,EACxC,EAAW,CAAE,WAAY,GAAoC,UAAW,EAAK,UAAW,CAAC,CAI7F,EAAK,OAAO,QAAS,GAAU,MAAM,EAAO,GAAe,CAAC,ICvDvD,GAAkC,GAAoC,CAC/E,IAAM,EAAe,OAAO,aAAe,SAAS,gBAAgB,aAC9D,EAAc,OAAO,YAAc,SAAS,gBAAgB,YAE5D,EAAc,CAChB,IAAK,KAAK,IAAI,EAAG,EAAe,IAAI,CACpC,KAAM,KAAK,IAAI,EAAG,EAAe,KAAK,CACtC,OAAQ,KAAK,IAAI,EAAc,EAAe,OAAO,CACrD,MAAO,KAAK,IAAI,EAAa,EAAe,MAAM,CACrD,CAgBD,OAbI,EAAe,KAAO,GACtB,EAAe,MAAQ,GACvB,EAAe,QAAU,GACzB,EAAe,OAAS,GACxB,EAAe,OAAS,GACxB,EAAe,QAAU,EAElB,GAGU,EAAY,MAAQ,EAAY,OAAS,EAAY,OAAS,EAAY,MAC7E,EAAe,MAAQ,EAAe,SCpB/C,GACT,EACA,IACqB,CACrB,IAAM,EAA6B,IAAI,IAEjC,EAAc,GAA4C,CACvD,EAAc,IAAI,EAAW,GAC9B,EAAW,CAAE,aAAY,YAAW,CAAC,CACrC,EAAc,IAAI,EAAW,GAI/B,GAA2B,EAAsB,IAA+B,CAClF,IAAM,EAAmB,EAAU,IAAI,uBAAuB,CAOxD,EAN8B,GAA+B,EAAiB,CACtD,EAA4B,yBAAyB,CAC/E,QAAS,EAAU,IACnB,uBAAwB,EAC3B,CAAC,CAEoF,EAItF,OAHI,GACA,EAAW,4BAA4B,CAEpC,GAGX,MAAO,CACH,wBAAwB,EAAsB,EAA4B,CACtE,OAAO,EAAwB,EAAW,EAAU,EAExD,SAAgB,CACZ,EAA4B,SAAS,EAE5C,EC/BQ,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,YAC5C,GAAI,EAAc,EAAU,IAAK,EAAY,CACzC,OAEJ,EAAe,EAAU,IAAK,EAAY,CAC1C,IAAM,EAAU,YAAY,KAAK,CACjC,GAAI,CACA,GAAgC,EAAK,UAAU,YAAa,OACvD,EAAG,CAER,MADA,EAAe,EAAU,IAAK,EAAY,CACpC,EAEV,EAAwB,CACpB,WAAY,GAAG,EAAY,SAC3B,YAAa,EACb,UAAW,EAAK,UACnB,CAAC,CACF,EAAW,CAAE,WAAY,EAAa,UAAW,EAAK,UAAW,CAAC,GCtBpE,EAAc,kBAEP,GAAb,KAAgD,CAC5C,YAAY,EAAwD,CAAvC,KAAA,UAAA,EAE7B,MAAM,KAAK,EAAqC,YAC5C,GAAI,EAAc,EAAU,IAAK,EAAY,CACzC,OAEJ,EAAe,EAAU,IAAK,EAAY,CAC1C,IAAM,EAAU,YAAY,KAAK,CACjC,GAAI,CACA,GAA8B,EAAK,UAAU,YAAa,OACrD,EAAG,CAER,MADA,EAAe,EAAU,IAAK,EAAY,CACpC,EAEV,EAAwB,CACpB,WAAY,GAAG,EAAY,SAC3B,YAAa,EACb,UAAW,EAAK,UACnB,CAAC,CACF,EAAW,CAAE,WAAY,EAAa,UAAW,EAAK,UAAW,CAAC,GC3B7D,GAAe,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,ECMlB,GAA2B,GAC/B,GAIE,EAAI,MAAM,oBAAoB,CAAC,KAAK,GAAG,CC3CrC,GAAyB,aAEzB,GAA0C,GAEnD,GAAuB,GAAwB,EAAI,CAAA,IAAgB,CAC/D,kBAAmB,GACtB,CAAC,CCVO,GAAiD,GAAwB,ECGzE,IAAoD,EAAa,IAA8B,CACxG,IAAM,EAAa,CAAE,IAAK,GAAW,EAAO,IAAI,CAAE,CAC5C,EAAoB,mBAAmB,KAAK,UAAU,EAAW,CAAC,CACxE,OAAO,EAAI,QAAQ,GAAA,MAA0B,CAAC,QAAQ,GAAiB,EAAkB,ECNhF,EAAM,CACf,KAAM,EAAsB,IAAyB,CACjD,EAAU,IAAI,QAAQ,MAAQ,OAAO,EAAM,EAE/C,IAAM,GACK,EAAU,IAAI,QAAQ,QAAU,OAE9C,CCUY,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,EAAI,QAAQ,GAAA,IAAiC,CAAC,QAAQ,GAAiB,EAAkB,GCzB3F,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,CCjBY,GACT,EACA,EACA,EACA,EACA,IACY,CAMZ,IAAM,EAAS,GAA+B,CAC1C,IAAI,EAEE,EAAe,CAAE,cAAe,GAAO,CAE7C,GAA0B,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,CAI7B,IAAU,EAAI,EAAa,EAAU,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,CAAE,QAAA,GAAA,KAAA,IAAA,GAAS,EAAO,QAAS,QAAO,YAAW,CAAC,CACpD,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,CAK7G,GAA0B,GAAgD,CAC5E,EAAW,CAAE,WAAY,sCAAuC,YAAW,CAAC,ECvHnE,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,CAAE,EAAU,CACxE,EAAY,CAAC,EAAU,CAAG,EAAE,CAC5B,EACH,CAEM,IAAI,GACP,EACA,EACA,IAA8B,CAC9B,EAAyB,GAAmC,CAAE,EAAU,CACxE,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,CAAE,EAAU,CACxE,IAAA,GACA,EACH,EC9EI,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,EC1EA,GAAc,CAAC,WAAY,WAAW,CAGtC,GAAc,KAEd,GAAgB,GAAqC,GAAY,KAAM,GAAQ,EAAM,UAAU,SAAS,EAAI,CAAC,CAE7G,GAAkB,GAAuD,CAC3E,IAAM,EAAQ,EAAa,cAAgC,QAAQ,CAGnE,MAFI,CAAC,GACD,GAAa,EAAM,EAAI,CAAC,EAAM,IAAY,KACvC,GAGE,EAAW,KAAO,IAAyD,CACpF,IAAM,EAAW,GAAe,EAAa,CAC7C,GAAI,EAAU,OAAO,EAErB,IAAI,EAAiC,KACrC,GAAI,CACA,MAAM,GAAwB,CAC1B,eACI,EAAQ,GAAe,EAAa,CAC7B,IAAU,MAErB,OAAQ,SAAY,GACpB,UAAW,GACd,CAAC,OACG,EAAG,CACR,IAAM,EAAQ,EACd,MAAU,MAAM,oCAAoC,EAAa,GAAG,IAAI,EAAM,UAAU,CAE5F,OAAO,GCLE,GAAuC,KAAO,IAAsD,CAC7G,IAAM,EAAQ,MAAM,EAAS,EAAQ,CAEjC,EAAoB,EACpB,EAAqB,EAiBzB,OAfA,EAAM,iBAAiB,WAAc,CACjC,EAAqB,EACrB,EAAoB,YAAY,KAAK,EACvC,CAEF,EAAM,iBAAiB,YAAgB,EAAqB,EAAG,CAE/D,EAAM,iBAAiB,YAAgB,EAAqB,EAAG,CAE/D,EAAM,iBAAiB,iBAAoB,CAClC,EAAM,SACP,EAAqB,YAAY,KAAK,CAAG,IAE/C,CAEK,CACH,iBAA2B,CACvB,OAAO,GAAsB,KAEpC,ECtDQ,GAAM,CACf,KAAM,EAAsB,IAAyB,CACjD,EAAQ,QAAQ,MAAQ,OAAO,EAAM,EAEzC,IAAM,GACK,EAAQ,QAAQ,QAAU,OAExC,CCkBY,GAAiC,GACtC,GAAI,IAAI,EAAkB,CACnB,CAAE,QAAS,GAAM,KAAM,kBAAmB,CAM9C,GAHQ,MAAM,KAAK,EAAkB,iBAAiB,MAAM,CAAC,CAAC,OAChE,GAAM,iBAAiB,EAAE,CAAC,UAAY,OAC1C,CACoC,CAcnC,GAA0B,GACxB,EAAO,SAAW,EACX,CAAE,QAAS,GAAO,KAAM,cAAe,CAG3C,EAAO,KAAM,GAAQ,EAAI,UAAY,EAAI,aAAe,GAAK,EAAI,cAAgB,EAAE,CACpF,CAAE,QAAS,GAAM,KAAM,kBAAmB,CAC1C,CAAE,QAAS,GAAO,KAAM,QAAS,CC/C9B,GAAuB,MAAO,EAAuB,SAAS,OAA2B,CAClG,IACI,EAAc,EAUlB,OAJI,GAA8B,EAAQ,CAAC,QAChC,GAGJ,IAAI,QAAkB,GAAY,CACrC,IAAM,EAAa,gBAAkB,CACjC,GAAe,EAEE,GAA8B,EAAQ,CAC1C,SACT,cAAc,EAAW,CACzB,EAAQ,GAAK,EACN,GAAe,KACtB,cAAc,EAAW,CACzB,EAAQ,GAAM,GAEnB,EAAW,EAChB,ECZA,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,ECpFxC,GAAsB,WAKf,GAAyB,GAAwC,SAC1E,IAAM,EAAW,GAAG,EAAe,gBAC7B,EAAU,SAAS,eAAe,EAAS,CACjD,OAAA,EAAA,GAAA,OAAA,EAAO,EAAS,eAAA,KAAA,IAAA,GAAA,EAAA,KAAA,EAAe,GAAoB,GAAA,KAAI,GAAJ,GCRjD,GAAsB,iBA6Gf,IAAiB,EAAsB,IAC5C,IAAiB,IAAuB,EAAa,MAAM,GAAK,GACzD,EAQJ,EAAI,QALmB,kBACN,GACb,EAAa,MAAM,CAAC,QAAQ,2BAA4B,GAAG,EAGb,EAAa,CAAC,CClH9D,GAA8C,KAAO,IAAwC,CACtG,IAAM,EAAqB,GAAsB,EAAU,IAAI,GAAG,CAC7D,KAEL,IAAK,IAAM,KAAK,EAAU,IAAI,iBAAiB,IAAI,CAC/C,EAAE,KAAO,GAAc,EAAoB,EAAE,KAAK,ECG7C,IACT,EACA,EACA,EACA,IACW,CACX,IAAI,EAAS,GAEb,MAAO,CACH,MAAM,OAAO,EAAqC,CAC9C,EAAS,MAAO,IAA6B,CAAC,GAAG,KAAK,CAChD,GAAsB,EAAU,IAAI,CACpC,GAAqB,EAAU,IAAI,EAEpC,IAA6B,CAAC,eAAe,EAC9C,GAA4C,EAAU,EAI9D,wBAAwB,EAA4B,CAChD,GAAkB,EAAW,EAAQ,EAAY,EAGrD,MAAM,EAA4B,CAC9B,GAAgB,EAAW,EAAQ,EAAQ,EAAa,EAAU,CAClE,GAAiB,EAAW,EAAO,EAE1C,EAGC,IAAqB,EAAsB,EAAgB,IAA8B,CACvF,GAA4B,EAAY,EAGxC,EAAO,gBAAgB,KAAK,EAAU,EAIjC,IACT,EACA,EACA,EACA,EACA,IACO,OACP,EAAI,IAAI,EAAW,EAAM,CACzB,IAAM,EAA8B,GAAmC,CACvE,GAAI,GAA4B,EAAY,CAAE,CAC1C,GACI,EACA,CACI,gBAAiB,EAAO,gBACxB,SAAU,EAAO,SACjB,mBAAoB,EAAO,mBAC9B,CACD,EAAyB,EAA6B,EAAU,CAChE,EACH,CACD,OAGJ,GAAI,EAAI,IAAI,EAAU,CAAE,QACpB,EAAA,EAAO,WAAA,MAAA,EAAU,KAAK,EAAU,CAEpC,EAAO,mBAAmB,KAAK,EAAU,EACzC,EAAA,EAAO,sBAAA,MAAA,EAAqB,KAAK,EAAU,CAAC,SAAW,kBAAO,oBAAA,KAAA,IAAA,GAAA,EAAmB,MAAM,EAAU,EAAC,EAGhG,IAAoB,EAAsB,IAAyB,CACrE,EAAO,aAAa,MAAM,EAAU,EAMlC,GAAwB,KAAO,IACjC,GAAqB,GAAuB,EAAQ,CAAC,CAMnD,GAA0B,GAExB,EAAQ,WAGD,EAAQ,WAGZ,EC1FL,EAA0B,uBAEnB,MAA6B,QACtC,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,EAAwB,CAAC,QAAS,GAAmC,CAChF,EAAY,OAAO,EACrB,EAGO,OAA8B,QACvC,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,EAAwB,CAAC,QAAS,GAAmC,CAChF,EAAY,QAAQ,EACtB,EAGO,IAAwB,EAAc,IAA+B,QAC9E,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,EAAwB,CAAC,QAAS,GAAmC,CAChF,EAAY,YAAY,EAAM,EAAS,EACzC,EC5BO,GAAoB,GAAkC,CAC/D,GAAqB,mBAAuB,EAAM,YAAc,EAAG,CAG9D,EAAM,QACP,GAAgB,CAEpB,EAAM,iBAAiB,WAAc,GAAgB,CAAC,CACtD,EAAM,iBAAiB,iBAAoB,CAClC,EAAM,QAAQ,GAAgB,EACrC,CAGF,EAAM,iBAAiB,YAAe,IAAiB,CAAC,CAGxD,EAAM,iBAAiB,YAAe,IAAiB,CAAC,EClB/C,IAAgC,EAAwB,IAAkC,OACnG,GACI,GAAA,EACA,EAAW,EAAgB,OAAO,GAAA,KAAI,EAAW,EAAgB,SAAS,CAAxC,EAClC,EAAW,EAAgB,QAAQ,CACtC,CACD,GAAkB,EAAO,EAAW,EAAgB,QAAQ,CAAE,EAAW,EAAgB,QAAQ,CAAC,CAClG,GAAgB,EAAW,EAAgB,QAAQ,CAAE,EAAW,EAAgB,SAAS,CAAC,EAGxF,IACF,EACA,EACA,IACO,CACP,EAAM,OACA,EAAiB,EAAmB,EAAa,CACjD,EAAiB,EAAc,EAAkB,CACvD,EAAM,iBAAiB,WAAc,EAAiB,EAAc,EAAkB,CAAC,CACvF,EAAM,iBAAiB,YAAe,EAAiB,EAAmB,EAAa,CAAC,CACxF,EAAM,iBAAiB,YAAe,EAAiB,EAAmB,EAAa,CAAC,EAGtF,IACF,EACA,EACA,IACO,CACP,EAAM,MAAQ,EAAiB,EAAc,EAAa,CAAG,EAAiB,EAAc,EAAa,CACzG,EAAM,iBAAiB,WAAc,EAAiB,EAAc,EAAa,CAAC,CAClF,EAAM,iBAAiB,aAAgB,EAAiB,EAAc,EAAa,CAAC,EAGlF,IAAmB,EAAqC,IAA+C,CACzG,EAAiB,EAAiB,EAAiB,CACnD,GAAA,MAAA,EAAiB,iBAAiB,YAAe,EAAiB,EAAkB,EAAgB,CAAC,CACrG,GAAA,MAAA,EAAkB,iBAAiB,YAAe,EAAiB,EAAiB,EAAiB,CAAC,EAGpG,GAAQ,GAAA,GAAA,KAAA,IAAA,GAA2B,EAAI,MAAM,YAAY,UAAW,OAAO,CAC3E,GAAQ,GAAA,GAAA,KAAA,IAAA,GAA2B,EAAI,MAAM,eAAe,UAAU,CACtE,GAAoB,EAA4B,IAAqC,CACvF,GAAK,EAAO,CACZ,GAAK,EAAO,EAGV,GAAiB,eACjB,GAAc,EAAY,IAAmB,SAAS,eAAe,GAAG,IAAK,KAAiB,IAAS,CCzCvG,GAAmB,EAEnB,GAAmB,EAEnB,GAA2B,GAG3B,GAAsB,CAAC,QAAS,QAAS,QAAS,UAAU,CAcrD,IACT,EACA,EACA,IACO,CACP,EAAW,CACP,WAAY,gCACZ,YAAa,EAAQ,SAAS,CAC9B,YACA,qBAAsB,CAClB,WAAY,OAAO,EAAM,WAAW,CACpC,aAAc,OAAO,EAAM,aAAa,CAC3C,CACJ,CAAC,CAEF,EAAiB,EAAO,EAAW,EAAS,CACxC,WAAY,iCACZ,MAAO,UACP,eAAgB,EAAM,YAAc,GACvC,CAAC,CACF,EAAiB,EAAO,EAAW,EAAS,CACxC,WAAY,wCACZ,MAAO,iBACP,eAAgB,EAAM,YAAc,GACvC,CAAC,CACF,EAAiB,EAAO,EAAW,EAAS,CACxC,WAAY,iCACZ,MAAO,UACP,eAAgB,EAAM,YAAc,EACvC,CAAC,CAEF,GAAmB,EAAO,EAAU,EAYlC,GACF,EACA,EACA,EACA,CAAE,aAAY,QAAO,oBACd,CACP,IAAM,MAAa,EAAW,CAAE,aAAY,YAAa,EAAQ,SAAS,CAAE,YAAW,CAAC,CAExF,GAAI,EAAgB,CAChB,GAAM,CACN,OAGJ,EAAM,iBAAiB,EAAO,EAAM,CAAE,KAAM,GAAM,CAAC,EASjD,IAAsB,EAAyB,IAAgD,CACjG,IAAI,EAAY,EAAM,YAAc,EAChC,EAAsC,KACtC,EAAgB,EAEpB,EAAM,iBAAiB,cAAkB,EAAY,GAAM,CAE3D,EAAM,iBAAiB,cAAiB,CAChC,CAAC,GAAa,GAAgB,EAAM,UAExC,EAAe,GAAsB,CACrC,EAAgB,EAAM,YACtB,EAAW,CAAE,WAAY,6BAA8B,YAAa,EAAG,YAAW,CAAC,GACrF,CAEF,EAAM,iBAAiB,iBAAoB,CAEnC,CAAC,GAAgB,EAAM,aAAe,EAAgB,KAE1D,EAAW,CAAE,WAAY,gCAAiC,YAAa,EAAa,SAAS,CAAE,YAAW,CAAC,CAC3G,EAAe,OACjB,CAEF,IAAK,IAAM,KAAS,GAChB,EAAM,iBAAiB,MAAc,EAAe,KAAM,EC/F5D,EAA2B,wBAEpB,IACT,EACA,EACA,EACA,IACO,QACP,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,EAAyB,CAAC,QAAS,GAA6C,CAC3F,GAAI,CACA,EAAoB,UAAU,EAAS,EAAU,EAAQ,OACpD,EAAO,CACZ,EAAa,CACT,QACA,QAAS,4CACT,YACH,CAAC,GAER,EAGO,GAAS,GAA+B,GAAc,EAAQ,CAE9D,OAAsB,IAAe,CAE5C,GAAiB,GAAgC,QACnD,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,EAAyB,CAAC,QAAS,GAA6C,CAC3F,EAAoB,MAAM,EAAQ,EACpC,EC7CO,EAAmB,IAAI,IAE9B,IAAgC,EAAyB,IAAgD,CAC3G,GACI,EACC,GAAa,CACN,GAAY,EAAM,QAAU,CAAC,EAAiB,IAAI,EAAM,GAAG,CAC3D,EAAM,MAAM,CACL,CAAC,GAAY,CAAC,EAAM,QAC3B,EAAM,OAAO,EAGrB,EACA,CACI,SAAU,IACb,CACJ,EAGC,GAAoB,GAA4B,CAClD,EAAiB,IAAI,EAAM,GAAG,CAC9B,IAAS,EAGA,IAA0B,EAAyB,IAAgD,CAC5G,GAA6B,EAAO,EAAU,CAC9C,EAAM,iBAAiB,gBAAmB,CACtC,EAAiB,OAAO,EAAM,GAAG,CACjC,GAAM,EAAM,EACd,CACF,EAAM,iBAAiB,iBAAoB,GAAiB,EAAM,CAAC,CACnE,EAAM,iBAAiB,YAAe,GAAiB,EAAM,CAAC,ECnCrD,GAAuB,MAAO,EAAwB,IAA2C,CAC1G,MAAM,IAA+B,CAEhC,EAAM,QACP,EAAU,cAAc,EAAY,EAAW,wBAAwB,CAAC,CAG5E,EAAM,iBAAiB,WAAc,EAAU,cAAc,EAAY,EAAW,wBAAwB,CAAC,CAAC,CAC9G,EAAM,iBAAiB,YAAe,EAAU,cAAc,EAAY,EAAW,sBAAsB,CAAC,CAAC,CAC7G,EAAM,iBAAiB,YAAe,EAAU,cAAc,EAAY,EAAW,sBAAsB,CAAC,CAAC,EAG3G,GAAe,EAAwB,IACzC,IAAI,YAAY,EAAW,CACvB,QAAS,GACT,OAAQ,CACJ,kBAAmB,EAAU,GAChC,CACJ,CAAC,CAEA,GAAgC,SAC3B,IAAI,QAAe,GAAY,QAClC,EAAA,OAAO,IAAA,MAAA,EAAG,KAAK,kCAAkC,CAAC,YAAc,CAC5D,GAAS,EACX,EACJ,CCjBA,GAAsB,mCACtB,GAAiB,OACjB,GAAgB,SAChB,GAAkC,IAE3B,GAAY,GAAgB,CACjC,GAAoB,KAAK,EAAI,CAC7B,eAAiB,CACb,OAAO,KAAK,EAAK,GAAe,EACjC,GAAgC,CAEnC,OAAO,KAAK,EAAK,GAAc,ECH1B,EAAc,CACvB,SAAU,WACV,QAAS,UACT,mBAAoB,SACvB,CAEK,GAAc,IAAI,IAEX,IACT,EACA,EACA,EACA,EACA,EAA4B,KACjB,CACX,IAAM,EAAmB,GACd,IAAI,SAAS,EAAS,IAAW,CACpC,EAAM,iBAAiB,qBAAwB,GAAS,CAAC,CACzD,EAAM,iBAAiB,QAAU,GAAM,EAAO,EAAE,CAAC,CAC7C,EAAM,YAAc,GAAG,GAAS,EACtC,CAGN,MAAO,CACH,MAAM,OAAO,EAAqC,CAC9C,IAAM,EAAQ,MAAM,EAAS,EAAU,IAAI,CAC3C,GAAsB,EAAO,EAAW,EAAY,CAChD,IACA,GAAmB,EAAM,CACzB,GAAiB,EAAM,CACvB,GAAqB,EAAU,IAAK,EAAM,CAC1C,GAAuB,EAAO,EAAU,CACxC,GAA6B,EAAU,IAAI,GAAI,EAAM,CACrD,GAAyB,EAAU,IAAI,GAAI,EAAM,EAErD,MAAM,EAAgB,EAAM,EAGhC,wBAAwB,EAAoB,GAE5C,MAAM,MAAM,EAAqC,CAC7C,IAAM,EAAQ,MAAM,EAAS,EAAU,IAAI,CAC3C,GAAgB,EAAO,EAAW,EAAQ,EAAe,CACzD,GAAiB,EAAQ,EAAU,CACnC,GAAgB,EAAO,EAAW,EAAgB,EAAiB,EAE1E,EAGC,GAAsB,GAAkC,CAC1D,EAAM,iBAAiB,YAAgB,EAAM,YAAc,EAAG,EAI5D,IAAmB,EAAa,IAAyB,CAC3D,EAAQ,YAAc,EAAI,KAC1B,EAAQ,MAAM,eAAe,UAAU,EAGrC,GAAoB,GAAyB,CAC/C,EAAQ,YAAc,GACtB,EAAQ,MAAM,YAAY,UAAW,OAAO,EAG1C,IAAmB,EAAkB,IAAyB,CAChE,IAAM,EAAM,EAAM,YAAe,EAAM,WAAW,GAClD,GAAA,MAAI,EAAK,KAEL,GAAgB,EAAK,EAAQ,CAG7B,GAAiB,EAAQ,EAI3B,GAAgB,GAAqB,EAAM,OAAS,EAAY,SAChE,GAAe,GAAqB,EAAM,OAAS,EAAY,mBAE/D,IAA4B,EAAwB,IAA4B,CAClF,IAAM,EAAY,SAAS,eAAe,GAAG,EAAe,gBAAgB,CAG5E,GAAI,GAAa,EAAM,YAAc,EAAM,WAAW,OAAS,EAAG,CAC9D,IAAM,EAAQ,EAAM,WAAW,GAG/B,EAAM,KAAO,EAAY,SAGzB,EAAM,iBAAiB,iBAAoB,CACvC,IAAM,MAAyB,GAAgB,EAAO,EAAU,CAE5D,GAAa,EAAM,EACnB,GAAiB,EAAU,CAC3B,EAAM,oBAAoB,YAAa,EAAiB,EACjD,GAAY,EAAM,GACzB,GAAgB,EAAO,EAAU,CACjC,EAAM,iBAAiB,YAAa,EAAiB,GAE3D,GAIJ,IACF,EACA,EACA,EACA,IACO,CACP,GAAI,EAAM,OACN,EAAM,iBACF,cACM,OACF,EAAI,IAAI,EAAW,GAAK,CACxB,EAAO,gBAAgB,KAAK,EAAU,EACtC,EAAA,EAAO,WAAA,MAAA,EAAU,KAAK,EAAU,CAChC,EAAO,mBAAmB,KAAK,EAAU,CACzC,EAAW,EAAe,YAAY,EAE1C,CAAE,KAAM,GAAM,CACjB,KACE,OACH,EAAI,IAAI,EAAW,GAAK,CACxB,EAAO,gBAAgB,KAAK,EAAU,EACtC,EAAA,EAAO,WAAA,MAAA,EAAU,KAAK,EAAU,CAChC,EAAO,mBAAmB,KAAK,EAAU,CACzC,EAAW,EAAe,YAAY,GAIxC,IAAoB,EAAgB,IAA+B,CACrE,EAAO,aAAa,MAAM,EAAU,EAGlC,GAAc,EAAyB,EAAe,IAA2B,CACnF,EAAM,iBAAiB,MAAa,EAAW,EAAO,CAAC,EAGrD,IACF,EACA,EACA,EACA,IACO,CACP,GAAgB,EAAO,EAAW,EAAe,CACjD,GAAgB,EAAO,EAAe,CACtC,GAAoB,EAAO,EAAe,CAC1C,EAAW,EAAO,QAAS,EAAe,SAAS,CACnD,EAAW,EAAO,QAAS,EAAe,MAAM,CAChD,GAAiB,EAAO,EAAe,CACvC,GAAiB,EAAO,EAAe,CACnC,GACA,EAAW,EAAO,OAAQ,EAAe,KAAK,CAC9C,EAAW,EAAO,SAAU,EAAe,OAAO,CAClD,GAAqB,EAAO,EAAe,EAE3C,GAAwB,EAAO,EAAe,EAIhD,GAAkB,MACpB,EACA,EACA,IACgB,CACZ,EAAM,OACN,EAAkB,CAAE,UAAW,EAAU,eAAgB,CAAC,CAC1D,EAAe,OAAS,EAAU,EAAe,MAAM,EAEvD,EAAM,iBAAiB,QAAS,SAAY,CACxC,EAAkB,CAAE,UAAW,EAAU,eAAgB,CAAC,CAC1D,EAAe,OAAS,EAAU,EAAe,MAAM,EACzD,EAIJ,IAAmB,EAAyB,IAAyC,CACnF,EAAM,OACN,EAAM,iBAAiB,WAAc,EAAW,EAAe,MAAM,CAAC,CAEtE,EAAW,EAAe,MAAM,EAIlC,IAAuB,EAAyB,IAAyC,CAC3F,EAAM,iBAAiB,iBAAoB,CACvC,IAAM,EAAW,EAAM,YAAc,EAAM,SACvC,GAAY,KAAM,EAAW,EAAe,cAAc,CAC1D,GAAY,IAAK,EAAW,EAAe,SAAS,CACpD,GAAY,KAAM,EAAW,EAAe,cAAc,EAChE,EAGA,IAAoB,EAAyB,IAAyC,CACxF,IAAI,EAAsB,GAC1B,EAAM,iBAAiB,iBAAoB,CACnC,EAAM,YAAc,GACpB,EAAW,EAAe,OAAO,CAErC,EAAsB,EAAM,aAC9B,EAGA,IAAoB,EAAyB,IAAyC,CACxF,IAAI,EAAW,GACf,EAAM,iBAAiB,YAAgB,EAAW,GAAM,CACxD,EAAM,iBAAiB,WAAc,GAAY,EAAW,EAAe,OAAO,CAAC,EAGjF,IAAwB,EAAyB,IAAyC,CAC5F,EAAM,iBAAiB,QAAU,GAAM,CACnC,EAAE,gBAAgB,CAClB,EAAW,EAAe,cAAc,CACxC,EAAe,cAAgB,GAAS,EAAe,aAAa,EACtE,EAGA,IAA2B,EAAyB,IAAyC,CAC/F,IAAI,EAAW,EAAM,MACrB,EAAM,iBAAiB,mBAAsB,CACrC,EAAM,QAAU,IACpB,EAAW,EAAM,MACjB,EAAW,EAAM,MAAQ,EAAe,KAAO,EAAe,OAAO,GACvE,EAGA,EAAa,KAAO,IAAuC,CAC7D,IAAK,IAAM,KAAY,EACnB,MAAM,EAAU,EAAS,EAI3B,EAAY,KAAO,IAAoC,CACrD,GAAY,IAAI,EAAS,GAI7B,GAAY,IAAI,EAAS,CAEzB,MAAM,MAAM,EAAU,CAClB,UAAW,GACX,KAAM,UACN,SAAU,MACb,CAAgB,GClPR,GAAiB,GAC1B,EAAe,cAAgB,GAAmB,EAAe,CAAG,GAAqB,EAAe,CAEtG,GAAuB,KAAO,IAChC,GACI,EAAe,kBACf,MAAM,GAAY,EAAe,CACjC,OAAO,EAAe,mBAAmB,YAAY,CACrD,EACH,CAEC,GAAqB,KAAO,IAAsD,OACpF,IAAM,EAAc,GAAsB,CACpC,EAAmB,EAAe,cACxC,OAAO,GACH,MAAM,GAAY,EAAe,CACjC,GAAoB,EAAiB,CACrC,EACA,GAAA,EACA,EAAiB,mBAAA,KAAoB,GAApB,EACpB,EAGC,GAAc,KAAO,IAAmC,CAC1D,IAAM,EAAc,SAAS,eAAe,EAAe,kBAAkB,CACvE,EAAY,EAAe,cAAgB,IAAM,IAEvD,MAAO,CACH,gBAAiB,GAAqB,EAAgB,EAAe,UAAU,CAC/E,mBAAoB,GAAwB,EAAe,CAC3D,aAAc,MAAM,GAAmB,EAAW,EAAa,MAJ7B,GAAqC,EAAY,CAIoB,CACvG,oBAAqB,GAAyB,EAAe,CAC7D,kBAAmB,GAAmB,EAAe,CACrD,SAAU,GAAc,EAAe,CAC1C,EAGC,GAAuB,GAAA,qCAAwD,CACjF,YAAa,EAAiB,YAC9B,MAAO,EAAiB,MACxB,OAAA,EAAO,EAAiB,eAAe,QAAA,KAAS,EAAE,CAAX,EACvC,eAAA,EAAe,EAAiB,eAAe,gBAAA,KAAiB,EAAE,CAAnB,EAC/C,UAAA,EAAU,EAAiB,eAAe,WAAA,KAAY,EAAE,CAAd,EAC1C,eAAA,EAAe,EAAiB,eAAe,gBAAA,KAAiB,EAAE,CAAnB,EAC/C,UAAA,EAAU,EAAiB,eAAe,WAAA,KAAY,EAAE,CAAd,EAC1C,MAAA,EAAM,EAAiB,eAAe,OAAA,KAAQ,EAAE,CAAV,EACtC,QAAA,EAAQ,EAAiB,eAAe,SAAA,KAAU,EAAE,CAAZ,EACxC,OAAA,EAAO,EAAiB,eAAe,QAAA,KAAS,EAAE,CAAX,EACvC,QAAA,EAAQ,EAAiB,eAAe,SAAA,KAAU,EAAE,CAAZ,EACxC,QAAA,EAAQ,EAAiB,eAAe,SAAA,KAAU,EAAE,CAAZ,EACxC,cAAA,EAAc,EAAiB,cAAA,KAAA,IAAA,GAAA,EAAa,aAC5C,eAAA,GAAA,EAAe,EAAiB,cAAA,KAAA,IAAA,GAAA,EAAa,gBAAA,KAAiB,EAAE,CAAnB,EAChD,EChEY,GAAiB,KAAO,IAC1B,IAAI,GACP,EAAe,YACf,EAAe,cACf,EAAe,kBACf,MAAM,GAAc,EAAe,CACnC,EAAe,WACf,EACH,CCRQ,GAAqB,KAAO,KAE9B,CACH,UAFc,MAAM,GAAe,EAAe,CAGlC,iBACnB,ECIQ,GAAb,KAA8C,CAC1C,MAAM,OAAO,EAAuC,YAChD,IAAM,EAAQ,MAAM,EAAgB,EAAe,CACnD,EAAM,YAAc,EACpB,MAAM,EAAK,KAAK,EAAe,CAGnC,MAAM,KAAK,EAAuC,CAC9C,IAAM,EAAQ,MAAM,EAAgB,EAAe,CACnD,EAAM,MAAM,CACZ,EAAM,cAAc,IAAI,YAAY,YAAY,CAAC,CAGrD,MAAM,MAAM,EAAuC,CAC/C,IAAM,EAAQ,MAAM,EAAgB,EAAe,CACnD,EAAM,OAAO,CACb,EAAM,cAAc,IAAI,YAAY,aAAa,CAAC,CAGtD,MAAM,KAAK,EAAuC,CAC9C,IAAM,EAAQ,MAAM,EAAgB,EAAe,CACnD,EAAM,MAAQ,GACd,EAAM,cAAc,IAAI,YAAY,OAAO,CAAC,CAGhD,MAAM,OAAO,EAAuC,CAChD,IAAM,EAAQ,MAAM,EAAgB,EAAe,CACnD,EAAM,MAAQ,GACd,EAAM,cAAc,IAAI,YAAY,SAAS,CAAC,CAQlD,MAAM,SAAS,EAAuC,OAClD,IAAM,EAAQ,MAAM,EAAgB,EAAe,CAC7C,EAAY,SAAS,eAAe,GAAG,EAAe,gBAAgB,CACtE,EAAA,GAAA,OAAA,EAAQ,EAAO,aAAA,KAAA,IAAA,GAAA,EAAa,GAE9B,CAAC,GAAS,CAAC,GAAa,CAAC,IAK7B,EAAM,KAAO,EAAY,mBACzB,EAAM,cAAc,IAAI,YAAY,aAAa,CAAC,EAOtD,MAAM,UAAU,EAAuC,OACnD,IAAM,EAAQ,MAAM,EAAgB,EAAe,CAC7C,EAAY,SAAS,eAAe,GAAG,EAAe,gBAAgB,CACtE,EAAA,GAAA,OAAA,EAAQ,EAAO,aAAA,KAAA,IAAA,GAAA,EAAa,GAE9B,CAAC,GAAS,CAAC,GAAa,CAAC,IAI7B,EAAM,KAAO,EAAY,SACzB,EAAM,cAAc,IAAI,YAAY,aAAa,CAAC,EAGtD,iBAAiB,EAA6B,EAAgC,CAC1E,EAAkB,QAAS,GAAY,QACnC,EAAA,SAAS,eAAe,EAAQ,GAAA,MAAA,EAAE,MAAM,eAAe,UAAU,EACnE,CACF,EAAe,QAAS,GAAY,QAChC,EAAA,SAAS,eAAe,EAAQ,GAAA,MAAA,EAAE,MAAM,YAAY,UAAW,OAAO,EACxE,GAIJ,EAAkB,KAAO,IAEpB,EADc,SAAS,eAAe,EAAe,CAC/B,CCzEpB,GAAb,KAAkD,yBAOvC,KAAO,IAAmC,CAC7C,IAAM,EAAgB,YAAY,KAAK,CACvC,EAAK,EAAS,OAAO,CACrB,EAAwB,CACpB,WAAY,sBACZ,YAAa,EACb,UAAW,EACd,CAAC,CACF,GAAI,CACA,GAAe,MAAM,GAAmB,EAAe,CAAC,OACnD,EAAK,CACV,EAAa,CAAE,QAAS,wBAAyB,MAAO,EAAK,UAAW,EAAgB,CAAC,iBAItF,IAAI,cAEP,IAAI,KC/BR,OAAO,SAIX,EAAK,EAAS,wBAAwB,CACtC,OAAO,OAAS,IAAI,GACpB,OAAO,cAAc,IAAI,YATW,2BAS0B,CAAC"}