{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/StormcloudVideoPlayer.cjs","../../src/ui/StormcloudVideoPlayer.tsx","../../src/sdk/hlsAdPlayer.ts","../../src/utils/devUrl.ts","../../src/sdk/pal.ts","../../src/utils/mqttClient.ts","../../src/utils/mqttConfig.ts","../../src/utils/vastEnvironmentSignals.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/vastMacros.ts","../../src/utils/browserCompat.ts","../../src/player/Scte35Parser.ts","../../src/player/Scte35CueManager.ts","../../src/player/AdConfigManager.ts","../../src/player/AdTimingService.ts","../../src/player/PlaceholderLayer.ts","../../src/player/HlsEngine.ts","../../src/player/PlayerControls.ts","../../src/player/AdBreakOrchestrator.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayerComponent","exports","import_react","require","import_hls","MAX_VAST_WRAPPER_DEPTH","createHlsAdPlayer","contentVideo","options","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","licenseKey","mainHlsInstance","adVideoElement","adHls","adContainerEl","currentAd","STALL_TIMEOUT_MS","lastAdProgressTime","podAds","podIndex","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","stallWatchdogId","lastAdProgressPosition","trackingFired","impression","start","midpoint","complete","set","event","Array","fn","payload","error","generateSessionId","Date","now","fireTrackingPixels","random","urls","toString","substr","forEach","url","trackingUrl","includes","level","levels","autoLevel","img","Image","src","console","log","warn","getMainStreamQuality","currentLevel","loadLevel","width","height","bitrate","selectBestMediaFile","mediaFiles","length","Error","firstFile","mainQuality","scoredFiles","map","file","widthDiff","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","sort","a","b","bestMatch","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","startsWith","endsWith","createEmptyTrackingUrls","firstQuartile","thirdQuartile","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","extractTrackingUrls","scope","trackingUrls","querySelectorAll","el","textContent","trim","push","getAttribute","eventKey","mergeTrackingUrls","source","keys","concat","parseVastXml","xmlString","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","adElement","adId","title","clickThrough","wrapperUri","vastAdTagUri","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","mf","index","bitrateAttr","bitrateValue","ad","id","parseAdElement","fetchVastXml","vastTagUrl","credentials","requestVast","response","creds","fetch","mode","headers","referrerPolicy","statusText","text","depth","accumulatedTracking","vastXml","parsed","substring","fetchAndParseVastAd","fetchAndParsePod","adElements","ads","resolved","aSeq","bSeq","aVal","Number","isFinite","MAX_SAFE_INTEGER","bVal","createAdVideoElement","video","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","muted","setupAdEventListeners","addEventListener","noteAdProgress","progress","currentTime","startStallWatchdog","handleAdComplete","e","advanceToNextPodAd","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","resetQuartileTracking","preserveImpression","loadCurrentAdMedia","isHlsAd","Hls","isSupported","destroy","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","play","catch","ERROR","_event","data","fatal","canPlayType","load","emit","total","clearStallWatchdog","clearInterval","handleAdStall","window","setInterval","paused","STALL_CHECK_INTERVAL_MS","releaseAdDecoder","removeAttribute","remove","display","pointerEvents","continueLiveStreamDuringAds","visibility","opacity","initialize","container","right","bottom","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","preloaded","Promise","reject","has","delete","resolve","contentVolume","previousMutedState","timeoutId","clearTimeout","removeChild","clear","isAdPlaying","resize","listener","Set","add","off","updateOriginalMutedState","nextVolume","isNaN","getAdVolume","getOriginalMutedState","getOriginalVolume","setAdVolume","clamped","showPlaceholder","hidePlaceholder","getLoadedAdDuration","getLoadedAdId","getPodAdCount","getPodTotalDurationMs","reduce","PRIVATE_HOST_PATTERNS","isLocalDevHost","hostname","host","replace","some","pattern","test","toDevSafeUrl","rawUrl","URL","protocol","cleanPath","pathname","PAL_SDK_URL","_nonceLoader","_palLoadPromise","loadPalSdk","goog","pal","existing","timeout","setTimeout","script","async","setAttribute","onload","onerror","head","getOrCreateNonceLoader","consentSettings","ConsentSettings","allowStorage","NonceLoader","createPalNonceManager","currentNonce","currentNonceManager","generateNonce","loader","request","manager","NonceRequest","adWillAutoPlay","adWillPlayMuted","playerVolume","continuousPlayback","descriptionUrl","location","href","iconsSupported","playerType","playerVersion","supportedApiFrameworks","videoWidth","videoHeight","JSON","stringify","ppid","getNonce","teardownClient","getCurrentNonce","injectNonce","searchParams","base","sep","encodeURIComponent","sendPlaybackStart","sendPlaybackEnd","sendAdClick","sendAdTouch","reset","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","username","password","topicPrefix","qos","mqttConfig","applyMQTTConfig","overrides","assign","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","buildPlayerTopic","channel","import_mqtt","LOG","KEEPALIVE_SECONDS","CONNECT_TIMEOUT_MS","RECONNECT_BASE_MS","RECONNECT_MAX_MS","MAX_RECONNECT_ATTEMPTS","COOLDOWN_MS","client","status","reconnectAttempts","reconnectTimer","stopped","clearReconnectTimer","removeAllListeners","end","scheduleReconnect","openConnection","delay","jitter","floor","clientId","slice","mqtt","connect","reschedulePings","clean","reconnectPeriod","connectTimeout","queueQoSZero","timerVariant","err","info","message","initMQTTClient","ensureMQTTClient","publish","publishMQTT","topic","connected","AIRY_ANDROID_APP_ID","AIRY_WEBOS_APP_ID","AIRY_TIZEN_APP_ID","AIRY_ROKU_APP_ID","AIRY_APP_NAME","AIRY_DEFAULT_CONTENT_URL","LG_TEST_APP_ID","CTV_SESSION_STORAGE_KEY","LG_TEST_APP_NAME","LG_TEST_CONTENT_URL","_lgTestDeviceId","getLgTestDeviceId","createUuid","isLgWebOS","navigator","userAgent","ua","DEVICE_ID_STORAGE_KEYS","ANDROID_ID_TYPES","resolveVastEnvironmentSignals","isCtv","platformDevice","readPlatformNativeDeviceId","lg","platformLat","bridgeSignals","limitAdTracking","deviceId","readStoredDeviceId","readStoredLimitAdTracking","contentUrl","readStoredString","appId","getDefaultAppId","appName","getOrCreateCtvSessionId","deviceIdType","deviceTypeHint","inferDeviceIdType","isEquivalentDeviceIdType","tagType","runtimeType","tag","runtime","resolveNativeDeviceId","readNativeBridgeSignals","isMacroPlaceholder","isZeroedAdId","getOrCreateStoredUuid","storageKey","readPersistentId","writePersistentId","readCookie","localStorage","setItem","writeCookie","PERSISTENT_ID_COOKIE_MAX_AGE","prefix","parts","cookie","entry","part","decodeURIComponent","bytes","crypto","randomUUID","Uint8Array","getRandomValues","seed","performanceNow","i","hex","padStart","performance","adinfo","webapis","tifa","getTIFA","lat","isLATEnabled","webOSDev","lgudid","LGUDID","roku","Roku","rida","getPublisherUniqueId","ZEROED_AD_ID_PATTERNS","t","candidates","__STORMCLOUD_CTV_AD_INFO__","__STORMCLOUD_CTV__","AiryTV","Android","webOS","tizen","amazon","filter","Boolean","readBridgeValue","readBridgeBoolean","result","normalized","normalizeBoolean","getItem","cachedBrowserId","buildAnalyticsContext","config","context","debugAdTiming","isLiveStream","inputStreamType","getClientInfo","screen","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","origin","path","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","sha256Hex","input","encodedData","utf8","buffer","hashBuffer","hash","char","fallbackHash","timestamp","subtle","digest","TextEncoder","encode","unescape","charCodeAt","padEnd","resolvePlayerIdentitySeed","clientInfo","nativeDeviceId","persistedId","PLAYER_ID_STORAGE_KEY","getBrowserID","canPublish","buildPlayerMetricEvent","flags","playerId","captureAt","toISOString","player_id","device_type","ad_loaded","adLoaded","ad_detect","adDetect","capture_at","input_stream_type","publishTracking","body","sendInitialTracking","metricEvent","events","sendAdDetectTracking","adDetectInfo","sendAdLoadedTracking","adLoadedInfo","sendHeartbeat","sendAdImpressionTracking","adImpressionInfo","ad_played_count","ad_url","adUrl","heartbeatData","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","param","decodedKey","safeDecodeURIComponent","decodedValue","str","values","String","getAll","callback","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","polyfillStringIncludes","indexOf","initializePolyfills","UNEXPANDED_MACRO_PATTERN","INVALID_VAST_PARAM_KEY","EXAMPLE_COM_URL","CTV_UNSUPPORTED_PARAMS","INLINE_DEVICE_MACRO_REPLACEMENTS","getValue","ctx","correlator","trimmed","generateCorrelator","buf","Uint32Array","expandInlineMacroPlaceholders","baseUrl","applyDeviceIdentityParams","runtimeId","tagRdid","tagLat","latValue","tagRdidValid","tagTypeValid","removeBrokenAppNameOrphans","toDelete","_value","suffix","normalizeVastTagUrl","raw","anValue","orphanFragments","reconstructed","_match","val","applyVastMacros","expandedUrl","replaceCorrelatorFallback","streamCorrelator","pod","podMinDurationMs","round","podMaxDurationMs","podMaxAds","requestUrl","pageUrl","existingUrl","consent","staleKeys","correlatorRegex","tcfApi","__tcfapi","gdpr","gdprConsent","usPrivacy","adTest","fetchConsentSignals","timeoutMs","signals","tasks","settled","tcData","success","eventStatus","gdprApplies","tcString","listenerId","uspApi","__uspapi","uspString","getChromeVersion","getWebKitVersion","getPlatform","userAgentData","detectBrowser","version","isLegacyTV","supportsModernJS","webOSVersion","chromeVersionNum","chromeVersion","webkitVersion","majorVersion","tizenVersion","getBrowserConfigOverrides","browser","allowNativeHls","pauseContentDuringAds","logBrowserInfo","debug","parseCueOutDuration","num","parseFloat","dStr","d","parseCueOutCont","res","elapsedMatch","durationMatch","elapsed","slashMatch","parseAttributeList","attrs","regex","rawVal","toNumber","n","isManifestBasedMarker","marker","id3","splice_command_type","decodeId3ValueToText","decoder","TextDecoder","decode","out","fromCharCode","getFragmentStartSeconds","frag","startPTS","candidate","parseScte35FromId3","cueOutMatch","arg","dur","ptsSeconds","durationSeconds","cueOutContMatch","cont","cueInMatch","daterangeMatch","hasScteOut","hasScteIn","klass","bin","parseScte35Binary","normalizeFragmentPayload","ArrayBuffer","isView","view","packetSizes","packetSize","tsPayloadOffset","offset","packetStart","matchedPackets","getPsiSectionStart","payloadUnitStart","pointerField","sectionStart","getPsiSectionLength","parsePatSection","pmtPids","sectionLength","sectionEnd","programNumber","pid","descriptorsIdentifyScte35","descriptorStart","descriptorEnd","registration","parsePmtSection","tsScte35Pids","programInfoLength","streamType","elementaryPid","esInfoLength","hasProcessedTsScte35Section","section","processedSections","checksum","size","firstKey","next","addScte35SectionMarker","markers","appendScte35Bytes","assemblers","assembler","expectedLength","collectScte35SectionsFromPayload","previousAssembler","subarray","tableId","totalLength","parseScte35FromTsPackets","packetInfo","detectTsPacketFormat","sectionAssemblers","tsStart","secondByte","thirdByte","fourthByte","adaptationFieldControl","hasPayload","payloadStart","adaptationLength","payloadEnd","BitReader","bytePos","bitPos","readBits","numBits","remainingInByte","toRead","currentByte","shift","mask","bits","skipBits","bytePosition","readSpliceTime","r","ptsAdjustmentTicks","timeSpecifiedFlag","high","low","ptsTicks","markerTypeFromSegmentationTypeId","segmentationTypeId","parseScte35SegmentationDescriptor","descriptor","identifier","segmentationEventId","cancelIndicator","programSegmentationFlag","segmentationDurationFlag","componentCount","durationTicks","segmentationUpidLength","markerType","parseScte35SegmentationDescriptors","descriptorTag","descriptorLoopLength","descriptorOffset","descriptorLength","descriptorDataStart","descriptorDataEnd","descriptorMarker","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","spliceEventId","commandBodyStart","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","componentPtsSeconds","expectedDescriptorOffset","splice_event_id","segmentation_event_id","Scte35CueManager","callbacks","pendingScte35Cues","recentScte35CueKeys","recentScte35CueLimit","processedTsScte35Sections","pendingScte35CueKey","pendingScte35CueKeyValue","activeScte35BreakKey","activeScte35BreakKeyValue","scheduledScte35BreakKey","scheduledScte35BreakKeyValue","createScte35CueContext","readiness","sn","fragmentStartSec","fragmentStartSeconds","createScte35Cue","onScte35Cue","cue","pendingKey","getPendingScte35CueKey","trimRecentScte35CueMaps","onEarlyStartCue","fragmentSn","inAdBreak","isInAdBreak","hasRecentlyHandledScte35Cue","markScte35CueHandled","onPlaybackCue","activatePendingScte35CuesForFragment","matchingCues","entries","getScte35CueKey","getScte35MarkerRaw","toIdentityString","daterangeId","ID","scteValue","recentKey","shouldAcceptScte35EndCue","isStrongScte35CueKey","AdConfigManager","vmapBreaks","consumedVmapBreakIds","viewCorrelator","consentSignals","podCounter","podAssignedByPrefetch","lastHeartbeatTime","defaultPodMaxAds","defaultPodMaxDurationMs","isVmapEnabled","isVmap","vmapUrl","fetchAdConfiguration","vastMode","vastEndpoint","apiUrl","imaPayload","decodedPayload","numberAds","fetchAndParseVmap","apiVastTagUrl","ok","json","applyMqttConfigFromResponse","apiNumberAds","vast","cue_tones","number_ads","mqtt_config","vmapXml","parseVmapToBreaks","doc","VMAP_NS","adBreakNodes","getElementsByTagNameNS","getElementsByTagName","localName","node","timeOffsetRaw","startTimeMs","parseVmapTimeOffsetToMs","adTagNode","adTagUrl","breakId","aStart","bStart","hms","resolveBreakStartMs","timeOffset","hh","mm","ss","ms","hours","minutes","seconds","millis","percent","ratio","durationSec","getAdBreakKey","adBreak","findCurrentOrNextBreak","nowMs","schedule","durationMs","tol","driftToleranceMs","breakStartMs","findBreakForTime","selectVastTagsForBreak","s","envSignals","beginNewAdPod","resolvePodParams","breakDurationMs","maxDurationMs","maxAds","minDurationMs","podExactDuration","generatePodVastUrl","podParams","adPlayer","palNonce","ctvAdRequest","urlWithMacros","autoplay","finalUrl","initializeTracking","heartbeatInterval","sendHeartbeatIfNeeded","destroyTracking","temporaryFailureCooldownMs","adStopTimerId","AdTimingService","adRequestWatchdogToken","adFailsafeToken","ptsDriftEmaMs","adBreakPlayedDurationMs","adBreakEpoch","adRequestTokenCounter","activeAdRequestToken","currentAdIndex","totalAdsInBreak","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","lastAdRequestTime","consecutiveFailures","maxConsecutiveFailures","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","defaultMinRemainingMsToStartAd","failedVastUrls","temporaryFailureUrls","globalConsecutiveNoFills","globalNoFillThreshold","globalNoFillCooldownUntil","globalNoFillBackoffBaseMs","globalNoFillBackoffMaxMs","globalLastGamRequestTime","globalMinGamIntervalMs","scheduleAdStopCountdown","clearAdStopTimer","remainingMs","ensureAdStoppedByTimer","onAdStopTimerFired","nowWallClockMs","scheduleAdStartIn","delayMs","cueKey","clearAdStartTimer","onAdStartTimerFired","adStartTimerId","updatePtsDrift","ptsSecondsSample","sampleMs","alpha","resolveScteBreakStartWallClockMs","estimatedCurrentPtsMs","deltaMs","setAdBreakDurationBoundary","expectedAdBreakDurationMs","currentAdBreakStartWallClockMs","scteAdBreakEndWallClockMs","scheduleAdStopAtBreakBoundary","getWallClockRemainingAdMs","endWallClockMs","getAdBreakEndWallClockMs","getLoadedAdDurationMs","getDurationBudgetRemainingMs","adController","adFitsRemainingBudget","logAdDurationDecision","remainingBudget","recordPlayedAdDuration","ensureLoadedAdFitsBudget","fits","rejectLoadedAdForDuration","markAdStarted","notePodAdStarted","getRemainingAdMs","wallClockRemaining","budgetRemaining","getMinRemainingMsToStartAd","configured","minRemainingMsToStartAd","hasTimeToStartAnotherAd","minRemaining","isTemporaryAdError","isUrlInCooldown","failureTime","cleanupTemporaryFailures","isGamInCooldown","recordGamNoFill","exponent","backoff","pow","resetGamNoFillCounter","enforceGlobalRateLimit","waitMs","startAdRequestWatchdog","token","clearAdRequestWatchdog","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","onWatchdogTimeout","startAdFailsafeTimer","clearAdFailsafeTimer","failsafeMs","adFailsafeTimerId","videoPaused","onFailsafeTimeout","extra","showAds","resetForBreakEnd","PlaceholderLayer","ensureContainer","transition","show","requestAnimationFrame","wasHidden","offsetHeight","hide","HlsEngine","cueManager","timing","nativeHlsMode","videoSrcProtection","reloadingLiveStream","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","shouldUseNativeHls","getStreamType","canNative","setupNativeHls","adBehavior","isLive","setupHls","hls","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","_data","minSegments","details","live","onManifestParsed","minSegmentsBeforePlay","LEVEL_LOADED","_evt","hasPendingAdBreak","fragments","fragmentsToScan","tagList","isArray","idx","earlyDetection","FRAG_BUFFERED","FRAG_PARSING_METADATA","pts","id3Tags","onId3Tag","FRAG_LOADED","processFragmentScte35Payload","FRAG_DECRYPTED","FRAG_CHANGED","activatePendingCuesForFragment","prog","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","onFatalDestroy","payloadData","getLiveSyncPosition","liveSyncPosition","restartLoadAt","stopLoad","reloadLiveStream","detachMedia","getAdAudioVolume","toggleMute","newMutedState","restoreVolume","toggleFullscreen","requestFullscreen","isMuted","setMuted","setVolume","clampedVolume","getVolume","isFullscreen","fullscreenElement","resizePlayer","clientWidth","clientHeight","AdBreakOrchestrator","adConfig","placeholder","isShowingPlaceholder","adDetectSentForCurrentBreak","continuousFetchingActive","continuousFetchLoopRunning","adRequestQueue","adPodQueue","pendingAdBreak","analyticsContext","nextAdRequestUrl","baseVastUrl","remaining","attachImaEventListeners","getAdPlayer","adIndex","queuedUrls","tryNextAvailableAdWithRateLimit","handleAdPodComplete","errorPayload","errorMessage","errorCode","code","vastErrorCode","cause","innerError","causeMessage","handleAdFailure","recreateAdController","shouldShowPlaceholder","preservedMutedState","preservedVolumeState","shouldContinueLiveStreamDuringAds","newAdPlayer","setAdPlayer","createAdPlayer","clearPendingAdBreak","prefetchTimerId","handleAdStart","_marker","scheduled","tags","adBreakDurationMs","currentMuted","currentVolume","podPlayed","startOptimizedPod","startContinuousFetching","podUrl","requestToken","podCount","vastUrls","continuousFetchLoop","epoch","maxQueueSize","newAdUrl","queuedUrlsPreview","generationDelay","stopContinuousFetching","backoffMultiplier","backoffDelay","effectiveMinInterval","timeSinceLastRequest","waitTime","tryNextAvailableAd","retryCount","nextAdUrl","maxRetries","playSingleAd","showPlaceholderAndWaitForAds","ap","playError","vastUrl","checkInterval","maxChecks","maxPlaceholderDurationMs","stop","restoredMuted","restoredVolume","liveSyncPos","toFixed","restartHlsLoad","resumeContentPlayback","monitorLiveResumeStall","getBufferedAhead","ranges","buffered","describeVideoState","networkStates","readyStates","net","v","networkState","ready","readyState","seeking","resumeBaseline","pollIntervalMs","graceMs","recoveryCooldownMs","maxRecoveries","maxMonitorMs","startTime","baseline","recoveries","lastRecoveryAt","listenersAttached","onMediaEvent","diagEvents"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n  for (var name in all)\n    __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n  if (from && typeof from === \"object\" || typeof from === \"function\") {\n    for (let key of __getOwnPropNames(from))\n      if (!__hasOwnProp.call(to, key) && key !== except)\n        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n  }\n  return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n  // If the importer is in node compatibility mode or this is not an ESM\n  // file that has been converted to a CommonJS file using a Babel-\n  // compatible transform (i.e. \"__esModule\" has not been set), then set\n  // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n  isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n  mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/ui/StormcloudVideoPlayer.tsx\nvar StormcloudVideoPlayer_exports = {};\n__export(StormcloudVideoPlayer_exports, {\n  StormcloudVideoPlayerComponent: () => StormcloudVideoPlayerComponent\n});\nmodule.exports = __toCommonJS(StormcloudVideoPlayer_exports);\nvar import_react = __toESM(require(\"react\"), 1);\n\n// src/sdk/hlsAdPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar MAX_VAST_WRAPPER_DEPTH = 5;\nfunction createHlsAdPlayer(contentVideo, options) {\n  let adPlaying = false;\n  let originalMutedState = false;\n  let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n  const listeners = /* @__PURE__ */ new Map();\n  const licenseKey = options?.licenseKey;\n  const mainHlsInstance = options?.mainHlsInstance;\n  let adVideoElement;\n  let adHls;\n  let adContainerEl;\n  let currentAd;\n  let podAds = [];\n  let podIndex = 0;\n  let sessionId;\n  const preloadedAds = /* @__PURE__ */ new Map();\n  const preloadingAds = /* @__PURE__ */ new Map();\n  let destroyed = false;\n  let pendingTimeouts = [];\n  const STALL_TIMEOUT_MS = 4e3;\n  const STALL_CHECK_INTERVAL_MS = 1e3;\n  let stallWatchdogId;\n  let lastAdProgressTime = 0;\n  let lastAdProgressPosition = 0;\n  let trackingFired = {\n    impression: false,\n    start: false,\n    firstQuartile: false,\n    midpoint: false,\n    thirdQuartile: false,\n    complete: false\n  };\n  function emit(event, payload) {\n    const set = listeners.get(event);\n    if (!set) return;\n    for (const fn of Array.from(set)) {\n      try {\n        fn(payload);\n      } catch (error) {\n        console.warn(\n          `[HlsAdPlayer] Error in event listener for ${event}:`,\n          error\n        );\n      }\n    }\n  }\n  function generateSessionId() {\n    return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n  }\n  function fireTrackingPixels(urls) {\n    if (!urls || urls.length === 0) return;\n    urls.forEach((url) => {\n      try {\n        let trackingUrl = url;\n        if (sessionId) {\n          trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n        }\n        if (licenseKey) {\n          trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n        }\n        const img = new Image(1, 1);\n        img.src = trackingUrl;\n        console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n      } catch (error) {\n        console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n      }\n    });\n  }\n  function getMainStreamQuality() {\n    if (!mainHlsInstance || !mainHlsInstance.levels) {\n      return null;\n    }\n    const currentLevel = mainHlsInstance.currentLevel;\n    if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n      const autoLevel = mainHlsInstance.loadLevel;\n      if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n        const level2 = mainHlsInstance.levels[autoLevel];\n        return {\n          width: level2.width || 1920,\n          height: level2.height || 1080,\n          bitrate: level2.bitrate || 5e6\n        };\n      }\n      return null;\n    }\n    const level = mainHlsInstance.levels[currentLevel];\n    return {\n      width: level.width || 1920,\n      height: level.height || 1080,\n      bitrate: level.bitrate || 5e6\n    };\n  }\n  function selectBestMediaFile(mediaFiles) {\n    if (mediaFiles.length === 0) {\n      throw new Error(\"No media files available\");\n    }\n    const firstFile = mediaFiles[0];\n    if (!firstFile) {\n      throw new Error(\"No media files available\");\n    }\n    if (mediaFiles.length === 1) {\n      return firstFile;\n    }\n    const mainQuality = getMainStreamQuality();\n    if (!mainQuality) {\n      console.log(\n        \"[HlsAdPlayer] No main stream quality info, using first media file\"\n      );\n      return firstFile;\n    }\n    console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n    const scoredFiles = mediaFiles.map((file) => {\n      const widthDiff = Math.abs(file.width - mainQuality.width);\n      const heightDiff = Math.abs(file.height - mainQuality.height);\n      const resolutionDiff = widthDiff + heightDiff;\n      const fileBitrate = (file.bitrate || 5e3) * 1e3;\n      const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n      const score = resolutionDiff * 2 + bitrateDiff / 1e3;\n      return { file, score, resolutionDiff, bitrateDiff };\n    });\n    scoredFiles.sort((a, b) => a.score - b.score);\n    const bestMatch = scoredFiles[0];\n    if (!bestMatch) {\n      console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n      return firstFile;\n    }\n    console.log(\"[HlsAdPlayer] Selected media file:\", {\n      url: bestMatch.file.url,\n      resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n      bitrate: bestMatch.file.bitrate,\n      score: bestMatch.score,\n      resolutionDiff: bestMatch.resolutionDiff,\n      bitrateDiff: bestMatch.bitrateDiff\n    });\n    return bestMatch.file;\n  }\n  function isHlsMediaFile(mediaFile) {\n    const type = mediaFile.type.toLowerCase();\n    const url = mediaFile.url.toLowerCase();\n    return type === \"application/x-mpegurl\" || type === \"application/vnd.apple.mpegurl\" || type.includes(\"mpegurl\") || url.includes(\".m3u8\");\n  }\n  function isProgressiveMediaFile(mediaFile) {\n    const type = mediaFile.type.toLowerCase();\n    const url = mediaFile.url.toLowerCase();\n    return type.startsWith(\"video/\") || url.endsWith(\".mp4\") || url.includes(\".mp4?\");\n  }\n  function createEmptyTrackingUrls() {\n    return {\n      impression: [],\n      start: [],\n      firstQuartile: [],\n      midpoint: [],\n      thirdQuartile: [],\n      complete: [],\n      mute: [],\n      unmute: [],\n      pause: [],\n      resume: [],\n      fullscreen: [],\n      exitFullscreen: [],\n      skip: [],\n      error: []\n    };\n  }\n  function extractTrackingUrls(scope) {\n    const trackingUrls = createEmptyTrackingUrls();\n    scope.querySelectorAll(\"Impression\").forEach((el) => {\n      const url = el.textContent?.trim();\n      if (url) trackingUrls.impression.push(url);\n    });\n    scope.querySelectorAll(\"Tracking\").forEach((el) => {\n      const event = el.getAttribute(\"event\");\n      const url = el.textContent?.trim();\n      if (event && url) {\n        const eventKey = event;\n        if (trackingUrls[eventKey]) {\n          trackingUrls[eventKey].push(url);\n        }\n      }\n    });\n    scope.querySelectorAll(\"Error\").forEach((el) => {\n      const url = el.textContent?.trim();\n      if (url) trackingUrls.error.push(url);\n    });\n    return trackingUrls;\n  }\n  function mergeTrackingUrls(target, source) {\n    Object.keys(target).forEach((key) => {\n      if (source[key] && source[key].length > 0) {\n        target[key] = target[key].concat(source[key]);\n      }\n    });\n    return target;\n  }\n  function parseVastXml(xmlString) {\n    try {\n      const parser = new DOMParser();\n      const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n      const parserError = xmlDoc.querySelector(\"parsererror\");\n      if (parserError) {\n        console.error(\n          \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n          parserError.textContent\n        );\n        return { type: \"empty\" };\n      }\n      const adElement = xmlDoc.querySelector(\"Ad\");\n      if (!adElement) {\n        console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n        return { type: \"empty\" };\n      }\n      const adId = adElement.getAttribute(\"id\") || \"unknown\";\n      const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n      const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n      const wrapperUri = xmlDoc.querySelector(\"VASTAdTagURI\")?.textContent?.trim();\n      if (wrapperUri) {\n        console.log(\n          `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n        );\n        return {\n          type: \"wrapper\",\n          vastAdTagUri: wrapperUri,\n          trackingUrls: extractTrackingUrls(xmlDoc),\n          clickThrough\n        };\n      }\n      const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n      const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n      const durationParts = durationText.split(\":\");\n      const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n      const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n      const mediaFiles = [];\n      console.log(\n        `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n      );\n      mediaFileElements.forEach((mf, index) => {\n        const type = mf.getAttribute(\"type\") || \"\";\n        const url = mf.textContent?.trim() || \"\";\n        const width = mf.getAttribute(\"width\") || \"\";\n        const height = mf.getAttribute(\"height\") || \"\";\n        console.log(\n          `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n        );\n        const mediaFile = {\n          url,\n          type,\n          width: parseInt(width || \"1920\", 10),\n          height: parseInt(height || \"1080\", 10),\n          bitrate: void 0\n        };\n        if (!url) {\n          console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n          return;\n        }\n        const bitrateAttr = mf.getAttribute(\"bitrate\");\n        const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n        mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;\n        if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n          mediaFiles.push(mediaFile);\n          console.log(\n            `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n          );\n        } else {\n          console.log(\n            `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n          );\n        }\n      });\n      if (mediaFiles.length === 0) {\n        if (isNoAdAvailable) {\n          console.warn(\n            \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n          );\n        } else {\n          console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n        }\n        return { type: \"empty\" };\n      }\n      return {\n        type: \"inline\",\n        ad: {\n          id: adId,\n          title,\n          duration,\n          mediaFiles,\n          trackingUrls: extractTrackingUrls(xmlDoc),\n          clickThrough\n        }\n      };\n    } catch (error) {\n      console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n      return { type: \"empty\" };\n    }\n  }\n  function parseAdElement(adElement) {\n    try {\n      const adId = adElement.getAttribute(\"id\") || \"unknown\";\n      const title = adElement.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n      const clickThrough = adElement.querySelector(\"ClickThrough\")?.textContent?.trim();\n      const wrapperUri = adElement.querySelector(\"VASTAdTagURI\")?.textContent?.trim();\n      if (wrapperUri) {\n        return {\n          type: \"wrapper\",\n          vastAdTagUri: wrapperUri,\n          trackingUrls: extractTrackingUrls(adElement),\n          clickThrough\n        };\n      }\n      const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n      const durationText = adElement.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n      const durationParts = durationText.split(\":\");\n      const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseInt(durationParts[2] || \"0\", 10);\n      const mediaFileElements = adElement.querySelectorAll(\"MediaFile\");\n      const mediaFiles = [];\n      mediaFileElements.forEach((mf) => {\n        const type = mf.getAttribute(\"type\") || \"\";\n        const url = mf.textContent?.trim() || \"\";\n        const width = mf.getAttribute(\"width\") || \"\";\n        const height = mf.getAttribute(\"height\") || \"\";\n        if (!url) return;\n        const bitrateAttr = mf.getAttribute(\"bitrate\");\n        const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n        const mediaFile = {\n          url,\n          type,\n          width: parseInt(width || \"1920\", 10),\n          height: parseInt(height || \"1080\", 10),\n          bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n        };\n        if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n          mediaFiles.push(mediaFile);\n        }\n      });\n      if (mediaFiles.length === 0) {\n        if (isNoAdAvailable) {\n          console.warn(\n            \"[HlsAdPlayer] Pod <Ad> indicates no ad available\"\n          );\n        } else {\n          console.warn(\"[HlsAdPlayer] No supported media files in pod <Ad>\");\n        }\n        return { type: \"empty\" };\n      }\n      return {\n        type: \"inline\",\n        ad: {\n          id: adId,\n          title,\n          duration,\n          mediaFiles,\n          trackingUrls: extractTrackingUrls(adElement),\n          clickThrough\n        }\n      };\n    } catch (error) {\n      console.error(\"[HlsAdPlayer] Error parsing pod <Ad> element:\", error);\n      return { type: \"empty\" };\n    }\n  }\n  async function fetchVastXml(vastTagUrl, credentials = \"include\") {\n    const requestVast = (creds) => fetch(vastTagUrl, {\n      mode: \"cors\",\n      credentials: creds,\n      headers: {\n        \"Accept\": \"application/xml, text/xml, */*\"\n      },\n      referrerPolicy: \"no-referrer-when-downgrade\"\n    });\n    let response;\n    try {\n      response = await requestVast(credentials);\n    } catch (error) {\n      if (credentials !== \"omit\") {\n        console.warn(\n          `[HlsAdPlayer] VAST fetch failed with credentials=\"${credentials}\", retrying without credentials:`,\n          error\n        );\n        response = await requestVast(\"omit\");\n      } else {\n        throw error;\n      }\n    }\n    if (!response.ok) {\n      throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n    }\n    return response.text();\n  }\n  async function fetchAndParseVastAd(vastTagUrl, depth = 0, accumulatedTracking = createEmptyTrackingUrls()) {\n    const vastXml = await fetchVastXml(\n      vastTagUrl,\n      depth === 0 ? \"include\" : \"omit\"\n    );\n    console.log(\"[HlsAdPlayer] VAST XML received\");\n    console.log(\n      \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n      vastXml.substring(0, 2e3)\n    );\n    const parsed = parseVastXml(vastXml);\n    if (parsed.type === \"empty\") {\n      return null;\n    }\n    if (parsed.type === \"wrapper\") {\n      if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n        console.warn(\n          `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n        );\n        return null;\n      }\n      mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n      return fetchAndParseVastAd(\n        parsed.vastAdTagUri,\n        depth + 1,\n        accumulatedTracking\n      );\n    }\n    mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n    return parsed.ad;\n  }\n  async function fetchAndParsePod(vastTagUrl) {\n    const vastXml = await fetchVastXml(vastTagUrl);\n    console.log(\"[HlsAdPlayer] Pod VAST XML received\");\n    const parser = new DOMParser();\n    const xmlDoc = parser.parseFromString(vastXml, \"text/xml\");\n    if (xmlDoc.querySelector(\"parsererror\")) {\n      console.error(\"[HlsAdPlayer] Pod VAST XML parsing error (malformed)\");\n      return [];\n    }\n    const adElements = Array.from(xmlDoc.querySelectorAll(\"Ad\"));\n    if (adElements.length === 0) {\n      console.warn(\"[HlsAdPlayer] No <Ad> elements found in pod VAST response\");\n      return [];\n    }\n    adElements.sort((a, b) => {\n      const aSeq = parseInt(a.getAttribute(\"sequence\") || \"\", 10);\n      const bSeq = parseInt(b.getAttribute(\"sequence\") || \"\", 10);\n      const aVal = Number.isFinite(aSeq) ? aSeq : Number.MAX_SAFE_INTEGER;\n      const bVal = Number.isFinite(bSeq) ? bSeq : Number.MAX_SAFE_INTEGER;\n      return aVal - bVal;\n    });\n    const ads = [];\n    for (const adElement of adElements) {\n      const parsed = parseAdElement(adElement);\n      if (parsed.type === \"inline\") {\n        ads.push(parsed.ad);\n      } else if (parsed.type === \"wrapper\") {\n        try {\n          const resolved = await fetchAndParseVastAd(\n            parsed.vastAdTagUri,\n            1,\n            parsed.trackingUrls\n          );\n          if (resolved) {\n            ads.push(resolved);\n          }\n        } catch (error) {\n          console.warn(\n            \"[HlsAdPlayer] Failed to resolve wrapper <Ad> in pod:\",\n            error\n          );\n        }\n      }\n    }\n    console.log(`[HlsAdPlayer] Parsed ${ads.length} ad(s) from pod VAST response`);\n    return ads;\n  }\n  function createAdVideoElement() {\n    const video = document.createElement(\"video\");\n    video.style.position = \"absolute\";\n    video.style.left = \"0\";\n    video.style.top = \"0\";\n    video.style.width = \"100%\";\n    video.style.height = \"100%\";\n    video.style.objectFit = \"contain\";\n    video.style.backgroundColor = \"#000\";\n    video.playsInline = true;\n    video.muted = false;\n    video.volume = 1;\n    console.log(\n      `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n    );\n    return video;\n  }\n  function setupAdEventListeners() {\n    if (!adVideoElement || !currentAd) return;\n    adVideoElement.addEventListener(\"timeupdate\", () => {\n      if (!currentAd || !adVideoElement) return;\n      noteAdProgress();\n      const progress = adVideoElement.currentTime / currentAd.duration;\n      if (progress >= 0.25 && !trackingFired.firstQuartile) {\n        trackingFired.firstQuartile = true;\n        fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n      }\n      if (progress >= 0.5 && !trackingFired.midpoint) {\n        trackingFired.midpoint = true;\n        fireTrackingPixels(currentAd.trackingUrls.midpoint);\n      }\n      if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n        trackingFired.thirdQuartile = true;\n        fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n      }\n    });\n    adVideoElement.addEventListener(\"playing\", () => {\n      startStallWatchdog();\n      if (!currentAd || trackingFired.start) return;\n      trackingFired.start = true;\n      fireTrackingPixels(currentAd.trackingUrls.start);\n      console.log(\"[HlsAdPlayer] Ad started playing\");\n    });\n    adVideoElement.addEventListener(\"ended\", () => {\n      if (!currentAd || trackingFired.complete) return;\n      trackingFired.complete = true;\n      fireTrackingPixels(currentAd.trackingUrls.complete);\n      console.log(\"[HlsAdPlayer] Ad completed\");\n      if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {\n        return;\n      }\n      handleAdComplete();\n    });\n    adVideoElement.addEventListener(\"error\", (e) => {\n      if (!adPlaying) return;\n      console.error(\"[HlsAdPlayer] Ad video error:\", e);\n      if (currentAd) {\n        fireTrackingPixels(currentAd.trackingUrls.error);\n      }\n      if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {\n        return;\n      }\n      handleAdError();\n    });\n    adVideoElement.addEventListener(\"volumechange\", () => {\n      if (!currentAd) return;\n      if (adVideoElement.muted) {\n        fireTrackingPixels(currentAd.trackingUrls.mute);\n      } else {\n        fireTrackingPixels(currentAd.trackingUrls.unmute);\n      }\n    });\n    adVideoElement.addEventListener(\"pause\", () => {\n      if (currentAd && !adVideoElement.ended) {\n        fireTrackingPixels(currentAd.trackingUrls.pause);\n      }\n    });\n    adVideoElement.addEventListener(\"play\", () => {\n      if (currentAd && adVideoElement.currentTime > 0) {\n        fireTrackingPixels(currentAd.trackingUrls.resume);\n      }\n    });\n  }\n  function setAdPlayingFlag(isPlaying) {\n    if (isPlaying) {\n      contentVideo.dataset.stormcloudAdPlaying = \"true\";\n    } else {\n      delete contentVideo.dataset.stormcloudAdPlaying;\n    }\n  }\n  function resetQuartileTracking(preserveImpression) {\n    trackingFired = {\n      impression: preserveImpression ? trackingFired.impression : false,\n      start: false,\n      firstQuartile: false,\n      midpoint: false,\n      thirdQuartile: false,\n      complete: false\n    };\n  }\n  function loadCurrentAdMedia() {\n    if (!adVideoElement || !currentAd) {\n      throw new Error(\"No ad video element or ad to load\");\n    }\n    const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n    if (!mediaFile) {\n      throw new Error(\"No media file available for ad\");\n    }\n    const isHlsAd = isHlsMediaFile(mediaFile);\n    console.log(\n      `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad (pod ${podIndex + 1}/${podAds.length || 1}) from: ${mediaFile.url}`\n    );\n    if (isHlsAd && import_hls.default.isSupported()) {\n      if (adHls) {\n        adHls.destroy();\n      }\n      adHls = new import_hls.default({\n        enableWorker: true,\n        lowLatencyMode: false\n      });\n      adHls.loadSource(mediaFile.url);\n      adHls.attachMedia(adVideoElement);\n      adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n        console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n        adVideoElement.play().catch((error) => {\n          console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n          handleAdError();\n        });\n      });\n      adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n        console.error(\"[HlsAdPlayer] HLS error:\", data);\n        if (data.fatal) {\n          handleAdError();\n        }\n      });\n    } else if (isHlsAd && adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n      adVideoElement.src = mediaFile.url;\n      adVideoElement.play().catch((error) => {\n        console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n        handleAdError();\n      });\n    } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n      if (adHls) {\n        adHls.destroy();\n        adHls = void 0;\n      }\n      adVideoElement.src = mediaFile.url;\n      adVideoElement.load();\n      adVideoElement.play().catch((error) => {\n        console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n        handleAdError();\n      });\n    } else {\n      throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n    }\n  }\n  function advanceToNextPodAd() {\n    if (podIndex >= podAds.length - 1) {\n      return false;\n    }\n    podIndex++;\n    currentAd = podAds[podIndex];\n    resetQuartileTracking(false);\n    if (currentAd) {\n      fireTrackingPixels(currentAd.trackingUrls.impression);\n      trackingFired.impression = true;\n      console.log(\n        `[HlsAdPlayer] Advancing to next pod ad (${podIndex + 1}/${podAds.length}): ${currentAd.title}, duration: ${currentAd.duration}s`\n      );\n    }\n    try {\n      loadCurrentAdMedia();\n      emit(\"pod_ad_started\", { index: podIndex, total: podAds.length });\n      return true;\n    } catch (error) {\n      console.error(\"[HlsAdPlayer] Failed to load next pod ad:\", error);\n      return false;\n    }\n  }\n  function clearStallWatchdog() {\n    if (stallWatchdogId != null) {\n      clearInterval(stallWatchdogId);\n      stallWatchdogId = void 0;\n    }\n  }\n  function noteAdProgress() {\n    lastAdProgressTime = Date.now();\n    if (adVideoElement) {\n      lastAdProgressPosition = adVideoElement.currentTime;\n    }\n  }\n  function handleAdStall() {\n    console.warn(\n      \"[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame\"\n    );\n    clearStallWatchdog();\n    if (currentAd) {\n      fireTrackingPixels(currentAd.trackingUrls.error);\n    }\n    if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {\n      return;\n    }\n    handleAdError();\n  }\n  function startStallWatchdog() {\n    clearStallWatchdog();\n    noteAdProgress();\n    stallWatchdogId = window.setInterval(() => {\n      if (!adPlaying || !adVideoElement) {\n        return;\n      }\n      if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {\n        noteAdProgress();\n        return;\n      }\n      if (adVideoElement.paused) {\n        noteAdProgress();\n        return;\n      }\n      if (Date.now() - lastAdProgressTime >= STALL_TIMEOUT_MS) {\n        handleAdStall();\n      }\n    }, STALL_CHECK_INTERVAL_MS);\n  }\n  function releaseAdDecoder() {\n    if (adHls) {\n      adHls.destroy();\n      adHls = void 0;\n    }\n    if (adVideoElement) {\n      adVideoElement.pause();\n      adVideoElement.removeAttribute(\"src\");\n      try {\n        adVideoElement.load();\n      } catch (error) {\n        console.warn(\"[HlsAdPlayer] adVideoElement.load() threw after src removal:\", error);\n      }\n      adVideoElement.remove();\n      adVideoElement = void 0;\n    }\n    if (adContainerEl) {\n      adContainerEl.style.display = \"none\";\n      adContainerEl.style.pointerEvents = \"none\";\n    }\n  }\n  function handleAdComplete() {\n    console.log(\"[HlsAdPlayer] Handling ad completion\");\n    clearStallWatchdog();\n    adPlaying = false;\n    setAdPlayingFlag(false);\n    contentVideo.muted = true;\n    releaseAdDecoder();\n    if (!options?.continueLiveStreamDuringAds) {\n      contentVideo.style.visibility = \"visible\";\n      contentVideo.style.opacity = \"1\";\n    }\n    if (options?.continueLiveStreamDuringAds) {\n      if (contentVideo.paused) {\n        console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n        contentVideo.play().catch((error) => {\n          console.error(\"[HlsAdPlayer] Error resuming content playback in live mode:\", error);\n        });\n      } else {\n        console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n      }\n    }\n    emit(\"content_resume\");\n  }\n  function handleAdError() {\n    console.log(\"[HlsAdPlayer] Handling ad error\");\n    clearStallWatchdog();\n    adPlaying = false;\n    setAdPlayingFlag(false);\n    contentVideo.muted = true;\n    releaseAdDecoder();\n    if (!options?.continueLiveStreamDuringAds) {\n      contentVideo.style.visibility = \"visible\";\n      contentVideo.style.opacity = \"1\";\n    }\n    emit(\"ad_error\");\n  }\n  return {\n    initialize() {\n      console.log(\"[HlsAdPlayer] Initializing\");\n      if (!adContainerEl) {\n        const container = document.createElement(\"div\");\n        container.style.position = \"absolute\";\n        container.style.left = \"0\";\n        container.style.top = \"0\";\n        container.style.right = \"0\";\n        container.style.bottom = \"0\";\n        container.style.display = \"none\";\n        container.style.alignItems = \"center\";\n        container.style.justifyContent = \"center\";\n        container.style.pointerEvents = \"none\";\n        container.style.zIndex = \"30\";\n        container.style.backgroundColor = \"#000\";\n        contentVideo.parentElement?.appendChild(container);\n        adContainerEl = container;\n      }\n    },\n    async requestAds(vastTagUrl) {\n      console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n      if (adPlaying) {\n        console.warn(\n          \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n        );\n        return Promise.reject(new Error(\"Ad already playing\"));\n      }\n      try {\n        sessionId = generateSessionId();\n        let ads = [];\n        if (preloadedAds.has(vastTagUrl)) {\n          const preloaded = preloadedAds.get(vastTagUrl);\n          preloadedAds.delete(vastTagUrl);\n          if (preloaded) {\n            ads = [preloaded];\n          }\n          console.log(\n            \"[HlsAdPlayer] Using preloaded VAST response:\",\n            vastTagUrl\n          );\n        } else {\n          ads = await fetchAndParsePod(vastTagUrl);\n        }\n        if (!ads.length) {\n          console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n          emit(\"ad_error\");\n          return Promise.reject(new Error(\"No ads available from VAST response\"));\n        }\n        podAds = ads;\n        podIndex = 0;\n        currentAd = ads[0];\n        console.log(\n          `[HlsAdPlayer] Pod parsed: ${ads.length} ad(s), first=\"${currentAd?.title}\", duration=${currentAd?.duration}s`\n        );\n        if (currentAd) {\n          fireTrackingPixels(currentAd.trackingUrls.impression);\n          trackingFired.impression = true;\n        }\n        return Promise.resolve();\n      } catch (error) {\n        console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n        emit(\"ad_error\");\n        return Promise.reject(error);\n      }\n    },\n    async play() {\n      if (!currentAd) {\n        console.warn(\n          \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n        );\n        return Promise.reject(new Error(\"No ad loaded\"));\n      }\n      console.log(\"[HlsAdPlayer] Starting ad playback\");\n      try {\n        if (!adVideoElement) {\n          adVideoElement = createAdVideoElement();\n          adContainerEl?.appendChild(adVideoElement);\n          setupAdEventListeners();\n        }\n        resetQuartileTracking(true);\n        const contentVolume = contentVideo.volume;\n        originalVolume = Math.max(\n          0,\n          Math.min(1, contentVolume || originalVolume)\n        );\n        if (!options?.continueLiveStreamDuringAds) {\n          contentVideo.pause();\n          console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n        } else {\n          console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n        }\n        console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n        contentVideo.muted = true;\n        adPlaying = true;\n        setAdPlayingFlag(true);\n        if (adVideoElement) {\n          adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n          adVideoElement.muted = originalMutedState;\n          console.log(\n            `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n          );\n        }\n        if (adContainerEl) {\n          adContainerEl.style.display = \"flex\";\n          adContainerEl.style.pointerEvents = \"auto\";\n        }\n        emit(\"content_pause\");\n        loadCurrentAdMedia();\n        return Promise.resolve();\n      } catch (error) {\n        console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n        handleAdError();\n        return Promise.reject(error);\n      }\n    },\n    pause() {\n      if (!adPlaying || !adVideoElement) {\n        return;\n      }\n      try {\n        if (adVideoElement && !adVideoElement.paused) {\n          adVideoElement.pause();\n        }\n      } catch (error) {\n        console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n      }\n    },\n    resume() {\n      if (!adPlaying || !adVideoElement) {\n        return;\n      }\n      try {\n        if (adVideoElement && adVideoElement.paused) {\n          adVideoElement.play().catch(() => {\n          });\n        }\n      } catch (error) {\n        console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n      }\n    },\n    async stop() {\n      console.log(\"[HlsAdPlayer] Stopping ad\");\n      clearStallWatchdog();\n      adPlaying = false;\n      setAdPlayingFlag(false);\n      const previousMutedState = contentVideo.muted;\n      contentVideo.muted = originalMutedState;\n      contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n      console.log(\n        `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n      );\n      releaseAdDecoder();\n      contentVideo.style.visibility = \"visible\";\n      contentVideo.style.opacity = \"1\";\n      if (options?.continueLiveStreamDuringAds) {\n        if (contentVideo.paused) {\n          console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n          contentVideo.play().catch((error) => {\n            console.error(\"[HlsAdPlayer] Error resuming content playback in live mode on stop:\", error);\n          });\n        }\n      }\n      currentAd = void 0;\n      podAds = [];\n      podIndex = 0;\n    },\n    destroy() {\n      console.log(\"[HlsAdPlayer] Destroying\");\n      destroyed = true;\n      clearStallWatchdog();\n      for (const timeoutId of pendingTimeouts) {\n        clearTimeout(timeoutId);\n      }\n      pendingTimeouts = [];\n      adPlaying = false;\n      setAdPlayingFlag(false);\n      contentVideo.muted = originalMutedState;\n      contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n      releaseAdDecoder();\n      if (adContainerEl?.parentElement) {\n        adContainerEl.parentElement.removeChild(adContainerEl);\n      }\n      adContainerEl = void 0;\n      currentAd = void 0;\n      podAds = [];\n      podIndex = 0;\n      listeners.clear();\n      preloadedAds.clear();\n      preloadingAds.clear();\n    },\n    isAdPlaying() {\n      return adPlaying;\n    },\n    resize(width, height) {\n      console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n      if (adContainerEl) {\n        adContainerEl.style.width = `${width}px`;\n        adContainerEl.style.height = `${height}px`;\n      }\n      if (adVideoElement) {\n        adVideoElement.style.width = `${width}px`;\n        adVideoElement.style.height = `${height}px`;\n      }\n    },\n    on(event, listener) {\n      if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n      listeners.get(event).add(listener);\n    },\n    off(event, listener) {\n      listeners.get(event)?.delete(listener);\n    },\n    updateOriginalMutedState(muted, volume) {\n      const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n      console.log(\n        `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n      );\n      originalMutedState = muted;\n      originalVolume = nextVolume;\n    },\n    getOriginalMutedState() {\n      return originalMutedState;\n    },\n    getOriginalVolume() {\n      return originalVolume;\n    },\n    setAdVolume(volume) {\n      if (adVideoElement && adPlaying) {\n        const clamped = Math.max(0, Math.min(1, volume));\n        adVideoElement.volume = clamped;\n        adVideoElement.muted = clamped === 0;\n      }\n    },\n    getAdVolume() {\n      if (adVideoElement && adPlaying) {\n        return adVideoElement.volume;\n      }\n      return 1;\n    },\n    showPlaceholder() {\n      contentVideo.style.opacity = \"0\";\n      contentVideo.style.visibility = \"hidden\";\n      if (!adContainerEl) {\n        const container = document.createElement(\"div\");\n        container.style.position = \"absolute\";\n        container.style.left = \"0\";\n        container.style.top = \"0\";\n        container.style.right = \"0\";\n        container.style.bottom = \"0\";\n        container.style.display = \"none\";\n        container.style.alignItems = \"center\";\n        container.style.justifyContent = \"center\";\n        container.style.pointerEvents = \"none\";\n        container.style.zIndex = \"10\";\n        container.style.backgroundColor = \"#000\";\n        contentVideo.parentElement?.appendChild(container);\n        adContainerEl = container;\n      }\n      if (adContainerEl) {\n        adContainerEl.style.display = \"flex\";\n        adContainerEl.style.pointerEvents = \"auto\";\n      }\n    },\n    hidePlaceholder() {\n      if (adContainerEl) {\n        adContainerEl.style.display = \"none\";\n        adContainerEl.style.pointerEvents = \"none\";\n      }\n      if (!adPlaying) {\n        contentVideo.style.visibility = \"visible\";\n        contentVideo.style.opacity = \"1\";\n      }\n    },\n    getLoadedAdDuration() {\n      return currentAd?.duration;\n    },\n    getLoadedAdId() {\n      return currentAd?.id;\n    },\n    getPodAdCount() {\n      return podAds.length;\n    },\n    getPodTotalDurationMs() {\n      return podAds.reduce(\n        (total, ad) => total + (ad.duration > 0 ? ad.duration * 1e3 : 0),\n        0\n      );\n    }\n  };\n}\n\n// src/utils/devUrl.ts\nvar PRIVATE_HOST_PATTERNS = [\n  /^localhost$/i,\n  /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n  /^0\\.0\\.0\\.0$/,\n  /^::1$/,\n  /^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n  /^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/,\n  /^172\\.(1[6-9]|2\\d|3[0-1])\\.\\d{1,3}\\.\\d{1,3}$/\n];\nfunction isLocalDevHost(hostname) {\n  const host = hostname.replace(/^\\[/, \"\").replace(/\\]$/, \"\").toLowerCase();\n  if (!host) return false;\n  if (host.endsWith(\".local\") || host.endsWith(\".localhost\")) return true;\n  return PRIVATE_HOST_PATTERNS.some((pattern) => pattern.test(host));\n}\nfunction toDevSafeUrl(rawUrl) {\n  if (!rawUrl) return rawUrl ?? \"\";\n  let url;\n  try {\n    url = new URL(rawUrl);\n  } catch {\n    return rawUrl;\n  }\n  if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n    return rawUrl;\n  }\n  if (!isLocalDevHost(url.hostname)) {\n    return rawUrl;\n  }\n  const cleanPath = url.pathname.replace(/\\/{2,}/g, \"/\") || \"/index.html\";\n  return `file://${cleanPath}`;\n}\n\n// src/sdk/pal.ts\nvar PAL_SDK_URL = \"https://imasdk.googleapis.com/pal/sdkloader/pal.js\";\nvar _nonceLoader;\nvar _palLoadPromise;\nfunction loadPalSdk() {\n  if (typeof window !== \"undefined\" && window.goog?.pal) {\n    return Promise.resolve();\n  }\n  if (_palLoadPromise) return _palLoadPromise;\n  _palLoadPromise = new Promise((resolve, reject) => {\n    const existing = document.querySelector(\n      'script[data-pal=\"true\"]'\n    );\n    if (existing) {\n      if (window.goog?.pal) {\n        resolve();\n        return;\n      }\n      const timeout = setTimeout(\n        () => reject(new Error(\"PAL SDK load timeout\")),\n        1e4\n      );\n      existing.addEventListener(\"load\", () => {\n        clearTimeout(timeout);\n        resolve();\n      });\n      existing.addEventListener(\"error\", () => {\n        clearTimeout(timeout);\n        reject(new Error(\"PAL SDK load failed\"));\n      });\n      return;\n    }\n    const script = document.createElement(\"script\");\n    script.src = PAL_SDK_URL;\n    script.async = true;\n    script.setAttribute(\"data-pal\", \"true\");\n    script.onload = () => resolve();\n    script.onerror = () => reject(new Error(\"PAL SDK load failed\"));\n    document.head.appendChild(script);\n  });\n  return _palLoadPromise;\n}\nfunction getOrCreateNonceLoader() {\n  if (_nonceLoader) return _nonceLoader;\n  const goog = window.goog;\n  const consentSettings = new goog.pal.ConsentSettings();\n  consentSettings.allowStorage = true;\n  _nonceLoader = new goog.pal.NonceLoader(consentSettings);\n  return _nonceLoader;\n}\nfunction createPalNonceManager() {\n  let currentNonce = \"\";\n  let currentNonceManager;\n  return {\n    async generateNonce(options = {}) {\n      try {\n        await loadPalSdk();\n        const loader = getOrCreateNonceLoader();\n        const goog = window.goog;\n        const request = new goog.pal.NonceRequest();\n        request.adWillAutoPlay = options.adWillAutoPlay ?? true;\n        request.adWillPlayMuted = options.adWillPlayMuted ?? false;\n        request.playerVolume = options.playerVolume ?? (request.adWillPlayMuted ? 0 : 1);\n        request.continuousPlayback = options.continuousPlayback ?? true;\n        request.descriptionUrl = toDevSafeUrl(\n          options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\")\n        );\n        request.iconsSupported = true;\n        request.playerType = \"StormcloudVideoPlayer\";\n        request.playerVersion = \"1.0\";\n        request.supportedApiFrameworks = \"2,7,9\";\n        request.url = toDevSafeUrl(\n          options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\")\n        );\n        request.videoWidth = options.videoWidth || 640;\n        request.videoHeight = options.videoHeight || 480;\n        if (options.ppid) request.ppid = options.ppid;\n        if (options.sessionId) request.sessionId = options.sessionId;\n        console.log(\n          \"[PAL] NonceRequest before generateNonce:\",\n          JSON.stringify({\n            adWillAutoPlay: request.adWillAutoPlay,\n            adWillPlayMuted: request.adWillPlayMuted,\n            playerVolume: request.playerVolume,\n            continuousPlayback: request.continuousPlayback,\n            descriptionUrl: request.descriptionUrl,\n            iconsSupported: request.iconsSupported,\n            playerType: request.playerType,\n            playerVersion: request.playerVersion,\n            supportedApiFrameworks: request.supportedApiFrameworks,\n            url: request.url,\n            videoWidth: request.videoWidth,\n            videoHeight: request.videoHeight,\n            ppid: request.ppid,\n            sessionId: request.sessionId\n          }, null, 2)\n        );\n        const manager = await loader.loadNonceManager(request);\n        currentNonceManager = manager;\n        currentNonce = manager.getNonce();\n        console.log(\"[PAL] Nonce generated successfully\");\n        return currentNonce;\n      } catch (error) {\n        console.warn(\"[PAL] Failed to generate nonce:\", error);\n        currentNonce = \"\";\n        currentNonceManager = void 0;\n        return \"\";\n      }\n    },\n    getCurrentNonce() {\n      return currentNonce;\n    },\n    injectNonce(vastTagUrl) {\n      if (!currentNonce || !vastTagUrl) return vastTagUrl;\n      try {\n        const url = new URL(vastTagUrl);\n        url.searchParams.delete(\"paln\");\n        url.searchParams.set(\"givn\", currentNonce);\n        return url.toString();\n      } catch {\n        let base = vastTagUrl.replace(/([?&])paln=[^&]*/g, \"\").replace(/[?&]$/, \"\");\n        const sep = base.includes(\"?\") ? \"&\" : \"?\";\n        return `${base}${sep}givn=${encodeURIComponent(currentNonce)}`;\n      }\n    },\n    sendPlaybackStart() {\n      try {\n        currentNonceManager?.sendPlaybackStart();\n      } catch {\n      }\n    },\n    sendPlaybackEnd() {\n      try {\n        currentNonceManager?.sendPlaybackEnd();\n      } catch {\n      }\n    },\n    sendAdClick() {\n      try {\n        currentNonceManager?.sendAdClick();\n      } catch {\n      }\n    },\n    sendAdTouch(event) {\n      try {\n        currentNonceManager?.sendAdTouch(event);\n      } catch {\n      }\n    },\n    reset() {\n      currentNonce = \"\";\n      currentNonceManager = void 0;\n    }\n  };\n}\n\n// src/utils/mqttConfig.ts\nvar DEFAULT_MQTT_CONFIG = {\n  enabled: true,\n  brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n  brokerPort: 8883,\n  wsPort: 8084,\n  username: \"for-sonifi\",\n  password: \"sonifi-mqtt\",\n  topicPrefix: \"adstorm/players\",\n  qos: 1\n};\nvar mqttConfig = { ...DEFAULT_MQTT_CONFIG };\nfunction applyMQTTConfig(overrides) {\n  Object.assign(mqttConfig, overrides);\n}\nfunction isMQTTEnabled() {\n  return mqttConfig.enabled;\n}\nfunction buildMQTTBrokerUrl() {\n  if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n  return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\nfunction buildPlayerTopic(licenseKey, channel) {\n  return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n\n// src/utils/mqttClient.ts\nvar import_mqtt = __toESM(require(\"mqtt\"), 1);\nvar LOG = \"[StormcloudVideoPlayer][MQTT]\";\nvar KEEPALIVE_SECONDS = 30;\nvar CONNECT_TIMEOUT_MS = 1e4;\nvar RECONNECT_BASE_MS = 5e3;\nvar RECONNECT_MAX_MS = 6e4;\nvar MAX_RECONNECT_ATTEMPTS = 8;\nvar COOLDOWN_MS = 10 * 6e4;\nvar client = null;\nvar status = \"disconnected\";\nvar reconnectAttempts = 0;\nvar reconnectTimer = null;\nvar stopped = false;\nfunction clearReconnectTimer() {\n  if (reconnectTimer) {\n    clearTimeout(reconnectTimer);\n    reconnectTimer = null;\n  }\n}\nfunction teardownClient() {\n  if (client) {\n    try {\n      client.removeAllListeners();\n      client.end(true);\n    } catch {\n    }\n    client = null;\n  }\n}\nfunction scheduleReconnect() {\n  if (stopped || !isMQTTEnabled() || reconnectTimer) return;\n  if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n    console.warn(\n      `${LOG} giving up after ${reconnectAttempts} attempts; cooling down for ${COOLDOWN_MS / 6e4}m`\n    );\n    teardownClient();\n    status = \"disconnected\";\n    reconnectTimer = setTimeout(() => {\n      reconnectTimer = null;\n      reconnectAttempts = 0;\n      openConnection();\n    }, COOLDOWN_MS);\n    return;\n  }\n  const delay = Math.min(\n    RECONNECT_MAX_MS,\n    RECONNECT_BASE_MS * 2 ** reconnectAttempts\n  );\n  const jitter = Math.floor(Math.random() * 1e3);\n  reconnectAttempts += 1;\n  reconnectTimer = setTimeout(() => {\n    reconnectTimer = null;\n    openConnection();\n  }, delay + jitter);\n}\nfunction openConnection() {\n  if (stopped || !isMQTTEnabled()) return;\n  teardownClient();\n  const url = buildMQTTBrokerUrl();\n  status = \"connecting\";\n  const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n  try {\n    client = import_mqtt.default.connect(url, {\n      clientId,\n      username: mqttConfig.username,\n      password: mqttConfig.password,\n      keepalive: KEEPALIVE_SECONDS,\n      clean: true,\n      // Disable MQTT.js internal reconnect; we manage reconnection ourselves.\n      reconnectPeriod: 0,\n      connectTimeout: CONNECT_TIMEOUT_MS,\n      queueQoSZero: false,\n      reschedulePings: true,\n      // Root-cause fix for the Tizen 4.0 \"Keepalive timeout\" loop: MQTT.js's\n      // default timerVariant \"auto\" runs the keepalive interval inside a\n      // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old\n      // WebKit) served from a file:// origin that worker can't tick reliably,\n      // so the keepalive counter trips onKeepaliveTimeout almost immediately\n      // after connect. Force the native setInterval timer instead; the main\n      // thread is free because video is decoded by the native AVPlay pipeline.\n      timerVariant: \"native\"\n    });\n  } catch (err) {\n    status = \"error\";\n    console.warn(`${LOG} connect() threw:`, err);\n    scheduleReconnect();\n    return;\n  }\n  client.on(\"connect\", () => {\n    status = \"connected\";\n    reconnectAttempts = 0;\n    clearReconnectTimer();\n    console.info(`${LOG} connected to ${url}`);\n  });\n  client.on(\"offline\", () => {\n    if (status === \"connected\") status = \"disconnected\";\n    console.warn(`${LOG} offline`);\n    scheduleReconnect();\n  });\n  client.on(\"error\", (err) => {\n    status = \"error\";\n    console.warn(`${LOG} error:`, err.message);\n    scheduleReconnect();\n  });\n  client.on(\"close\", () => {\n    if (status === \"connected\") status = \"disconnected\";\n    scheduleReconnect();\n  });\n}\nfunction initMQTTClient() {\n  if (client || !isMQTTEnabled()) return;\n  stopped = false;\n  reconnectAttempts = 0;\n  openConnection();\n}\nfunction ensureMQTTClient() {\n  if (isMQTTEnabled() && !client && !reconnectTimer) {\n    initMQTTClient();\n  }\n}\nfunction publishMQTT(topic, payload) {\n  if (!isMQTTEnabled()) {\n    return false;\n  }\n  ensureMQTTClient();\n  if (!client || !client.connected) {\n    return false;\n  }\n  try {\n    client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n    return true;\n  } catch (err) {\n    console.warn(`${LOG} publish failed on ${topic}:`, err);\n    return false;\n  }\n}\n\n// src/utils/vastEnvironmentSignals.ts\nvar AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nvar AIRY_WEBOS_APP_ID = \"com.freeairytv.webos\";\nvar AIRY_TIZEN_APP_ID = \"com.freeairytv.samsung\";\nvar AIRY_ROKU_APP_ID = \"com.freeairytv.roku\";\nvar AIRY_APP_NAME = \"AiryTV Movies & TV\";\nvar AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nvar CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\nvar PLAYER_ID_STORAGE_KEY = \"stormcloud.player.id\";\nvar LG_TEST_APP_ID = \"com.hulu.plus\";\nvar LG_TEST_APP_NAME = \"Hulu\";\nvar LG_TEST_CONTENT_URL = \"https://www.hulu.com/live-tv\";\nvar _lgTestDeviceId;\nfunction getLgTestDeviceId() {\n  if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();\n  return _lgTestDeviceId;\n}\nfunction isLgWebOS() {\n  if (typeof navigator === \"undefined\") return false;\n  return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);\n}\nfunction getDefaultAppId() {\n  if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n  const ua = navigator.userAgent;\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n  if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;\n  if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;\n  return AIRY_ANDROID_APP_ID;\n}\nvar DEVICE_ID_STORAGE_KEYS = [\n  \"rdid\",\n  \"ifa\",\n  \"advertisingId\",\n  \"advertising_id\",\n  \"deviceAdvertisingId\",\n  \"aaid\",\n  \"adid\",\n  \"rida\",\n  \"tifa\",\n  \"lgudid\"\n];\nvar ANDROID_ID_TYPES = /* @__PURE__ */ new Set([\"aaid\", \"adid\"]);\nfunction resolveVastEnvironmentSignals(isCtv) {\n  const bridgeSignals = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const lg = isCtv && isLgWebOS();\n  const deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId || (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : void 0);\n  const deviceIdType = bridgeSignals.deviceIdType || readStoredString(\"deviceIdType\") || readStoredString(\"idtype\") || platformDevice.deviceIdType || inferDeviceIdType() || (lg ? \"lgudid\" : void 0);\n  const platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;\n  const limitAdTracking = deviceId != null ? platformLat ?? readStoredLimitAdTracking() ?? false : void 0;\n  if (isCtv) {\n    return {\n      isCtv: true,\n      contentUrl: bridgeSignals.contentUrl || readStoredString(\"contentUrl\") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),\n      appId: bridgeSignals.appId || readStoredString(\"appId\") || readStoredString(\"msid\") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),\n      appName: bridgeSignals.appName || readStoredString(\"appName\") || readStoredString(\"an\") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),\n      sessionId: getOrCreateCtvSessionId(),\n      ...deviceId ? { deviceId } : {},\n      ...deviceIdType ? { deviceIdType } : {},\n      ...limitAdTracking != null ? { limitAdTracking } : {},\n      deviceTypeHint: 5\n    };\n  }\n  return {\n    isCtv: false,\n    ...deviceId ? { deviceId } : {},\n    ...deviceIdType ? { deviceIdType } : {},\n    ...limitAdTracking != null ? { limitAdTracking } : {}\n  };\n}\nfunction inferDeviceIdType() {\n  if (typeof navigator === \"undefined\") {\n    return void 0;\n  }\n  const ua = navigator.userAgent;\n  if (/Roku/i.test(ua)) return \"rida\";\n  if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n  if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n  if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n  if (/Android|Google TV/i.test(ua)) return \"aaid\";\n  if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n  return void 0;\n}\nfunction isEquivalentDeviceIdType(tagType, runtimeType) {\n  if (!tagType || !runtimeType) return false;\n  const tag = tagType.toLowerCase();\n  const runtime = runtimeType.toLowerCase();\n  if (tag === runtime) return true;\n  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\nfunction resolveNativeDeviceId() {\n  const bridgeSignals = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;\n  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {\n    return void 0;\n  }\n  return deviceId;\n}\nfunction getOrCreateStoredUuid(storageKey) {\n  if (typeof window === \"undefined\") {\n    return void 0;\n  }\n  const existing = readPersistentId(storageKey);\n  if (existing) {\n    writePersistentId(storageKey, existing);\n    return existing;\n  }\n  const id = createUuid();\n  writePersistentId(storageKey, id);\n  return id;\n}\nfunction getOrCreateCtvSessionId() {\n  const existing = readPersistentId(CTV_SESSION_STORAGE_KEY);\n  if (existing) {\n    writePersistentId(CTV_SESSION_STORAGE_KEY, existing);\n    return existing;\n  }\n  const sessionId = createUuid();\n  writePersistentId(CTV_SESSION_STORAGE_KEY, sessionId);\n  return sessionId;\n}\nfunction readPersistentId(storageKey) {\n  return readStoredString(storageKey) || readCookie(storageKey);\n}\nfunction writePersistentId(storageKey, value) {\n  try {\n    window.localStorage?.setItem(storageKey, value);\n  } catch {\n  }\n  writeCookie(storageKey, value);\n}\nvar PERSISTENT_ID_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5;\nfunction readCookie(name) {\n  if (typeof document === \"undefined\") {\n    return void 0;\n  }\n  try {\n    const prefix = encodeURIComponent(name) + \"=\";\n    const parts = document.cookie ? document.cookie.split(\";\") : [];\n    for (const part of parts) {\n      const entry = part.trim();\n      if (entry.startsWith(prefix)) {\n        return decodeURIComponent(entry.slice(prefix.length)) || void 0;\n      }\n    }\n  } catch {\n  }\n  return void 0;\n}\nfunction writeCookie(name, value) {\n  if (typeof document === \"undefined\") {\n    return;\n  }\n  try {\n    document.cookie = encodeURIComponent(name) + \"=\" + encodeURIComponent(value) + \";path=/;max-age=\" + PERSISTENT_ID_COOKIE_MAX_AGE + \";SameSite=Lax\";\n  } catch {\n  }\n}\nfunction createUuid() {\n  if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n  const bytes = new Uint8Array(16);\n  if (typeof crypto !== \"undefined\" && typeof crypto.getRandomValues === \"function\") {\n    crypto.getRandomValues(bytes);\n  } else {\n    let seed = Date.now() ^ Math.floor(performanceNow() * 1e3);\n    for (let i = 0; i < 16; i++) {\n      seed = seed * 1103515245 + 12345 & 2147483647;\n      bytes[i] = (seed ^ Math.floor(Math.random() * 256)) & 255;\n    }\n  }\n  bytes[6] = (bytes[6] ?? 0) & 15 | 64;\n  bytes[8] = (bytes[8] ?? 0) & 63 | 128;\n  let hex = \"\";\n  for (let i = 0; i < 16; i++) {\n    hex += (bytes[i] ?? 0).toString(16).padStart(2, \"0\");\n  }\n  return hex.slice(0, 8) + \"-\" + hex.slice(8, 12) + \"-\" + hex.slice(12, 16) + \"-\" + hex.slice(16, 20) + \"-\" + hex.slice(20, 32);\n}\nfunction performanceNow() {\n  try {\n    if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n      return performance.now();\n    }\n  } catch {\n  }\n  return 0;\n}\nfunction readPlatformNativeDeviceId() {\n  if (typeof window === \"undefined\") return {};\n  try {\n    const adinfo = window.webapis?.adinfo;\n    if (adinfo) {\n      const tifa = typeof adinfo.getTIFA === \"function\" ? adinfo.getTIFA() : adinfo.tifa;\n      if (typeof tifa === \"string\" && tifa && !isMacroPlaceholder(tifa)) {\n        const lat = typeof adinfo.isLATEnabled === \"function\" ? adinfo.isLATEnabled() : void 0;\n        return {\n          deviceId: tifa,\n          deviceIdType: \"tifa\",\n          ...typeof lat === \"boolean\" ? { limitAdTracking: lat } : {}\n        };\n      }\n    }\n  } catch {\n  }\n  try {\n    const webOSDev = window.webOSDev;\n    if (webOSDev) {\n      const lgudid = typeof webOSDev.LGUDID === \"function\" ? webOSDev.LGUDID() : webOSDev.lgudid ?? webOSDev.LGUDID;\n      if (typeof lgudid === \"string\" && lgudid) {\n        if (isZeroedAdId(lgudid)) {\n          return { deviceIdType: \"lgudid\", limitAdTracking: true };\n        }\n        if (!isMacroPlaceholder(lgudid)) {\n          return { deviceId: lgudid, deviceIdType: \"lgudid\", limitAdTracking: false };\n        }\n      }\n    }\n  } catch {\n  }\n  try {\n    const roku = window.Roku;\n    if (roku) {\n      const rida = typeof roku.getPublisherUniqueId === \"function\" ? roku.getPublisherUniqueId() : roku.rida;\n      if (typeof rida === \"string\" && rida && !isMacroPlaceholder(rida)) {\n        return { deviceId: rida, deviceIdType: \"rida\", limitAdTracking: false };\n      }\n    }\n  } catch {\n  }\n  return {};\n}\nvar ZEROED_AD_ID_PATTERNS = /* @__PURE__ */ new Set([\n  \"38400000-8cf0-11bd-b23e-10b96e40000d\",\n  \"00000000-0000-0000-0000-000000000000\"\n]);\nfunction isMacroPlaceholder(value) {\n  const t = value.trim();\n  return !t || /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());\n}\nfunction isZeroedAdId(value) {\n  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());\n}\nfunction readNativeBridgeSignals() {\n  if (typeof window === \"undefined\") {\n    return {};\n  }\n  const candidates = [\n    window.__STORMCLOUD_CTV_AD_INFO__,\n    window.__STORMCLOUD_CTV__,\n    window.stormcloudCtv,\n    window.AiryTV,\n    window.Android,\n    window.webOS,\n    window.tizen,\n    window.amazon\n  ].filter(Boolean);\n  for (const source of candidates) {\n    const contentUrl = readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) || void 0;\n    const appId = readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) || void 0;\n    const appName = readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || void 0;\n    const deviceId = readBridgeValue(source, [\n      \"rdid\",\n      \"ifa\",\n      \"advertisingId\",\n      \"adId\",\n      \"deviceId\",\n      \"lgudid\",\n      \"LGUDID\",\n      \"tifa\",\n      \"rida\",\n      \"afai\",\n      \"aaid\"\n    ]) || void 0;\n    if (!contentUrl && !deviceId && !appId && !appName) continue;\n    const deviceIdType = readBridgeValue(source, [\n      \"idtype\",\n      \"deviceIdType\",\n      \"advertisingIdType\",\n      \"idType\"\n    ]) || inferDeviceIdType();\n    const limitAdTracking = readBridgeBoolean(source, [\n      \"is_lat\",\n      \"limitAdTracking\",\n      \"limitedAdTracking\",\n      \"lat\"\n    ]);\n    return {\n      ...contentUrl ? { contentUrl } : {},\n      ...appId ? { appId } : {},\n      ...appName ? { appName } : {},\n      ...deviceId ? { deviceId } : {},\n      ...deviceId && deviceIdType ? { deviceIdType } : {},\n      ...deviceId && limitAdTracking != null ? { limitAdTracking } : {}\n    };\n  }\n  return {};\n}\nfunction readBridgeValue(source, keys) {\n  for (const key of keys) {\n    const value = source?.[key];\n    if (typeof value === \"string\" && value) {\n      return value;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = value.call(source);\n        if (typeof result === \"string\" && result) {\n          return result;\n        }\n      } catch {\n      }\n    }\n  }\n  return void 0;\n}\nfunction readBridgeBoolean(source, keys) {\n  for (const key of keys) {\n    const value = source?.[key];\n    const normalized = normalizeBoolean(value);\n    if (normalized != null) {\n      return normalized;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = normalizeBoolean(value.call(source));\n        if (result != null) {\n          return result;\n        }\n      } catch {\n      }\n    }\n  }\n  return void 0;\n}\nfunction readStoredDeviceId() {\n  for (const key of DEVICE_ID_STORAGE_KEYS) {\n    const value = readStoredString(key);\n    if (value) {\n      return value;\n    }\n  }\n  return void 0;\n}\nfunction readStoredString(key) {\n  if (typeof window === \"undefined\") {\n    return void 0;\n  }\n  try {\n    const value = window.localStorage?.getItem(key);\n    return value || void 0;\n  } catch {\n    return void 0;\n  }\n}\nfunction readStoredLimitAdTracking() {\n  return normalizeBoolean(\n    readStoredString(\"limitAdTracking\") || readStoredString(\"limitedAdTracking\") || readStoredString(\"is_lat\")\n  );\n}\nfunction normalizeBoolean(value) {\n  if (typeof value === \"boolean\") {\n    return value;\n  }\n  if (typeof value === \"number\") {\n    return value === 1;\n  }\n  if (typeof value === \"string\") {\n    const normalized = value.toLowerCase();\n    if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n      return true;\n    }\n    if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n      return false;\n    }\n  }\n  return void 0;\n}\n\n// src/utils/tracking.ts\nvar cachedBrowserId = null;\nfunction buildAnalyticsContext(config) {\n  const context = {};\n  if (config.debugAdTiming) {\n    context.debugAdTiming = true;\n  }\n  if (config.isLiveStream !== void 0) {\n    context.inputStreamType = config.isLiveStream ? \"live\" : \"vod\";\n  }\n  return context;\n}\nfunction getClientInfo() {\n  const ua = navigator.userAgent;\n  const platform = navigator.platform;\n  const vendor = navigator.vendor || \"\";\n  const maxTouchPoints = navigator.maxTouchPoints || 0;\n  const memory = navigator.deviceMemory || null;\n  const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n  const screenInfo = {\n    width: screen?.width,\n    height: screen?.height,\n    availWidth: screen?.availWidth,\n    availHeight: screen?.availHeight,\n    orientation: screen?.orientation?.type || \"\",\n    pixelDepth: screen?.pixelDepth\n  };\n  let deviceType = \"desktop\";\n  let brand = \"Unknown\";\n  let os = \"Unknown\";\n  let model = \"\";\n  let isSmartTV = false;\n  let isAndroid = false;\n  let isWebView = false;\n  let isWebApp = false;\n  if (ua.includes(\"Web0S\")) {\n    brand = \"LG\";\n    os = \"webOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n    model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n  } else if (ua.includes(\"Tizen\")) {\n    brand = \"Samsung\";\n    os = \"Tizen\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n    const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n    model = tizenMatch ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim() : \"Tizen TV\";\n  } else if (ua.includes(\"Philips\")) {\n    brand = \"Philips\";\n    os = \"Saphi\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n    brand = \"Sharp\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Android\") && (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))) {\n    brand = \"Sony\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Android\") && (ua.includes(\"NetCast\") || ua.includes(\"LG\"))) {\n    brand = \"LG\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n    brand = \"Roku\";\n    os = \"Roku OS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"AppleTV\")) {\n    brand = \"Apple\";\n    os = \"tvOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  }\n  if (ua.includes(\"Android\")) {\n    isAndroid = true;\n    os = \"Android\";\n    deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n    if (ua.includes(\"Android\") && (maxTouchPoints === 0 || ua.includes(\"Google TV\") || ua.includes(\"XiaoMi\"))) {\n      deviceType = \"tv\";\n      isSmartTV = true;\n      brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n    }\n    const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n    if (androidModelMatch && androidModelMatch[1]) {\n      model = androidModelMatch[1];\n    }\n  }\n  if (/iPad|iPhone|iPod/.test(ua)) {\n    os = \"iOS\";\n    deviceType = \"mobile\";\n    brand = \"Apple\";\n    if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n      deviceType = \"tablet\";\n    }\n  }\n  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n    if (ua.includes(\"Windows\")) {\n      os = \"Windows\";\n      deviceType = \"desktop\";\n    } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n      os = \"macOS\";\n      deviceType = \"desktop\";\n      if (maxTouchPoints > 1) deviceType = \"tablet\";\n    } else if (ua.includes(\"Linux\")) {\n      os = \"Linux\";\n      deviceType = \"desktop\";\n    }\n  }\n  if (brand === \"Unknown\") {\n    if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n    if (vendor.includes(\"Apple\")) brand = \"Apple\";\n    if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n  }\n  isWebView = /wv|WebView|Linux; U;/.test(ua);\n  if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n    isWebView = true;\n  }\n  isWebApp = window.matchMedia(\"(display-mode: standalone)\").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;\n  return {\n    brand,\n    os,\n    model: model || ua.substring(0, 50) + \"...\",\n    deviceType,\n    isSmartTV,\n    isAndroid,\n    isWebView,\n    isWebApp,\n    domain: window.location.hostname,\n    origin: window.location.origin,\n    path: window.location.pathname,\n    userAgent: ua,\n    vendor,\n    platform,\n    screen: screenInfo,\n    hardwareConcurrency,\n    deviceMemory: memory,\n    maxTouchPoints,\n    language: navigator.language,\n    languages: navigator.languages?.join(\",\") || \"\",\n    cookieEnabled: navigator.cookieEnabled,\n    doNotTrack: navigator.doNotTrack || \"\",\n    referrer: document.referrer,\n    visibilityState: document.visibilityState\n  };\n}\nasync function sha256Hex(input) {\n  if (typeof crypto !== \"undefined\" && crypto.subtle?.digest) {\n    try {\n      await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n      let encodedData;\n      if (typeof TextEncoder !== \"undefined\") {\n        encodedData = new TextEncoder().encode(input);\n      } else {\n        const utf8 = unescape(encodeURIComponent(input));\n        const buffer = new Uint8Array(utf8.length);\n        for (let i = 0; i < utf8.length; i++) {\n          buffer[i] = utf8.charCodeAt(i);\n        }\n        encodedData = buffer;\n      }\n      const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n      return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n    } catch {\n      console.warn(\n        \"[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash\"\n      );\n    }\n  }\n  let hash = 0;\n  for (let i = 0; i < input.length; i++) {\n    const char = input.charCodeAt(i);\n    hash = (hash << 5) - hash + char;\n    hash = hash & hash;\n  }\n  const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n  const timestamp = Date.now().toString(16).padStart(12, \"0\");\n  const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n  return (fallbackHash + timestamp + random).padEnd(64, \"0\");\n}\nfunction resolvePlayerIdentitySeed(clientInfo) {\n  const nativeDeviceId = resolveNativeDeviceId();\n  if (nativeDeviceId) {\n    return `device:${nativeDeviceId}`;\n  }\n  const persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);\n  if (persistedId) {\n    return `persisted:${persistedId}`;\n  }\n  return `fingerprint:${JSON.stringify(clientInfo)}`;\n}\nasync function getBrowserID(clientInfo) {\n  if (cachedBrowserId) {\n    return cachedBrowserId;\n  }\n  cachedBrowserId = await sha256Hex(resolvePlayerIdentitySeed(clientInfo));\n  return cachedBrowserId;\n}\nfunction canPublish(licenseKey) {\n  return Boolean(isMQTTEnabled() && licenseKey);\n}\nasync function buildPlayerMetricEvent(context = {}, flags = {}) {\n  const clientInfo = getClientInfo();\n  const debugAdTiming = !!context.debugAdTiming;\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] clientInfo: \", JSON.stringify(clientInfo, null, 2));\n  }\n  const playerId = await getBrowserID(clientInfo);\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] playerId: \", playerId);\n  }\n  const captureAt = flags.captureAt ?? (/* @__PURE__ */ new Date()).toISOString();\n  return {\n    player_id: playerId,\n    device_type: clientInfo.deviceType,\n    os: clientInfo.os.toLowerCase(),\n    ad_loaded: flags.adLoaded ?? false,\n    ad_detect: flags.adDetect ?? false,\n    capture_at: captureAt,\n    ...context.inputStreamType ? { input_stream_type: context.inputStreamType } : {}\n  };\n}\nfunction publishTracking(licenseKey, channel, body) {\n  ensureMQTTClient();\n  publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\nasync function sendInitialTracking(licenseKey, context = {}) {\n  if (!canPublish(licenseKey)) return;\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      adLoaded: false,\n      adDetect: false\n    });\n    publishTracking(licenseKey, \"metrics\", {\n      events: [metricEvent]\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n      error\n    );\n  }\n}\nasync function sendAdDetectTracking(licenseKey, adDetectInfo, context = {}) {\n  try {\n    await sendHeartbeat(licenseKey, context, {\n      adDetect: true,\n      captureAt: adDetectInfo.timestamp\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n      error\n    );\n  }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo, context = {}) {\n  try {\n    await sendHeartbeat(licenseKey, context, {\n      adLoaded: true,\n      captureAt: adLoadedInfo.timestamp\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n      error\n    );\n  }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo, context = {}) {\n  if (!canPublish(licenseKey)) return;\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      captureAt: adImpressionInfo.timestamp\n    });\n    publishTracking(licenseKey, \"heartbeat\", metricEvent);\n    publishTracking(licenseKey, \"impressions\", {\n      events: [\n        {\n          player_id: metricEvent.player_id,\n          ad_played_count: 1,\n          ad_url: adImpressionInfo.adUrl,\n          capture_at: adImpressionInfo.timestamp\n        }\n      ]\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n      error\n    );\n  }\n}\nasync function sendHeartbeat(licenseKey, context = {}, flags = {}) {\n  if (!canPublish(licenseKey)) return;\n  try {\n    const heartbeatData = await buildPlayerMetricEvent(context, flags);\n    publishTracking(licenseKey, \"heartbeat\", heartbeatData);\n  } catch (error) {\n    console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n  }\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n  if (typeof URLSearchParams !== \"undefined\") {\n    return;\n  }\n  class URLSearchParamsPolyfill {\n    constructor(init) {\n      this.params = /* @__PURE__ */ new Map();\n      if (typeof init === \"string\") {\n        this.parseQueryString(init);\n      } else if (init instanceof URLSearchParamsPolyfill) {\n        init.forEach((value, key) => {\n          this.append(key, value);\n        });\n      }\n    }\n    parseQueryString(query) {\n      const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n      if (!cleanQuery) return;\n      cleanQuery.split(\"&\").forEach((param) => {\n        const [key, value] = param.split(\"=\");\n        if (key) {\n          const decodedKey = this.safeDecodeURIComponent(key);\n          const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n          this.append(decodedKey, decodedValue);\n        }\n      });\n    }\n    safeDecodeURIComponent(str) {\n      try {\n        return decodeURIComponent(str.replace(/\\+/g, \" \"));\n      } catch (e) {\n        return str;\n      }\n    }\n    append(name, value) {\n      const values = this.params.get(name) || [];\n      values.push(String(value));\n      this.params.set(name, values);\n    }\n    delete(name) {\n      this.params.delete(name);\n    }\n    get(name) {\n      const values = this.params.get(name);\n      return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n    }\n    getAll(name) {\n      return this.params.get(name) || [];\n    }\n    has(name) {\n      return this.params.has(name);\n    }\n    set(name, value) {\n      this.params.set(name, [String(value)]);\n    }\n    forEach(callback) {\n      this.params.forEach((values, key) => {\n        values.forEach((value) => {\n          callback(value, key, this);\n        });\n      });\n    }\n    toString() {\n      const parts = [];\n      this.params.forEach((values, key) => {\n        values.forEach((value) => {\n          parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n        });\n      });\n      return parts.join(\"&\");\n    }\n  }\n  window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n  if (typeof TextEncoder !== \"undefined\") {\n    return;\n  }\n  class TextEncoderPolyfill {\n    constructor() {\n      this.encoding = \"utf-8\";\n    }\n    encode(str) {\n      const utf8 = [];\n      for (let i = 0; i < str.length; i++) {\n        let charcode = str.charCodeAt(i);\n        if (charcode < 128) {\n          utf8.push(charcode);\n        } else if (charcode < 2048) {\n          utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n        } else if (charcode < 55296 || charcode >= 57344) {\n          utf8.push(\n            224 | charcode >> 12,\n            128 | charcode >> 6 & 63,\n            128 | charcode & 63\n          );\n        } else {\n          i++;\n          charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n          utf8.push(\n            240 | charcode >> 18,\n            128 | charcode >> 12 & 63,\n            128 | charcode >> 6 & 63,\n            128 | charcode & 63\n          );\n        }\n      }\n      return new Uint8Array(utf8);\n    }\n  }\n  window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n  if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n    Promise.prototype.finally = function(callback) {\n      const constructor = this.constructor;\n      return this.then(\n        (value) => constructor.resolve(callback()).then(() => value),\n        (reason) => constructor.resolve(callback()).then(() => {\n          throw reason;\n        })\n      );\n    };\n  }\n}\nfunction polyfillObjectAssign() {\n  if (typeof Object.assign !== \"function\") {\n    Object.assign = function(target, ...sources) {\n      if (target == null) {\n        throw new TypeError(\"Cannot convert undefined or null to object\");\n      }\n      const to = Object(target);\n      for (let i = 0; i < sources.length; i++) {\n        const nextSource = sources[i];\n        if (nextSource != null) {\n          for (const nextKey in nextSource) {\n            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n              to[nextKey] = nextSource[nextKey];\n            }\n          }\n        }\n      }\n      return to;\n    };\n  }\n}\nfunction polyfillArrayFrom() {\n  if (!Array.from) {\n    Array.from = function(arrayLike, mapFn, thisArg) {\n      const items = Object(arrayLike);\n      if (arrayLike == null) {\n        throw new TypeError(\"Array.from requires an array-like object\");\n      }\n      const len = items.length >>> 0;\n      const result = new Array(len);\n      for (let i = 0; i < len; i++) {\n        if (mapFn) {\n          result[i] = mapFn.call(thisArg, items[i], i);\n        } else {\n          result[i] = items[i];\n        }\n      }\n      return result;\n    };\n  }\n}\nfunction polyfillStringStartsWith() {\n  if (!String.prototype.startsWith) {\n    String.prototype.startsWith = function(search, pos) {\n      pos = !pos || pos < 0 ? 0 : +pos;\n      return this.substring(pos, pos + search.length) === search;\n    };\n  }\n}\nfunction polyfillStringEndsWith() {\n  if (!String.prototype.endsWith) {\n    String.prototype.endsWith = function(search, length) {\n      if (length === void 0 || length > this.length) {\n        length = this.length;\n      }\n      return this.substring(length - search.length, length) === search;\n    };\n  }\n}\nfunction polyfillStringIncludes() {\n  if (!String.prototype.includes) {\n    String.prototype.includes = function(search, start) {\n      if (typeof start !== \"number\") {\n        start = 0;\n      }\n      if (start + search.length > this.length) {\n        return false;\n      }\n      return this.indexOf(search, start) !== -1;\n    };\n  }\n}\nfunction initializePolyfills() {\n  polyfillObjectAssign();\n  polyfillArrayFrom();\n  polyfillStringStartsWith();\n  polyfillStringEndsWith();\n  polyfillStringIncludes();\n  polyfillURLSearchParams();\n  polyfillTextEncoder();\n  polyfillPromiseFinally();\n}\n\n// src/utils/vastMacros.ts\nvar UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nvar INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nvar EXAMPLE_COM_URL = /example\\.com/i;\nvar CTV_UNSUPPORTED_PARAMS = [\n  \"description_url\",\n  \"tfcd\",\n  \"npa\",\n  \"min_ad_duration\",\n  \"max_ad_duration\",\n  \"unviewed_position_start\",\n  \"impl\",\n  \"vad_type\",\n  \"gdpr\",\n  \"gdpr_consent\",\n  \"us_privacy\"\n];\nvar INLINE_DEVICE_MACRO_REPLACEMENTS = [\n  { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n  { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n  { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n  { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n  { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n  { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator }\n];\nfunction isMacroPlaceholder2(value) {\n  if (value == null) return true;\n  const trimmed = value.trim();\n  if (!trimmed) return true;\n  if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n  return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\nfunction generateCorrelator() {\n  if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n    try {\n      const buf = new Uint32Array(2);\n      crypto.getRandomValues(buf);\n      const value = (buf[0] ?? 0) * 2097152 + ((buf[1] ?? 0) & 2097151);\n      if (value > 0) {\n        return String(value);\n      }\n    } catch {\n    }\n  }\n  return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\nfunction expandInlineMacroPlaceholders(baseUrl, ctx) {\n  let url = baseUrl;\n  for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n    const value = getValue(ctx);\n    if (value != null && value !== \"\") {\n      url = url.replace(pattern, encodeURIComponent(value));\n    }\n  }\n  return url;\n}\nfunction applyDeviceIdentityParams(params, ctx) {\n  const runtimeId = ctx.deviceId?.trim();\n  const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n  const tagRdid = params.get(\"rdid\");\n  const tagType = params.get(\"idtype\");\n  const tagLat = params.get(\"is_lat\");\n  const latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0;\n  if (runtimeId) {\n    params.set(\"rdid\", runtimeId);\n    params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n    params.set(\"is_lat\", latValue ?? (isMacroPlaceholder2(tagLat) ? \"0\" : tagLat));\n    return;\n  }\n  const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));\n  const tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));\n  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {\n    params.delete(\"rdid\");\n    params.delete(\"idtype\");\n    params.delete(\"is_lat\");\n    return;\n  }\n  if (tagRdidValid) {\n    if (isMacroPlaceholder2(tagType) && runtimeType) {\n      params.set(\"idtype\", runtimeType);\n    }\n    if (isMacroPlaceholder2(tagLat)) {\n      params.set(\"is_lat\", latValue ?? \"0\");\n    }\n    return;\n  }\n  params.delete(\"rdid\");\n  params.delete(\"idtype\");\n  params.delete(\"is_lat\");\n}\nfunction removeBrokenAppNameOrphans(params, appName) {\n  const toDelete = [];\n  params.forEach((_value, key) => {\n    if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n      toDelete.push(key);\n    }\n  });\n  if (appName && appName.includes(\"&\")) {\n    for (const suffix of appName.split(\"&\").slice(1)) {\n      const trimmed = suffix.replace(/^\\s+/, \"\");\n      if (!trimmed) continue;\n      toDelete.push(suffix, ` ${trimmed}`, trimmed);\n    }\n  }\n  for (const key of new Set(toDelete)) {\n    if (key) params.delete(key);\n  }\n}\nfunction normalizeVastTagUrl(raw) {\n  if (!raw) return raw;\n  try {\n    const url = new URL(raw);\n    const anValue = url.searchParams.get(\"an\");\n    if (anValue !== null) {\n      const orphanFragments = [];\n      url.searchParams.forEach((_value, key) => {\n        if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n          orphanFragments.push(key.trim());\n        }\n      });\n      if (orphanFragments.length > 0) {\n        const reconstructed = [anValue.replace(/\\s+$/, \"\"), ...orphanFragments].filter(Boolean).join(\" & \");\n        url.searchParams.forEach((_value, key) => {\n          if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n            url.searchParams.delete(key);\n          }\n        });\n        url.searchParams.set(\"an\", reconstructed);\n        return url.toString().replace(\n          /([?&]an=)([^&]*)/,\n          (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n        );\n      }\n    }\n    removeBrokenAppNameOrphans(url.searchParams);\n    return url.toString();\n  } catch {\n    return raw;\n  }\n}\nfunction applyVastMacros(baseUrl, ctx) {\n  const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n  let url;\n  try {\n    url = new URL(normalizeVastTagUrl(expandedUrl));\n  } catch {\n    return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n  }\n  const params = url.searchParams;\n  removeBrokenAppNameOrphans(params, ctx.appName);\n  params.set(\"correlator\", ctx.correlator);\n  params.set(\"scor\", ctx.streamCorrelator);\n  if (ctx.isCtv) {\n    for (const key of CTV_UNSUPPORTED_PARAMS) {\n      params.delete(key);\n    }\n  }\n  if (ctx.pod != null) {\n    params.set(\"pod\", String(ctx.pod));\n  }\n  params.delete(\"ppos\");\n  params.delete(\"lip\");\n  if (ctx.podMinDurationMs != null) {\n    params.set(\"pmnd\", String(Math.max(0, Math.round(ctx.podMinDurationMs))));\n  }\n  if (ctx.podMaxDurationMs != null) {\n    params.set(\"pmxd\", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));\n  }\n  if (ctx.podMaxAds != null) {\n    params.set(\"pmad\", String(Math.max(1, Math.round(ctx.podMaxAds))));\n  }\n  const requestUrl = ctx.contentUrl || ctx.pageUrl;\n  if (requestUrl) {\n    params.set(\"url\", requestUrl);\n    if (!ctx.isCtv) {\n      params.set(\"description_url\", requestUrl);\n    }\n  } else {\n    const existingUrl = params.get(\"url\") || \"\";\n    if (EXAMPLE_COM_URL.test(existingUrl)) {\n      params.delete(\"url\");\n      params.delete(\"description_url\");\n    }\n  }\n  if (ctx.adWillPlayMuted != null) {\n    params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n  }\n  if (ctx.adWillAutoPlay != null) {\n    params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n  }\n  if (ctx.appId) {\n    params.set(\"msid\", ctx.appId);\n  }\n  if (ctx.appName) {\n    removeBrokenAppNameOrphans(params, ctx.appName);\n    params.set(\"an\", ctx.appName);\n  }\n  if (ctx.sessionId) {\n    params.set(\"sid\", ctx.sessionId);\n  }\n  if (ctx.deviceTypeHint != null) {\n    params.set(\"dth\", String(ctx.deviceTypeHint));\n  } else if (ctx.isCtv) {\n    params.set(\"dth\", \"5\");\n  }\n  applyDeviceIdentityParams(params, ctx);\n  if (!ctx.isCtv) {\n    const consent = ctx.consent;\n    if (consent?.gdpr != null) {\n      params.set(\"gdpr\", consent.gdpr);\n    }\n    if (consent?.gdprConsent != null) {\n      params.set(\"gdpr_consent\", consent.gdprConsent);\n    }\n    if (consent?.usPrivacy != null) {\n      params.set(\"us_privacy\", consent.usPrivacy);\n    }\n  }\n  if (ctx.adTest) {\n    params.set(\"adtest\", \"on\");\n  }\n  const staleKeys = [];\n  params.forEach((value, key) => {\n    if (isMacroPlaceholder2(value)) {\n      staleKeys.push(key);\n    }\n  });\n  for (const key of staleKeys) {\n    params.delete(key);\n  }\n  removeBrokenAppNameOrphans(params, ctx.appName);\n  return url.toString();\n}\nfunction replaceCorrelatorFallback(baseUrl, correlator) {\n  const correlatorRegex = /([?&])correlator=([^&]*)/;\n  if (correlatorRegex.test(baseUrl)) {\n    return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n  }\n  const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n  return `${baseUrl}${sep}correlator=${correlator}`;\n}\nfunction fetchConsentSignals(timeoutMs = 1500) {\n  const signals = {};\n  if (typeof window === \"undefined\") {\n    return Promise.resolve(signals);\n  }\n  const tasks = [];\n  const tcfApi = window.__tcfapi;\n  if (typeof tcfApi === \"function\") {\n    tasks.push(\n      new Promise((resolve) => {\n        let settled = false;\n        try {\n          tcfApi(\"addEventListener\", 2, (tcData, success) => {\n            if (settled) return;\n            if (success && tcData && (tcData.eventStatus === \"tcloaded\" || tcData.eventStatus === \"useractioncomplete\")) {\n              settled = true;\n              signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n              if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n                signals.gdprConsent = tcData.tcString;\n              }\n              try {\n                tcfApi(\"removeEventListener\", 2, () => {\n                }, tcData.listenerId);\n              } catch {\n              }\n              resolve();\n            }\n          });\n        } catch {\n          resolve();\n        }\n        setTimeout(() => {\n          if (!settled) {\n            settled = true;\n            resolve();\n          }\n        }, timeoutMs);\n      })\n    );\n  }\n  const uspApi = window.__uspapi;\n  if (typeof uspApi === \"function\") {\n    tasks.push(\n      new Promise((resolve) => {\n        try {\n          uspApi(\"getUSPData\", 1, (data, success) => {\n            if (success && typeof data?.uspString === \"string\" && data.uspString) {\n              signals.usPrivacy = data.uspString;\n            }\n            resolve();\n          });\n        } catch {\n          resolve();\n        }\n        setTimeout(resolve, timeoutMs);\n      })\n    );\n  }\n  if (tasks.length === 0) {\n    return Promise.resolve(signals);\n  }\n  return Promise.all(tasks).then(() => signals);\n}\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n  const match = ua.match(/Chrome\\/(\\d+)/);\n  return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n  const match = ua.match(/AppleWebKit\\/(\\d+)/);\n  return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n  if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n    return navigator.userAgentData.platform;\n  }\n  const ua = navigator.userAgent;\n  if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n    return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n  }\n  if (/Win/i.test(ua)) {\n    return \"Win32\";\n  }\n  if (/Linux/i.test(ua)) {\n    return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n  }\n  if (/CrOS/i.test(ua)) {\n    return \"CrOS\";\n  }\n  return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n  const ua = navigator.userAgent;\n  const platform = getPlatform();\n  let name = \"Unknown\";\n  let version = \"0\";\n  let majorVersion = 0;\n  let isSmartTV = false;\n  let isLegacyTV = false;\n  let supportsModernJS = true;\n  let webOSVersion;\n  let tizenVersion;\n  let chromeVersionNum;\n  const chromeVersion = getChromeVersion(ua);\n  const webkitVersion = getWebKitVersion(ua);\n  chromeVersionNum = chromeVersion > 0 ? chromeVersion : void 0;\n  if (/Web0S|webOS|LG Browser|LGSTB/i.test(ua)) {\n    name = \"LG WebOS\";\n    isSmartTV = true;\n    let match = ua.match(/Web0S[/\\s]*([\\d.]+)/i) || ua.match(/webOS[/\\s]*([\\d.]+)/i);\n    if (!match || !match[1]) {\n      match = ua.match(/webOSTV[/\\s-]*([\\d.]+)/i) || ua.match(/webOS\\.TV[/\\s-]*([\\d.]+)/i);\n    }\n    if (match && match[1]) {\n      version = match[1];\n      const parts = version.split(\".\");\n      majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n      webOSVersion = majorVersion;\n    } else if (chromeVersion > 0) {\n      if (chromeVersion >= 79) {\n        webOSVersion = 6;\n        version = \"6.0\";\n        majorVersion = 6;\n      } else if (chromeVersion >= 68) {\n        webOSVersion = 5;\n        version = \"5.0\";\n        majorVersion = 5;\n      } else if (chromeVersion >= 53) {\n        webOSVersion = 4;\n        version = \"4.0\";\n        majorVersion = 4;\n      } else if (chromeVersion >= 38) {\n        webOSVersion = 3;\n        version = \"3.0\";\n        majorVersion = 3;\n      } else {\n        webOSVersion = 2;\n        version = \"2.0\";\n        majorVersion = 2;\n      }\n    } else {\n      version = \"Unknown\";\n      webOSVersion = void 0;\n    }\n    isLegacyTV = webOSVersion !== void 0 && webOSVersion < 3;\n  } else if (/Tizen/i.test(ua)) {\n    name = \"Samsung Tizen\";\n    isSmartTV = true;\n    const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n    version = match && match[1] ? match[1] : \"Unknown\";\n    if (version !== \"Unknown\") {\n      const parts = version.split(\".\");\n      majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n      tizenVersion = majorVersion;\n    }\n    isLegacyTV = tizenVersion !== void 0 && tizenVersion < 3;\n  } else if (/SMART-TV|SmartTV/i.test(ua)) {\n    name = \"Smart TV\";\n    isSmartTV = true;\n    isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n  } else if (/NetCast/i.test(ua)) {\n    name = \"LG NetCast\";\n    isSmartTV = true;\n    isLegacyTV = true;\n  } else if (/BRAVIA/i.test(ua)) {\n    name = \"Sony BRAVIA\";\n    isSmartTV = true;\n    isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n  } else {\n    if (chromeVersion > 0) {\n      name = \"Chrome\";\n      version = chromeVersion.toString();\n      majorVersion = chromeVersion;\n      if (chromeVersion < 50) {\n        supportsModernJS = false;\n      }\n    }\n    if (webkitVersion > 0 && webkitVersion < 600) {\n      supportsModernJS = false;\n    }\n  }\n  if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n    supportsModernJS = false;\n  }\n  if (typeof URLSearchParams === \"undefined\") {\n    supportsModernJS = false;\n  }\n  return {\n    name,\n    version,\n    majorVersion,\n    isSmartTV,\n    isLegacyTV,\n    platform,\n    supportsModernJS,\n    webOSVersion,\n    tizenVersion,\n    chromeVersion: chromeVersionNum\n  };\n}\nfunction getBrowserConfigOverrides() {\n  const browser = detectBrowser();\n  const overrides = {};\n  if (browser.isSmartTV) {\n    overrides.allowNativeHls = true;\n    overrides.pauseContentDuringAds = true;\n  }\n  return overrides;\n}\nfunction logBrowserInfo(debug = false) {\n  if (!debug) return;\n  const browser = detectBrowser();\n  console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n    browser: `${browser.name} ${browser.version}`,\n    platform: browser.platform,\n    isSmartTV: browser.isSmartTV,\n    isLegacyTV: browser.isLegacyTV,\n    supportsModernJS: browser.supportsModernJS,\n    ...browser.webOSVersion !== void 0 ? { webOSVersion: browser.webOSVersion } : {},\n    ...browser.tizenVersion !== void 0 ? { tizenVersion: browser.tizenVersion } : {},\n    ...browser.chromeVersion !== void 0 ? { chromeVersion: browser.chromeVersion } : {},\n    userAgent: navigator.userAgent\n  });\n}\n\n// src/player/Scte35Parser.ts\nfunction parseCueOutDuration(value) {\n  const num = parseFloat(value.trim());\n  if (!Number.isNaN(num)) return num;\n  const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n  if (match && match[1] != null) {\n    const dStr = match[1];\n    const d = parseFloat(dStr);\n    return Number.isNaN(d) ? void 0 : d;\n  }\n  return void 0;\n}\nfunction parseCueOutCont(value) {\n  const res = {};\n  const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n  const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n  if (elapsedMatch && elapsedMatch[1] != null) {\n    const e = parseFloat(elapsedMatch[1]);\n    if (!Number.isNaN(e)) res.elapsed = e;\n  }\n  if (durationMatch && durationMatch[1] != null) {\n    const d = parseFloat(durationMatch[1]);\n    if (!Number.isNaN(d)) res.duration = d;\n  }\n  if (!(\"elapsed\" in res) || !(\"duration\" in res)) {\n    const slashMatch = value.match(/([0-9.]+)\\s*\\/\\s*([0-9.]+)/);\n    if (slashMatch && slashMatch[1] && slashMatch[2]) {\n      const elapsed = parseFloat(slashMatch[1]);\n      const duration = parseFloat(slashMatch[2]);\n      if (!Number.isNaN(elapsed) && !(\"elapsed\" in res)) res.elapsed = elapsed;\n      if (!Number.isNaN(duration) && !(\"duration\" in res)) res.duration = duration;\n    }\n  }\n  if (\"elapsed\" in res || \"duration\" in res) return res;\n  return void 0;\n}\nfunction parseAttributeList(value) {\n  const attrs = {};\n  const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n  let match;\n  while ((match = regex.exec(value)) !== null) {\n    const key = match[1] ?? \"\";\n    let rawVal = match[3] ?? match[4] ?? \"\";\n    if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n      rawVal = rawVal.slice(1, -1);\n    }\n    if (key) {\n      attrs[key] = rawVal;\n    }\n  }\n  return attrs;\n}\nfunction toNumber(val) {\n  if (val == null) return void 0;\n  const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n  return Number.isNaN(n) ? void 0 : n;\n}\nfunction isManifestBasedMarker(marker) {\n  const raw = marker.raw;\n  if (!raw) return false;\n  if (raw.tag) {\n    const tag = String(raw.tag);\n    return tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-CUE-IN\") || tag.includes(\"EXT-X-DATERANGE\");\n  }\n  if (raw.id3) return false;\n  if (raw.splice_command_type) return false;\n  return false;\n}\nfunction decodeId3ValueToText(value) {\n  try {\n    if (typeof value === \"string\") return value;\n    const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n    const text = decoder.decode(value);\n    if (text && /[\\x20-\\x7E]/.test(text)) return text;\n    let out = \"\";\n    for (let i = 0; i < value.length; i++)\n      out += String.fromCharCode(value[i]);\n    return out;\n  } catch {\n    return void 0;\n  }\n}\nfunction getFragmentStartSeconds(frag) {\n  const candidates = [frag?.start, frag?.startPTS];\n  for (const candidate of candidates) {\n    if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n      return candidate;\n    }\n  }\n  return void 0;\n}\nfunction parseScte35FromId3(tag) {\n  const text = decodeId3ValueToText(tag.value);\n  if (!text) return void 0;\n  const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n  if (cueOutMatch) {\n    const arg = (cueOutMatch[1] ?? \"\").trim();\n    const dur = parseCueOutDuration(arg);\n    const marker = {\n      type: \"start\",\n      ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n      ...dur !== void 0 ? { durationSeconds: dur } : {},\n      raw: { id3: text }\n    };\n    return marker;\n  }\n  const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n  if (cueOutContMatch) {\n    const arg = (cueOutContMatch[1] ?? \"\").trim();\n    const cont = parseCueOutCont(arg);\n    const marker = {\n      type: \"progress\",\n      ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n      ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n      raw: { id3: text }\n    };\n    return marker;\n  }\n  const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n  if (cueInMatch) {\n    const marker = {\n      type: \"end\",\n      ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n      raw: { id3: text }\n    };\n    return marker;\n  }\n  const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n  if (daterangeMatch) {\n    const attrs = parseAttributeList(daterangeMatch[1] ?? \"\");\n    const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n    const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n    const klass = String(attrs[\"CLASS\"] ?? \"\");\n    const duration = toNumber(attrs[\"DURATION\"]);\n    if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n      const marker = {\n        type: \"start\",\n        ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n        ...duration !== void 0 ? { durationSeconds: duration } : {},\n        raw: { id3: text, attrs }\n      };\n      return marker;\n    }\n    if (hasScteIn) {\n      const marker = {\n        type: \"end\",\n        ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n        raw: { id3: text, attrs }\n      };\n      return marker;\n    }\n  }\n  if (/SCTE35-OUT/i.test(text)) {\n    const marker = {\n      type: \"start\",\n      ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n      raw: { id3: text }\n    };\n    return marker;\n  }\n  if (/SCTE35-IN/i.test(text)) {\n    const marker = {\n      type: \"end\",\n      ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n      raw: { id3: text }\n    };\n    return marker;\n  }\n  if (tag.value instanceof Uint8Array) {\n    const bin = parseScte35Binary(tag.value);\n    if (bin) return bin;\n  }\n  return void 0;\n}\nfunction normalizeFragmentPayload(payload) {\n  if (payload instanceof Uint8Array) {\n    return payload;\n  }\n  if (payload instanceof ArrayBuffer) {\n    return new Uint8Array(payload);\n  }\n  if (ArrayBuffer.isView(payload)) {\n    const view = payload;\n    return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n  }\n  return void 0;\n}\nfunction detectTsPacketFormat(data) {\n  const packetSizes = [188, 192, 204];\n  for (const packetSize of packetSizes) {\n    const tsPayloadOffset = packetSize === 192 ? 4 : 0;\n    for (let offset = 0; offset < packetSize; offset++) {\n      let matchedPackets = 0;\n      for (let packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize) {\n        if (data[packetStart + tsPayloadOffset] !== 71) {\n          break;\n        }\n        matchedPackets++;\n      }\n      if (matchedPackets >= 2) {\n        return { offset, packetSize, tsPayloadOffset };\n      }\n    }\n  }\n  return void 0;\n}\nfunction getPsiSectionStart(payload, payloadUnitStart) {\n  if (!payloadUnitStart) {\n    return void 0;\n  }\n  const pointerField = payload[0];\n  if (pointerField == null) {\n    return void 0;\n  }\n  const sectionStart = 1 + pointerField;\n  return sectionStart < payload.length ? sectionStart : void 0;\n}\nfunction getPsiSectionLength(data, offset) {\n  return ((data[offset + 1] ?? 0) & 15) << 8 | (data[offset + 2] ?? 0);\n}\nfunction parsePatSection(payload, payloadUnitStart, pmtPids) {\n  const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n  if (sectionStart == null || sectionStart + 8 >= payload.length) {\n    return;\n  }\n  if (payload[sectionStart] !== 0) {\n    return;\n  }\n  const sectionLength = getPsiSectionLength(payload, sectionStart);\n  const sectionEnd = Math.min(\n    payload.length,\n    sectionStart + 3 + sectionLength\n  );\n  for (let offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4) {\n    const programNumber = (payload[offset] ?? 0) << 8 | (payload[offset + 1] ?? 0);\n    const pid = ((payload[offset + 2] ?? 0) & 31) << 8 | (payload[offset + 3] ?? 0);\n    if (programNumber !== 0) {\n      pmtPids.add(pid);\n    }\n  }\n}\nfunction descriptorsIdentifyScte35(data, start, end) {\n  let offset = start;\n  while (offset + 2 <= end) {\n    const tag = data[offset] ?? 0;\n    const length = data[offset + 1] ?? 0;\n    const descriptorStart = offset + 2;\n    const descriptorEnd = descriptorStart + length;\n    if (descriptorEnd > end) {\n      return false;\n    }\n    const registration = length >= 4 ? String.fromCharCode(\n      data[descriptorStart] ?? 0,\n      data[descriptorStart + 1] ?? 0,\n      data[descriptorStart + 2] ?? 0,\n      data[descriptorStart + 3] ?? 0\n    ) : \"\";\n    if (tag === 138 || registration === \"CUEI\" || registration === \"SCTE\") {\n      return true;\n    }\n    offset = descriptorEnd;\n  }\n  return false;\n}\nfunction parsePmtSection(payload, payloadUnitStart, tsScte35Pids) {\n  const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n  if (sectionStart == null || sectionStart + 12 >= payload.length) {\n    return;\n  }\n  if (payload[sectionStart] !== 2) {\n    return;\n  }\n  const sectionLength = getPsiSectionLength(payload, sectionStart);\n  const sectionEnd = Math.min(\n    payload.length,\n    sectionStart + 3 + sectionLength\n  );\n  const programInfoLength = ((payload[sectionStart + 10] ?? 0) & 15) << 8 | (payload[sectionStart + 11] ?? 0);\n  let offset = sectionStart + 12 + programInfoLength;\n  while (offset + 5 <= sectionEnd - 4) {\n    const streamType = payload[offset] ?? 0;\n    const elementaryPid = ((payload[offset + 1] ?? 0) & 31) << 8 | (payload[offset + 2] ?? 0);\n    const esInfoLength = ((payload[offset + 3] ?? 0) & 15) << 8 | (payload[offset + 4] ?? 0);\n    const descriptorStart = offset + 5;\n    const descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);\n    if (streamType === 134 || streamType === 6 && descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {\n      tsScte35Pids.add(elementaryPid);\n    }\n    offset = descriptorStart + esInfoLength;\n  }\n}\nfunction hasProcessedTsScte35Section(section, processedSections) {\n  let checksum = 0;\n  for (let i = 0; i < section.length; i++) {\n    checksum = checksum * 31 + (section[i] ?? 0) >>> 0;\n  }\n  const key = `${section.length}:${checksum}`;\n  if (processedSections.has(key)) {\n    return true;\n  }\n  processedSections.add(key);\n  if (processedSections.size > 200) {\n    const firstKey = processedSections.values().next().value;\n    if (firstKey) {\n      processedSections.delete(firstKey);\n    }\n  }\n  return false;\n}\nfunction addScte35SectionMarker(section, markers, processedSections) {\n  if (section[0] !== 252 || hasProcessedTsScte35Section(section, processedSections)) {\n    return;\n  }\n  const marker = parseScte35Binary(section);\n  if (!marker) {\n    return;\n  }\n  marker.raw = {\n    ...typeof marker.raw === \"object\" && marker.raw ? marker.raw : {},\n    source: \"ts-packet\"\n  };\n  markers.push(marker);\n}\nfunction appendScte35Bytes(pid, bytes, assemblers, markers, processedSections) {\n  const assembler = assemblers.get(pid);\n  if (!assembler) {\n    return;\n  }\n  for (let i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++) {\n    assembler.bytes.push(bytes[i] ?? 0);\n  }\n  if (assembler.bytes.length >= assembler.expectedLength) {\n    assemblers.delete(pid);\n    addScte35SectionMarker(new Uint8Array(assembler.bytes), markers, processedSections);\n  }\n}\nfunction collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers, processedSections) {\n  if (payload.length === 0) {\n    return;\n  }\n  let offset = 0;\n  if (payloadUnitStart) {\n    const pointerField = payload[0] ?? 0;\n    const previousAssembler = assemblers.get(pid);\n    if (previousAssembler && pointerField > 0) {\n      appendScte35Bytes(\n        pid,\n        payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n        assemblers,\n        markers,\n        processedSections\n      );\n    }\n    assemblers.delete(pid);\n    offset = 1 + pointerField;\n  } else {\n    appendScte35Bytes(pid, payload, assemblers, markers, processedSections);\n    return;\n  }\n  while (offset + 3 <= payload.length) {\n    const tableId = payload[offset];\n    if (tableId == null || tableId === 255) {\n      return;\n    }\n    const sectionLength = getPsiSectionLength(payload, offset);\n    const totalLength = 3 + sectionLength;\n    if (sectionLength <= 0 || totalLength <= 3) {\n      return;\n    }\n    if (offset + totalLength <= payload.length) {\n      addScte35SectionMarker(\n        payload.subarray(offset, offset + totalLength),\n        markers,\n        processedSections\n      );\n      offset += totalLength;\n    } else {\n      assemblers.set(pid, {\n        bytes: Array.from(payload.subarray(offset)),\n        expectedLength: totalLength\n      });\n      return;\n    }\n  }\n}\nfunction parseScte35FromTsPackets(data, tsScte35Pids, pmtPids, processedSections) {\n  const packetInfo = detectTsPacketFormat(data);\n  if (!packetInfo) {\n    return [];\n  }\n  const markers = [];\n  const sectionAssemblers = /* @__PURE__ */ new Map();\n  for (let packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize) {\n    const tsStart = packetStart + packetInfo.tsPayloadOffset;\n    if (data[tsStart] !== 71) {\n      continue;\n    }\n    const secondByte = data[tsStart + 1];\n    const thirdByte = data[tsStart + 2];\n    const fourthByte = data[tsStart + 3];\n    if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {\n      continue;\n    }\n    const payloadUnitStart = (secondByte & 64) !== 0;\n    const pid = (secondByte & 31) << 8 | thirdByte;\n    const adaptationFieldControl = fourthByte >> 4 & 3;\n    const hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;\n    if (!hasPayload) {\n      continue;\n    }\n    let payloadStart = tsStart + 4;\n    if (adaptationFieldControl === 3) {\n      const adaptationLength = data[payloadStart];\n      if (adaptationLength == null) {\n        continue;\n      }\n      payloadStart += 1 + adaptationLength;\n    }\n    const payloadEnd = Math.min(tsStart + 188, data.length);\n    if (payloadStart >= payloadEnd || payloadStart >= data.length) {\n      continue;\n    }\n    const payload = data.subarray(payloadStart, payloadEnd);\n    if (pid === 0) {\n      parsePatSection(payload, payloadUnitStart, pmtPids);\n    } else if (pmtPids.has(pid)) {\n      parsePmtSection(payload, payloadUnitStart, tsScte35Pids);\n    } else if (tsScte35Pids.has(pid)) {\n      collectScte35SectionsFromPayload(\n        pid,\n        payload,\n        payloadUnitStart,\n        sectionAssemblers,\n        markers,\n        processedSections\n      );\n    }\n  }\n  return markers;\n}\nvar BitReader = class {\n  constructor(buf) {\n    this.buf = buf;\n    this.bytePos = 0;\n    this.bitPos = 0;\n  }\n  readBits(numBits) {\n    let result = 0;\n    while (numBits > 0) {\n      if (this.bytePos >= this.buf.length) return result;\n      const remainingInByte = 8 - this.bitPos;\n      const toRead = Math.min(numBits, remainingInByte);\n      const currentByte = this.buf[this.bytePos];\n      const shift = remainingInByte - toRead;\n      const mask = (1 << toRead) - 1 & 255;\n      const bits = currentByte >> shift & mask;\n      result = result << toRead | bits;\n      this.bitPos += toRead;\n      if (this.bitPos >= 8) {\n        this.bitPos = 0;\n        this.bytePos += 1;\n      }\n      numBits -= toRead;\n    }\n    return result >>> 0;\n  }\n  skipBits(n) {\n    this.readBits(n);\n  }\n  get bytePosition() {\n    return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n  }\n};\nfunction readSpliceTime(r, ptsAdjustmentTicks) {\n  const timeSpecifiedFlag = r.readBits(1) === 1;\n  if (!timeSpecifiedFlag) {\n    r.readBits(7);\n    return void 0;\n  }\n  r.readBits(6);\n  const high = r.readBits(1);\n  const low = r.readBits(32);\n  const ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks) % 8589934592;\n  return ptsTicks / 9e4;\n}\nfunction markerTypeFromSegmentationTypeId(segmentationTypeId) {\n  switch (segmentationTypeId) {\n    case 16:\n    case 34:\n    case 48:\n    case 50:\n    case 52:\n    case 54:\n      return \"start\";\n    case 17:\n    case 35:\n    case 49:\n    case 51:\n    case 53:\n    case 55:\n      return \"end\";\n    default:\n      return void 0;\n  }\n}\nfunction parseScte35SegmentationDescriptor(descriptor) {\n  if (descriptor.length < 11) {\n    return void 0;\n  }\n  const identifier = String.fromCharCode(\n    descriptor[0] ?? 0,\n    descriptor[1] ?? 0,\n    descriptor[2] ?? 0,\n    descriptor[3] ?? 0\n  );\n  if (identifier !== \"CUEI\") {\n    return void 0;\n  }\n  const segmentationEventId = (descriptor[4] ?? 0) * 16777216 + ((descriptor[5] ?? 0) << 16) + ((descriptor[6] ?? 0) << 8) + (descriptor[7] ?? 0);\n  const cancelIndicator = ((descriptor[8] ?? 0) & 128) !== 0;\n  if (cancelIndicator) {\n    return void 0;\n  }\n  const flags = descriptor[9] ?? 0;\n  const programSegmentationFlag = (flags & 128) !== 0;\n  const segmentationDurationFlag = (flags & 64) !== 0;\n  let offset = 10;\n  if (!programSegmentationFlag) {\n    const componentCount = descriptor[offset] ?? 0;\n    offset += 1 + componentCount * 6;\n    if (offset > descriptor.length) {\n      return void 0;\n    }\n  }\n  let durationSeconds = void 0;\n  if (segmentationDurationFlag) {\n    if (offset + 5 > descriptor.length) {\n      return void 0;\n    }\n    const durationTicks = (descriptor[offset] ?? 0) * 4294967296 + (descriptor[offset + 1] ?? 0) * 16777216 + ((descriptor[offset + 2] ?? 0) << 16) + ((descriptor[offset + 3] ?? 0) << 8) + (descriptor[offset + 4] ?? 0);\n    durationSeconds = durationTicks / 9e4;\n    offset += 5;\n  }\n  if (offset + 2 > descriptor.length) {\n    return void 0;\n  }\n  offset += 1;\n  const segmentationUpidLength = descriptor[offset] ?? 0;\n  offset += 1 + segmentationUpidLength;\n  if (offset >= descriptor.length) {\n    return void 0;\n  }\n  const segmentationTypeId = descriptor[offset] ?? 0;\n  const markerType = markerTypeFromSegmentationTypeId(segmentationTypeId);\n  if (!markerType) {\n    return void 0;\n  }\n  return {\n    type: markerType,\n    ...durationSeconds !== void 0 ? { durationSeconds } : {},\n    segmentationEventId\n  };\n}\nfunction parseScte35SegmentationDescriptors(data, offset) {\n  if (offset + 2 > data.length) {\n    return void 0;\n  }\n  const descriptorLoopLength = (data[offset] ?? 0) << 8 | (data[offset + 1] ?? 0);\n  let descriptorOffset = offset + 2;\n  const descriptorEnd = Math.min(\n    data.length,\n    descriptorOffset + descriptorLoopLength\n  );\n  while (descriptorOffset + 2 <= descriptorEnd) {\n    const descriptorTag = data[descriptorOffset] ?? 0;\n    const descriptorLength = data[descriptorOffset + 1] ?? 0;\n    const descriptorDataStart = descriptorOffset + 2;\n    const descriptorDataEnd = descriptorDataStart + descriptorLength;\n    if (descriptorDataEnd > descriptorEnd) {\n      return void 0;\n    }\n    if (descriptorTag === 2) {\n      const descriptorMarker = parseScte35SegmentationDescriptor(\n        data.subarray(descriptorDataStart, descriptorDataEnd)\n      );\n      if (descriptorMarker) {\n        return descriptorMarker;\n      }\n    }\n    descriptorOffset = descriptorDataEnd;\n  }\n  return void 0;\n}\nfunction parseScte35Binary(data) {\n  const r = new BitReader(data);\n  const tableId = r.readBits(8);\n  if (tableId !== 252) return void 0;\n  r.readBits(1);\n  r.readBits(1);\n  r.readBits(2);\n  const sectionLength = r.readBits(12);\n  if (sectionLength <= 0 || data.length < 3 + sectionLength) {\n    return void 0;\n  }\n  r.readBits(8);\n  r.readBits(1);\n  r.readBits(6);\n  const ptsAdjHigh = r.readBits(1);\n  const ptsAdjLow = r.readBits(32);\n  const ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;\n  r.readBits(8);\n  r.readBits(12);\n  const spliceCommandLength = r.readBits(12);\n  const spliceCommandType = r.readBits(8);\n  let markerType;\n  let durationSeconds = void 0;\n  let ptsSeconds = void 0;\n  let spliceEventId = void 0;\n  const commandBodyStart = r.bytePosition;\n  if (spliceCommandType === 5) {\n    spliceEventId = r.readBits(32);\n    const cancel = r.readBits(1) === 1;\n    r.readBits(7);\n    if (cancel) return void 0;\n    const outOfNetwork = r.readBits(1) === 1;\n    const programSpliceFlag = r.readBits(1) === 1;\n    const durationFlag = r.readBits(1) === 1;\n    const spliceImmediateFlag = r.readBits(1) === 1;\n    r.readBits(4);\n    markerType = outOfNetwork ? \"start\" : \"end\";\n    if (programSpliceFlag && !spliceImmediateFlag) {\n      ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n    } else if (!programSpliceFlag) {\n      const componentCount = r.readBits(8);\n      for (let i = 0; i < componentCount; i++) {\n        r.readBits(8);\n        if (!spliceImmediateFlag) {\n          const componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n          if (ptsSeconds === void 0) {\n            ptsSeconds = componentPtsSeconds;\n          }\n        }\n      }\n    }\n    if (durationFlag) {\n      r.readBits(6);\n      r.readBits(1);\n      const high = r.readBits(1);\n      const low = r.readBits(32);\n      const durationTicks = high * 4294967296 + low;\n      durationSeconds = durationTicks / 9e4;\n    }\n    r.readBits(16);\n    r.readBits(8);\n    r.readBits(8);\n  } else if (spliceCommandType === 6) {\n    ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n  } else {\n    return void 0;\n  }\n  const expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;\n  const descriptorMarker = parseScte35SegmentationDescriptors(\n    data,\n    expectedDescriptorOffset\n  );\n  if (descriptorMarker) {\n    markerType = descriptorMarker.type;\n    if (durationSeconds === void 0) {\n      durationSeconds = descriptorMarker.durationSeconds;\n    }\n  }\n  if (!markerType) {\n    return void 0;\n  }\n  const marker = {\n    type: markerType,\n    ...ptsSeconds !== void 0 ? { ptsSeconds } : {},\n    ...durationSeconds !== void 0 ? { durationSeconds } : {},\n    raw: {\n      splice_command_type: spliceCommandType,\n      ...spliceEventId !== void 0 ? { splice_event_id: spliceEventId } : {},\n      ...descriptorMarker?.segmentationEventId !== void 0 ? { segmentation_event_id: descriptorMarker.segmentationEventId } : {}\n    }\n  };\n  return marker;\n}\n\n// src/player/Scte35CueManager.ts\nvar Scte35CueManager = class {\n  constructor(debug, callbacks) {\n    this.pendingScte35Cues = /* @__PURE__ */ new Map();\n    this.recentScte35CueKeys = /* @__PURE__ */ new Map();\n    this.recentScte35CueLimit = 200;\n    this.tsScte35Pids = /* @__PURE__ */ new Set();\n    this.pmtPids = /* @__PURE__ */ new Set();\n    this.processedTsScte35Sections = /* @__PURE__ */ new Set();\n    this.debug = debug;\n    this.callbacks = callbacks;\n  }\n  get pendingScte35CueKey() {\n    return this.pendingScte35CueKeyValue;\n  }\n  set pendingScte35CueKey(value) {\n    this.pendingScte35CueKeyValue = value;\n  }\n  get activeScte35BreakKey() {\n    return this.activeScte35BreakKeyValue;\n  }\n  set activeScte35BreakKey(value) {\n    this.activeScte35BreakKeyValue = value;\n  }\n  get scheduledScte35BreakKey() {\n    return this.scheduledScte35BreakKeyValue;\n  }\n  set scheduledScte35BreakKey(value) {\n    this.scheduledScte35BreakKeyValue = value;\n  }\n  createScte35CueContext(source, readiness, frag) {\n    const context = { source, readiness };\n    if (typeof frag?.sn === \"number\") {\n      context.fragmentSn = frag.sn;\n    }\n    const fragmentStartSec = getFragmentStartSeconds(frag);\n    if (fragmentStartSec !== void 0) {\n      context.fragmentStartSeconds = fragmentStartSec;\n    }\n    return context;\n  }\n  onScte35Cue(marker, context) {\n    const cue = this.createScte35Cue(marker, context);\n    const pendingKey = this.getPendingScte35CueKey(cue);\n    if (context.readiness === \"early\") {\n      this.pendingScte35Cues.set(pendingKey, cue);\n      this.trimRecentScte35CueMaps();\n      if (marker.type === \"start\") {\n        this.callbacks.onEarlyStartCue(marker, context.fragmentSn, cue.key);\n      }\n      return;\n    }\n    if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n          key: cue.key,\n          activeScte35BreakKey: this.activeScte35BreakKeyValue,\n          inAdBreak: this.callbacks.isInAdBreak(),\n          source: cue.source\n        });\n      }\n      return;\n    }\n    if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue\", {\n          key: cue.key,\n          source: cue.source\n        });\n      }\n      return;\n    }\n    this.pendingScte35Cues.delete(pendingKey);\n    this.markScte35CueHandled(cue);\n    this.callbacks.onPlaybackCue(marker, cue.key);\n  }\n  activatePendingScte35CuesForFragment(frag) {\n    const fragmentSn = typeof frag?.sn === \"number\" ? frag.sn : void 0;\n    if (fragmentSn === void 0) {\n      return;\n    }\n    const matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(\n      ([, cue]) => cue.fragmentSn === fragmentSn\n    );\n    matchingCues.forEach(([pendingKey, cue]) => {\n      this.pendingScte35Cues.delete(pendingKey);\n      const context = {\n        source: cue.source,\n        readiness: \"playback\"\n      };\n      context.fragmentSn = fragmentSn;\n      const fragmentStartSec = cue.fragmentStartSeconds ?? getFragmentStartSeconds(frag);\n      if (fragmentStartSec !== void 0) {\n        context.fragmentStartSeconds = fragmentStartSec;\n      }\n      this.onScte35Cue(cue.marker, context);\n    });\n  }\n  createScte35Cue(marker, context) {\n    const cue = {\n      marker,\n      source: context.source,\n      readiness: context.readiness,\n      key: this.getScte35CueKey(marker, context)\n    };\n    if (context.fragmentSn !== void 0) {\n      cue.fragmentSn = context.fragmentSn;\n    }\n    if (context.fragmentStartSeconds !== void 0) {\n      cue.fragmentStartSeconds = context.fragmentStartSeconds;\n    }\n    return cue;\n  }\n  getScte35CueKey(marker, context) {\n    const raw = this.getScte35MarkerRaw(marker);\n    const spliceEventId = this.toIdentityString(raw?.splice_event_id);\n    if (spliceEventId) {\n      return `splice:${spliceEventId}`;\n    }\n    const segmentationEventId = this.toIdentityString(raw?.segmentation_event_id);\n    if (segmentationEventId) {\n      return `segmentation:${segmentationEventId}`;\n    }\n    const daterangeId = this.toIdentityString(raw?.attrs?.ID);\n    if (daterangeId) {\n      return `daterange:${daterangeId}`;\n    }\n    const scteValue = this.toIdentityString(raw?.attrs?.[\"SCTE35-OUT\"]) || this.toIdentityString(raw?.attrs?.[\"SCTE35-IN\"]);\n    if (scteValue) {\n      return `daterange-scte:${scteValue}`;\n    }\n    if (typeof marker.ptsSeconds === \"number\" && Number.isFinite(marker.ptsSeconds)) {\n      return `pts:${Math.round(marker.ptsSeconds * 2) / 2}`;\n    }\n    if (context.fragmentSn !== void 0) {\n      return `fragment:${context.fragmentSn}`;\n    }\n    return `${context.source}:wallclock:${Math.floor(Date.now() / 1e3)}`;\n  }\n  getPendingScte35CueKey(cue) {\n    return `${cue.marker.type}:${cue.key}:${cue.fragmentSn !== void 0 ? cue.fragmentSn : \"unknown\"}`;\n  }\n  getScte35MarkerRaw(marker) {\n    return typeof marker.raw === \"object\" && marker.raw !== null ? marker.raw : {};\n  }\n  toIdentityString(value) {\n    if (typeof value === \"number\" && Number.isFinite(value)) {\n      return String(value);\n    }\n    if (typeof value === \"string\" && value.trim().length > 0) {\n      return value.trim();\n    }\n    return void 0;\n  }\n  isStrongScte35CueKey(key) {\n    return !!(key && (key.startsWith(\"splice:\") || key.startsWith(\"segmentation:\") || key.startsWith(\"daterange:\") || key.startsWith(\"daterange-scte:\")));\n  }\n  hasRecentlyHandledScte35Cue(cue) {\n    if (this.activeScte35BreakKeyValue === cue.key || this.scheduledScte35BreakKeyValue === cue.key) {\n      return true;\n    }\n    const recentKey = `${cue.marker.type}:${cue.key}`;\n    return this.recentScte35CueKeys.has(recentKey);\n  }\n  markScte35CueHandled(cue) {\n    this.recentScte35CueKeys.set(`${cue.marker.type}:${cue.key}`, Date.now());\n    this.trimRecentScte35CueMaps();\n  }\n  trimRecentScte35CueMaps() {\n    while (this.recentScte35CueKeys.size > this.recentScte35CueLimit) {\n      const firstKey = this.recentScte35CueKeys.keys().next().value;\n      if (!firstKey) {\n        break;\n      }\n      this.recentScte35CueKeys.delete(firstKey);\n    }\n    while (this.pendingScte35Cues.size > this.recentScte35CueLimit) {\n      const firstKey = this.pendingScte35Cues.keys().next().value;\n      if (!firstKey) {\n        break;\n      }\n      this.pendingScte35Cues.delete(firstKey);\n    }\n  }\n  shouldAcceptScte35EndCue(cue) {\n    if (!this.callbacks.isInAdBreak()) {\n      return false;\n    }\n    if (this.isStrongScte35CueKey(this.activeScte35BreakKeyValue) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKeyValue !== cue.key) {\n      return false;\n    }\n    return true;\n  }\n};\n\n// src/player/AdConfigManager.ts\nvar AdConfigManager = class {\n  constructor(config, video) {\n    this.vmapBreaks = [];\n    this.consumedVmapBreakIds = /* @__PURE__ */ new Set();\n    this.streamCorrelator = generateCorrelator();\n    this.viewCorrelator = generateCorrelator();\n    this.consentSignals = {};\n    this.podCounter = 0;\n    this.podAssignedByPrefetch = false;\n    this.lastHeartbeatTime = 0;\n    this.defaultPodMaxAds = 6;\n    this.defaultPodMaxDurationMs = 12e4;\n    this.config = config;\n    this.video = video;\n  }\n  get debug() {\n    return !!this.config.debugAdTiming;\n  }\n  isVmapEnabled() {\n    return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n  }\n  async fetchAdConfiguration() {\n    if (this.isVmapEnabled()) {\n      await this.fetchAndParseVmap(this.config.vmapUrl);\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n      }\n      return;\n    }\n    const vastMode = this.config.vastMode || \"default\";\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n    }\n    if (vastMode === \"adstorm\") {\n      if (!this.config.licenseKey) {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n          );\n        }\n        return;\n      }\n      const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n      this.apiVastTagUrl = vastEndpoint;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n          vastEndpoint\n        );\n      }\n      return;\n    }\n    if (this.config.vastTagUrl) {\n      this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n      return;\n    }\n    const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n    if (this.debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n        apiUrl\n      );\n    }\n    const headers = {};\n    if (this.config.licenseKey) {\n      headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n    }\n    const response = await fetch(apiUrl, { headers });\n    if (!response.ok) {\n      if (this.debug) {\n        console.warn(\n          `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n        );\n      }\n      return;\n    }\n    const data = await response.json();\n    this.applyMqttConfigFromResponse(data);\n    const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n    if (imaPayload) {\n      let decodedPayload = imaPayload;\n      try {\n        decodedPayload = decodeURIComponent(imaPayload);\n      } catch {\n        console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n      }\n      console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n      this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n    } else {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n        );\n      }\n    }\n    const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n    if (numberAds != null && numberAds > 0) {\n      this.apiNumberAds = numberAds;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n          this.apiNumberAds\n        );\n      }\n    }\n  }\n  applyMqttConfigFromResponse(data) {\n    const mqttConfig2 = data.response?.mqtt_config;\n    if (!mqttConfig2 || typeof mqttConfig2 !== \"object\") {\n      return;\n    }\n    applyMQTTConfig(mqttConfig2);\n    if (this.debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Applied MQTT config from /ads/web:\",\n        mqttConfig2\n      );\n    }\n  }\n  async fetchAndParseVmap(vmapUrl) {\n    if (!vmapUrl.trim()) {\n      return;\n    }\n    try {\n      const response = await fetch(vmapUrl);\n      if (!response.ok) {\n        throw new Error(`Failed to fetch VMAP (${response.status})`);\n      }\n      const vmapXml = await response.text();\n      this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n      this.consumedVmapBreakIds.clear();\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n          vmapUrl\n        );\n      }\n    } catch (error) {\n      this.vmapBreaks = [];\n      this.consumedVmapBreakIds.clear();\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n      }\n    }\n  }\n  parseVmapToBreaks(vmapXml) {\n    if (typeof DOMParser === \"undefined\") {\n      return [];\n    }\n    const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n    if (doc.querySelector(\"parsererror\")) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n      }\n      return [];\n    }\n    const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n    let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(\n        doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n      );\n    }\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n        (el) => el.localName === \"AdBreak\"\n      );\n    }\n    const parsed = [];\n    adBreakNodes.forEach((node, index) => {\n      const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n      const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n      if (startTimeMs == null) {\n        return;\n      }\n      let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n      if (!adTagNode) {\n        adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") ?? void 0;\n      }\n      const adTagUrl = (adTagNode?.textContent || \"\").trim();\n      if (!adTagUrl) {\n        return;\n      }\n      const breakId = node.getAttribute(\"breakId\") || `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n      parsed.push({\n        id: breakId,\n        startTimeMs,\n        vastTagUrl: adTagUrl\n      });\n    });\n    parsed.sort((a, b) => {\n      const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n      const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n      return aStart - bStart;\n    });\n    return parsed;\n  }\n  parseVmapTimeOffsetToMs(timeOffset) {\n    if (!timeOffset) {\n      return void 0;\n    }\n    const normalized = timeOffset.trim().toLowerCase();\n    if (normalized === \"start\") {\n      return 0;\n    }\n    if (normalized === \"end\") {\n      return -1;\n    }\n    const hms = timeOffset.match(\n      /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n    );\n    if (hms) {\n      const [, hh, mm, ss, ms = \"0\"] = hms;\n      const hours = Number(hh);\n      const minutes = Number(mm);\n      const seconds = Number(ss);\n      const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n      return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;\n    }\n    const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n    if (percent) {\n      const ratio = Number(percent[1]) / 100;\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1e3 * ratio);\n      }\n      return void 0;\n    }\n    return void 0;\n  }\n  getAdBreakKey(adBreak) {\n    if (adBreak.id) {\n      return adBreak.id;\n    }\n    return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n  }\n  resolveBreakStartMs(adBreak) {\n    if (adBreak.startTimeMs >= 0) {\n      return adBreak.startTimeMs;\n    }\n    if (adBreak.startTimeMs === -1) {\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1e3);\n      }\n    }\n    return void 0;\n  }\n  findCurrentOrNextBreak(nowMs) {\n    const schedule = this.vmapBreaks;\n    let candidate;\n    const tol = this.config.driftToleranceMs ?? 1e3;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n      if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))) {\n        candidate = b;\n      }\n    }\n    return candidate;\n  }\n  findBreakForTime(nowMs) {\n    const schedule = this.vmapBreaks;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n      if (b.durationMs) {\n        const end = breakStartMs + b.durationMs;\n        if (nowMs >= breakStartMs && nowMs < end) {\n          return b;\n        }\n        continue;\n      }\n      if (nowMs >= breakStartMs) {\n        return b;\n      }\n    }\n    return void 0;\n  }\n  selectVastTagsForBreak(b) {\n    if (!b || !b.vastTagUrl) return void 0;\n    if (b.vastTagUrl.includes(\",\")) {\n      return b.vastTagUrl.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n    }\n    return [b.vastTagUrl];\n  }\n  beginNewAdPod() {\n    this.podCounter++;\n  }\n  resolvePodParams(breakDurationMs) {\n    const maxDurationMs = breakDurationMs != null && breakDurationMs > 0 ? breakDurationMs : this.config.podMaxDurationMs != null && this.config.podMaxDurationMs > 0 ? this.config.podMaxDurationMs : this.defaultPodMaxDurationMs;\n    const maxAds = this.config.podMaxAds && this.config.podMaxAds > 0 ? this.config.podMaxAds : this.apiNumberAds && this.apiNumberAds > 0 ? this.apiNumberAds : this.defaultPodMaxAds;\n    const minDurationMs = this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;\n    return { maxAds, minDurationMs, maxDurationMs };\n  }\n  generatePodVastUrl(baseUrl, podParams, adPlayer, palNonce, inAdBreak) {\n    const adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;\n    const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n    const urlWithMacros = applyVastMacros(baseUrl, {\n      correlator: this.viewCorrelator,\n      streamCorrelator: this.streamCorrelator,\n      pod: this.podCounter > 0 ? this.podCounter : void 0,\n      podMaxAds: podParams.maxAds,\n      podMinDurationMs: podParams.minDurationMs,\n      podMaxDurationMs: podParams.maxDurationMs,\n      isCtv: envSignals.isCtv,\n      contentUrl: envSignals.contentUrl,\n      pageUrl: !envSignals.isCtv && typeof window !== \"undefined\" ? toDevSafeUrl(window.location.href) : void 0,\n      adWillPlayMuted,\n      adWillAutoPlay: !!this.config.autoplay,\n      appId: envSignals.appId,\n      appName: envSignals.appName,\n      sessionId: envSignals.sessionId,\n      deviceId: envSignals.deviceId,\n      deviceIdType: envSignals.deviceIdType,\n      limitAdTracking: envSignals.limitAdTracking,\n      deviceTypeHint: envSignals.deviceTypeHint,\n      adTest: this.config.adTest,\n      consent: this.consentSignals\n    });\n    const finalUrl = palNonce.injectNonce(urlWithMacros);\n    console.log(\n      `[StormcloudVideoPlayer] Resolved optimized-pod request URL (pod=${this.podCounter}, pmad=${podParams.maxAds}, pmnd=${podParams.minDurationMs}, pmxd=${podParams.maxDurationMs ?? \"?\"}):`,\n      finalUrl\n    );\n    return finalUrl;\n  }\n  // --- Tracking ---\n  initializeTracking() {\n    sendInitialTracking(this.config.licenseKey, buildAnalyticsContext(this.config)).then(() => {\n      this.heartbeatInterval = window.setInterval(() => {\n        this.sendHeartbeatIfNeeded();\n      }, 5e3);\n    }).catch((error) => {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n          error\n        );\n      }\n      this.heartbeatInterval = window.setInterval(() => {\n        this.sendHeartbeatIfNeeded();\n      }, 5e3);\n    });\n  }\n  sendHeartbeatIfNeeded() {\n    const now = Date.now();\n    if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n      this.lastHeartbeatTime = now;\n      sendHeartbeat(this.config.licenseKey, buildAnalyticsContext(this.config)).catch((error) => {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n            error\n          );\n        }\n      });\n    }\n  }\n  destroyTracking() {\n    if (this.heartbeatInterval) {\n      clearInterval(this.heartbeatInterval);\n      this.heartbeatInterval = void 0;\n    }\n  }\n};\n\n// src/player/AdTimingService.ts\nvar AdTimingService = class {\n  constructor(config, video, callbacks) {\n    this.adRequestWatchdogToken = null;\n    this.adFailsafeToken = null;\n    this.ptsDriftEmaMs = 0;\n    this.adBreakPlayedDurationMs = 0;\n    this.adBreakEpoch = 0;\n    this.adRequestTokenCounter = 0;\n    this.activeAdRequestToken = null;\n    this.currentAdIndex = 0;\n    this.totalAdsInBreak = 0;\n    this.totalAdRequestsInBreak = 0;\n    this.maxTotalAdRequestsPerBreak = 10;\n    this.lastAdRequestTime = 0;\n    this.consecutiveFailures = 0;\n    this.maxConsecutiveFailures = 5;\n    this.minAdRequestIntervalMs = 3e3;\n    this.backoffBaseMs = 1e3;\n    this.maxBackoffMs = 15e3;\n    this.defaultMinRemainingMsToStartAd = 4e3;\n    this.failedVastUrls = /* @__PURE__ */ new Set();\n    this.temporaryFailureUrls = /* @__PURE__ */ new Map();\n    this.temporaryFailureCooldownMs = 3e4;\n    this.globalConsecutiveNoFills = 0;\n    this.globalNoFillThreshold = 3;\n    this.globalNoFillCooldownUntil = 0;\n    this.globalNoFillBackoffBaseMs = 5e3;\n    this.globalNoFillBackoffMaxMs = 6e4;\n    this.globalLastGamRequestTime = 0;\n    this.globalMinGamIntervalMs = 3e3;\n    this.config = config;\n    this.video = video;\n    this.callbacks = callbacks;\n  }\n  get debug() {\n    return !!this.config.debugAdTiming;\n  }\n  // --- Ad stop timer ---\n  scheduleAdStopCountdown(remainingMs) {\n    this.clearAdStopTimer();\n    const ms = Math.max(0, Math.floor(remainingMs));\n    if (ms === 0) {\n      this.ensureAdStoppedByTimer();\n      return;\n    }\n    this.adStopTimerId = window.setTimeout(() => {\n      this.ensureAdStoppedByTimer();\n    }, ms);\n  }\n  clearAdStopTimer() {\n    if (this.adStopTimerId != null) {\n      clearTimeout(this.adStopTimerId);\n      this.adStopTimerId = void 0;\n    }\n  }\n  ensureAdStoppedByTimer() {\n    this.adStopTimerId = void 0;\n    this.callbacks.onAdStopTimerFired();\n  }\n  // --- Ad start timer ---\n  scheduleAdStartIn(delayMs, marker = { type: \"start\" }, cueKey) {\n    this.clearAdStartTimer();\n    const ms = Math.max(0, Math.floor(delayMs));\n    if (ms === 0) {\n      this.callbacks.onAdStartTimerFired(marker, cueKey);\n      return;\n    }\n    this.adStartTimerId = window.setTimeout(() => {\n      this.callbacks.onAdStartTimerFired(marker, cueKey);\n    }, ms);\n  }\n  clearAdStartTimer() {\n    if (this.adStartTimerId != null) {\n      clearTimeout(this.adStartTimerId);\n      this.adStartTimerId = void 0;\n    }\n  }\n  // --- PTS drift ---\n  updatePtsDrift(ptsSecondsSample) {\n    const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n    if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n    const alpha = 0.1;\n    this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n  }\n  resolveScteBreakStartWallClockMs(marker) {\n    const nowWallClockMs = Date.now();\n    if (typeof marker.ptsSeconds !== \"number\") {\n      return nowWallClockMs;\n    }\n    const nowMs = this.video.currentTime * 1e3;\n    const estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n    const deltaMs = marker.ptsSeconds * 1e3 - estimatedCurrentPtsMs;\n    if (!Number.isFinite(deltaMs)) {\n      return nowWallClockMs;\n    }\n    return nowWallClockMs + Math.floor(deltaMs);\n  }\n  // --- Duration boundary ---\n  setAdBreakDurationBoundary(durationMs) {\n    this.expectedAdBreakDurationMs = durationMs;\n    if (durationMs != null && this.currentAdBreakStartWallClockMs != null) {\n      this.scteAdBreakEndWallClockMs = this.currentAdBreakStartWallClockMs + durationMs;\n    } else {\n      this.scteAdBreakEndWallClockMs = void 0;\n    }\n  }\n  scheduleAdStopAtBreakBoundary() {\n    if (this.expectedAdBreakDurationMs == null) {\n      return;\n    }\n    this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());\n  }\n  // --- Duration budget ---\n  getWallClockRemainingAdMs() {\n    const endWallClockMs = this.getAdBreakEndWallClockMs();\n    if (endWallClockMs != null) {\n      return Math.max(0, endWallClockMs - Date.now());\n    }\n    return 0;\n  }\n  getAdBreakEndWallClockMs() {\n    if (this.scteAdBreakEndWallClockMs != null) {\n      return this.scteAdBreakEndWallClockMs;\n    }\n    if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null) {\n      return void 0;\n    }\n    return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;\n  }\n  getDurationBudgetRemainingMs() {\n    if (this.expectedAdBreakDurationMs == null) {\n      return 0;\n    }\n    return Math.max(0, this.expectedAdBreakDurationMs - this.adBreakPlayedDurationMs);\n  }\n  getLoadedAdDurationMs(adController) {\n    const durationSec = adController.getLoadedAdDuration?.();\n    if (durationSec == null || durationSec <= 0) {\n      return 0;\n    }\n    return Math.round(durationSec * 1e3);\n  }\n  adFitsRemainingBudget(durationMs) {\n    if (durationMs <= 0) {\n      return true;\n    }\n    return durationMs <= this.getDurationBudgetRemainingMs();\n  }\n  logAdDurationDecision(accepted, durationMs, adController) {\n    if (!this.debug) {\n      return;\n    }\n    const remainingBudget = this.getDurationBudgetRemainingMs();\n    const adId = adController.getLoadedAdId?.() ?? \"unknown\";\n    if (accepted) {\n      console.log(\n        `[AD-DURATION] Accepted ad id=${adId}, duration=${durationMs}ms, budget remaining after play=${Math.max(0, remainingBudget - durationMs)}ms`\n      );\n    } else {\n      console.log(\n        `[AD-DURATION] Rejected ad id=${adId}, duration=${durationMs}ms exceeds remaining budget=${remainingBudget}ms \\u2014 requesting another ad`\n      );\n    }\n  }\n  recordPlayedAdDuration(adController) {\n    const durationMs = this.getLoadedAdDurationMs(adController);\n    if (durationMs <= 0) {\n      return;\n    }\n    this.adBreakPlayedDurationMs += durationMs;\n    if (this.debug) {\n      console.log(\n        `[AD-DURATION] Played ${durationMs}ms \\u2014 total played=${this.adBreakPlayedDurationMs}ms / ${this.expectedAdBreakDurationMs ?? \"?\"}ms`\n      );\n    }\n  }\n  ensureLoadedAdFitsBudget(adController) {\n    const durationMs = this.getLoadedAdDurationMs(adController);\n    const fits = this.adFitsRemainingBudget(durationMs);\n    this.logAdDurationDecision(fits, durationMs, adController);\n    return fits;\n  }\n  rejectLoadedAdForDuration(adController) {\n    try {\n      adController.destroy();\n    } catch {\n    }\n  }\n  markAdStarted() {\n    this.currentAdIndex++;\n    this.totalAdsInBreak = this.currentAdIndex;\n    this.totalAdRequestsInBreak++;\n    this.lastAdRequestTime = Date.now();\n  }\n  notePodAdStarted() {\n    this.currentAdIndex++;\n    this.totalAdsInBreak = this.currentAdIndex;\n  }\n  getRemainingAdMs() {\n    const wallClockRemaining = this.getWallClockRemainingAdMs();\n    const budgetRemaining = this.getDurationBudgetRemainingMs();\n    if (this.expectedAdBreakDurationMs == null) {\n      return wallClockRemaining;\n    }\n    return Math.min(wallClockRemaining, budgetRemaining);\n  }\n  getMinRemainingMsToStartAd() {\n    const configured = this.config.minRemainingMsToStartAd;\n    if (typeof configured === \"number\" && configured >= 0) {\n      return configured;\n    }\n    return this.defaultMinRemainingMsToStartAd;\n  }\n  hasTimeToStartAnotherAd() {\n    const minRemaining = this.getMinRemainingMsToStartAd();\n    return this.getWallClockRemainingAdMs() > minRemaining && this.getDurationBudgetRemainingMs() > minRemaining;\n  }\n  // --- Circuit breaker ---\n  isTemporaryAdError(error) {\n    const message = error?.message?.toLowerCase() || \"\";\n    if (message.includes(\"no ads available\") || message.includes(\"no fill\") || message.includes(\"nofill\")) {\n      return true;\n    }\n    if (message.includes(\"timeout\")) {\n      return true;\n    }\n    if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n      return true;\n    }\n    if (message.includes(\"ad playback error\")) {\n      return true;\n    }\n    return false;\n  }\n  isUrlInCooldown(vastTagUrl) {\n    const failureTime = this.temporaryFailureUrls.get(vastTagUrl);\n    if (failureTime == null) {\n      return false;\n    }\n    const elapsed = Date.now() - failureTime;\n    if (elapsed >= this.temporaryFailureCooldownMs) {\n      this.temporaryFailureUrls.delete(vastTagUrl);\n      return false;\n    }\n    return true;\n  }\n  cleanupTemporaryFailures() {\n    const now = Date.now();\n    for (const [url, timestamp] of this.temporaryFailureUrls) {\n      if (now - timestamp >= this.temporaryFailureCooldownMs) {\n        this.temporaryFailureUrls.delete(url);\n      }\n    }\n  }\n  isGamInCooldown() {\n    return Date.now() < this.globalNoFillCooldownUntil;\n  }\n  recordGamNoFill() {\n    this.globalConsecutiveNoFills++;\n    if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {\n      const exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;\n      const backoff = Math.min(\n        this.globalNoFillBackoffBaseMs * Math.pow(2, exponent),\n        this.globalNoFillBackoffMaxMs\n      );\n      this.globalNoFillCooldownUntil = Date.now() + backoff;\n      if (this.debug) {\n        console.log(\n          `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n        );\n      }\n    }\n  }\n  resetGamNoFillCounter() {\n    if (this.globalConsecutiveNoFills > 0 && this.debug) {\n      console.log(\n        `[CIRCUIT-BREAKER] Resetting no-fill counter (was ${this.globalConsecutiveNoFills})`\n      );\n    }\n    this.globalConsecutiveNoFills = 0;\n    this.globalNoFillCooldownUntil = 0;\n  }\n  async enforceGlobalRateLimit() {\n    const now = Date.now();\n    const elapsed = now - this.globalLastGamRequestTime;\n    if (elapsed < this.globalMinGamIntervalMs) {\n      const waitMs = this.globalMinGamIntervalMs - elapsed;\n      if (this.debug) {\n        console.log(`[RATE-LIMIT] Waiting ${waitMs}ms before next GAM request`);\n      }\n      await new Promise((resolve) => setTimeout(resolve, waitMs));\n    }\n    this.globalLastGamRequestTime = Date.now();\n  }\n  // --- Watchdog ---\n  startAdRequestWatchdog(token) {\n    this.clearAdRequestWatchdog();\n    const timeoutMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n    this.adRequestWatchdogToken = token;\n    this.adRequestWatchdogId = window.setTimeout(() => {\n      if (this.adRequestWatchdogToken !== token) {\n        return;\n      }\n      this.adRequestWatchdogId = void 0;\n      this.adRequestWatchdogToken = null;\n      if (this.activeAdRequestToken === token) {\n        this.activeAdRequestToken = null;\n      }\n      this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n      this.callbacks.onWatchdogTimeout();\n    }, timeoutMs);\n    this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n  }\n  clearAdRequestWatchdog() {\n    if (this.adRequestWatchdogId != null) {\n      clearTimeout(this.adRequestWatchdogId);\n      this.adRequestWatchdogId = void 0;\n    }\n    if (this.adRequestWatchdogToken != null) {\n      this.logAdState(\"ad_request_watchdog_cleared\", {\n        token: this.adRequestWatchdogToken\n      });\n      this.adRequestWatchdogToken = null;\n    }\n  }\n  // --- Failsafe ---\n  startAdFailsafeTimer(token) {\n    this.clearAdFailsafeTimer();\n    const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;\n    this.adFailsafeToken = token;\n    this.adFailsafeTimerId = window.setTimeout(() => {\n      if (this.adFailsafeToken !== token) {\n        return;\n      }\n      this.adFailsafeTimerId = void 0;\n      this.adFailsafeToken = null;\n      if (this.activeAdRequestToken === token) {\n        this.activeAdRequestToken = null;\n      }\n      this.logAdState(\"ad_failsafe_triggered\", {\n        token,\n        failsafeMs,\n        videoPaused: this.video.paused\n      });\n      this.callbacks.onFailsafeTimeout();\n    }, failsafeMs);\n    this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n  }\n  clearAdFailsafeTimer() {\n    if (this.adFailsafeTimerId != null) {\n      clearTimeout(this.adFailsafeTimerId);\n      this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n      this.adFailsafeTimerId = void 0;\n    }\n    this.adFailsafeToken = null;\n  }\n  logAdState(event, extra = {}, adPlayer, inAdBreak, showAds) {\n    if (!this.debug) {\n      return;\n    }\n    console.log(\"[StormcloudVideoPlayer][AdState]\", {\n      event,\n      timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n      showAds: showAds ?? false,\n      adPlaying: adPlayer?.isAdPlaying() ?? false,\n      inAdBreak: inAdBreak ?? false,\n      activeAdRequestToken: this.activeAdRequestToken,\n      ...extra\n    });\n  }\n  // --- Reset for ad break end ---\n  resetForBreakEnd() {\n    this.clearAdStopTimer();\n    this.clearAdStartTimer();\n    this.clearAdRequestWatchdog();\n    this.clearAdFailsafeTimer();\n    this.activeAdRequestToken = null;\n    this.expectedAdBreakDurationMs = void 0;\n    this.currentAdBreakStartWallClockMs = void 0;\n    this.scteAdBreakEndWallClockMs = void 0;\n    this.adBreakPlayedDurationMs = 0;\n    this.currentAdIndex = 0;\n    this.totalAdsInBreak = 0;\n    this.consecutiveFailures = 0;\n    this.globalConsecutiveNoFills = 0;\n    this.adBreakEpoch++;\n  }\n  destroy() {\n    this.clearAdStopTimer();\n    this.clearAdStartTimer();\n    this.clearAdFailsafeTimer();\n    this.clearAdRequestWatchdog();\n  }\n};\n\n// src/player/PlaceholderLayer.ts\nvar PlaceholderLayer = class {\n  constructor(video, debug) {\n    this.video = video;\n    this.debug = debug;\n  }\n  ensureContainer() {\n    if (this.container) {\n      return;\n    }\n    const el = document.createElement(\"div\");\n    el.style.position = \"absolute\";\n    el.style.left = \"0\";\n    el.style.top = \"0\";\n    el.style.right = \"0\";\n    el.style.bottom = \"0\";\n    el.style.display = \"none\";\n    el.style.alignItems = \"center\";\n    el.style.justifyContent = \"center\";\n    el.style.pointerEvents = \"none\";\n    el.style.zIndex = \"5\";\n    el.style.backgroundColor = \"#000\";\n    el.style.transition = \"opacity 0.3s ease-in-out\";\n    el.style.opacity = \"0\";\n    if (!this.video.parentElement) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n      }\n      return;\n    }\n    this.video.parentElement.appendChild(el);\n    this.container = el;\n  }\n  show() {\n    this.ensureContainer();\n    if (!this.container) {\n      return;\n    }\n    if (!this.video.muted) {\n      this.video.muted = true;\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n      }\n    }\n    const wasHidden = this.container.style.display === \"none\" || this.container.style.opacity === \"0\";\n    if (wasHidden) {\n      this.container.style.transition = \"none\";\n    } else {\n      this.container.style.transition = \"opacity 0.3s ease-in-out\";\n    }\n    this.container.style.backgroundColor = \"#000\";\n    this.container.style.display = \"flex\";\n    this.container.offsetHeight;\n    this.container.style.opacity = \"1\";\n    this.container.style.pointerEvents = \"auto\";\n    if (wasHidden) {\n      requestAnimationFrame(() => {\n        if (this.container) {\n          this.container.style.transition = \"opacity 0.3s ease-in-out\";\n        }\n      });\n    }\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and ad layer)\");\n    }\n  }\n  hide() {\n    if (!this.container) {\n      return;\n    }\n    this.container.style.opacity = \"0\";\n    setTimeout(() => {\n      if (this.container) {\n        this.container.style.display = \"none\";\n        this.container.style.pointerEvents = \"none\";\n        this.container.style.backgroundColor = \"#000\";\n      }\n    }, 300);\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n    }\n  }\n  destroy() {\n    if (this.container) {\n      if (this.container.parentElement) {\n        this.container.parentElement.removeChild(this.container);\n      }\n      this.container = void 0;\n    }\n  }\n};\n\n// src/player/HlsEngine.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\nvar HlsEngine = class {\n  constructor(config, video, cueManager, timing, callbacks) {\n    this.isLiveStream = false;\n    this.nativeHlsMode = false;\n    this.videoSrcProtection = null;\n    this.reloadingLiveStream = false;\n    this.bufferedSegmentsCount = 0;\n    this.shouldAutoplayAfterBuffering = false;\n    this.hasInitialBufferCompleted = false;\n    this.config = config;\n    this.video = video;\n    this.cueManager = cueManager;\n    this.timing = timing;\n    this.callbacks = callbacks;\n  }\n  get debug() {\n    return !!this.config.debugAdTiming;\n  }\n  shouldUseNativeHls(getStreamType) {\n    const streamType = getStreamType();\n    if (streamType === \"other\") {\n      return true;\n    }\n    const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n    return !!(this.config.allowNativeHls && canNative);\n  }\n  async setupNativeHls() {\n    this.nativeHlsMode = true;\n    this.videoSrcProtection = this.config.src;\n    this.video.src = this.config.src;\n    this.isLiveStream = this.config.isLiveStream ?? (this.config.lowLatencyMode ?? false);\n    if (this.debug) {\n      const adBehavior = this.isLiveStream ? \"live (main video continues muted during ads)\" : \"vod (main video pauses during ads)\";\n      console.log(\n        \"[StormcloudVideoPlayer] Using native HLS playback:\",\n        {\n          isLive: this.isLiveStream,\n          allowNativeHls: this.config.allowNativeHls,\n          adBehavior\n        }\n      );\n    }\n    if (this.config.autoplay) {\n      await this.video.play()?.catch(() => {\n      });\n    }\n  }\n  setupHls() {\n    this.hls = new import_hls2.default({\n      enableWorker: true,\n      backBufferLength: 30,\n      liveDurationInfinity: true,\n      lowLatencyMode: !!this.config.lowLatencyMode,\n      maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,\n      ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},\n      maxBufferLength: 30,\n      maxMaxBufferLength: 600,\n      maxBufferSize: 60 * 1e3 * 1e3,\n      maxBufferHole: 0.5,\n      highBufferWatchdogPeriod: 2,\n      nudgeOffset: 0.1,\n      nudgeMaxRetry: 3,\n      startPosition: -1\n    });\n    this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {\n      this.hls?.loadSource(this.config.src);\n    });\n    this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, _data) => {\n      this.isLiveStream = this.config.isLiveStream ?? (this.hls?.levels?.some(\n        (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n      ) ?? false);\n      await this.callbacks.onManifestParsed(this.isLiveStream);\n      this.bufferedSegmentsCount = 0;\n      this.hasInitialBufferCompleted = false;\n      this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n      const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Waiting for\",\n          minSegments,\n          \"segments to buffer before playback\"\n        );\n      }\n      if (minSegments === 0 || !this.config.autoplay) {\n        this.hasInitialBufferCompleted = true;\n        if (this.config.autoplay) {\n          await this.video.play()?.catch(() => {\n          });\n        }\n      }\n      this.reloadingLiveStream = false;\n    });\n    this.hls.on(import_hls2.default.Events.LEVEL_LOADED, (_evt, data) => {\n      if (this.callbacks.isInAdBreak() || this.callbacks.hasPendingAdBreak()) {\n        return;\n      }\n      const details = data?.details;\n      if (!details || !details.fragments || details.fragments.length === 0) {\n        return;\n      }\n      const fragmentsToScan = Math.min(5, details.fragments.length);\n      for (let i = 0; i < fragmentsToScan; i++) {\n        const frag = details.fragments[i];\n        const tagList = frag?.tagList;\n        if (!Array.isArray(tagList)) continue;\n        for (const entry of tagList) {\n          let tag = \"\";\n          let value = \"\";\n          if (Array.isArray(entry)) {\n            tag = String(entry[0] ?? \"\");\n            value = String(entry[1] ?? \"\");\n          } else if (typeof entry === \"string\") {\n            const idx = entry.indexOf(\":\");\n            if (idx >= 0) {\n              tag = entry.substring(0, idx);\n              value = entry.substring(idx + 1);\n            } else {\n              tag = entry;\n            }\n          }\n          if (!tag) continue;\n          if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n            const attrs = tag.includes(\"EXT-X-DATERANGE\") ? parseAttributeList(value) : {};\n            const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") || \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n            if (hasScteOut) {\n              const durationSeconds = parseCueOutDuration(value);\n              const marker = {\n                type: \"start\",\n                ...durationSeconds !== void 0 ? { durationSeconds } : {},\n                raw: { tag, value, earlyDetection: true }\n              };\n              if (this.debug) {\n                console.log(\"[StormcloudVideoPlayer] EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n              }\n              this.callbacks.onScte35Cue(marker, {\n                ...this.cueManager.createScte35CueContext(\"manifest\", \"early\", frag)\n              });\n              return;\n            }\n          }\n        }\n      }\n    });\n    this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, async (_evt, _data) => {\n      if (this.hasInitialBufferCompleted) {\n        return;\n      }\n      this.bufferedSegmentsCount++;\n      const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n        );\n      }\n      if (this.bufferedSegmentsCount >= minSegments) {\n        this.hasInitialBufferCompleted = true;\n        if (this.shouldAutoplayAfterBuffering) {\n          if (this.debug) {\n            console.log(\n              `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n            );\n          }\n          await this.video.play()?.catch((err) => {\n            if (this.debug) {\n              console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n            }\n          });\n        }\n      }\n    });\n    this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {\n      const id3Tags = (data?.samples || []).map((s) => ({\n        key: \"ID3\",\n        value: s?.data,\n        ptsSeconds: s?.pts\n      }));\n      id3Tags.forEach((tag) => this.onId3Tag(tag));\n    });\n    this.hls.on(import_hls2.default.Events.FRAG_LOADED, (_evt, data) => {\n      this.processFragmentScte35Payload(\n        data?.payload,\n        typeof data?.frag?.sn === \"number\" ? data.frag.sn : void 0,\n        getFragmentStartSeconds(data?.frag)\n      );\n    });\n    this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, (_evt, data) => {\n      this.processFragmentScte35Payload(\n        data?.payload,\n        typeof data?.frag?.sn === \"number\" ? data.frag.sn : void 0,\n        getFragmentStartSeconds(data?.frag)\n      );\n    });\n    this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {\n      const frag = data?.frag;\n      const tagList = frag?.tagList;\n      if (!Array.isArray(tagList)) {\n        this.callbacks.activatePendingCuesForFragment(frag);\n        return;\n      }\n      for (const entry of tagList) {\n        let tag = \"\";\n        let value = \"\";\n        if (Array.isArray(entry)) {\n          tag = String(entry[0] ?? \"\");\n          value = String(entry[1] ?? \"\");\n        } else if (typeof entry === \"string\") {\n          const idx = entry.indexOf(\":\");\n          if (idx >= 0) {\n            tag = entry.substring(0, idx);\n            value = entry.substring(idx + 1);\n          } else {\n            tag = entry;\n            value = \"\";\n          }\n        }\n        if (!tag) continue;\n        if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n          const prog = parseCueOutCont(value);\n          const marker = {\n            type: \"progress\",\n            ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n            ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n            raw: { tag, value }\n          };\n          this.callbacks.onScte35Cue(marker, {\n            ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n          });\n        } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n          const durationSeconds = parseCueOutDuration(value);\n          const marker = {\n            type: \"start\",\n            ...durationSeconds !== void 0 ? { durationSeconds } : {},\n            raw: { tag, value }\n          };\n          this.callbacks.onScte35Cue(marker, {\n            ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n          });\n        } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n          this.callbacks.onScte35Cue(\n            { type: \"end\", raw: { tag, value } },\n            {\n              ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n            }\n          );\n        } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n          const attrs = parseAttributeList(value);\n          const hasScteOut = \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== void 0;\n          const hasScteIn = \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== void 0;\n          const klass = String(attrs[\"CLASS\"] ?? \"\");\n          const duration = toNumber(attrs[\"DURATION\"]);\n          if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n            const marker = {\n              type: \"start\",\n              ...duration !== void 0 ? { durationSeconds: duration } : {},\n              raw: { tag, value, attrs }\n            };\n            this.callbacks.onScte35Cue(marker, {\n              ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n            });\n          }\n          if (hasScteIn) {\n            this.callbacks.onScte35Cue(\n              { type: \"end\", raw: { tag, value, attrs } },\n              {\n                ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag)\n              }\n            );\n          }\n        }\n      }\n      this.callbacks.activatePendingCuesForFragment(frag);\n    });\n    this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {\n      if (data?.fatal) {\n        switch (data.type) {\n          case import_hls2.default.ErrorTypes.NETWORK_ERROR:\n            this.hls?.startLoad();\n            break;\n          case import_hls2.default.ErrorTypes.MEDIA_ERROR:\n            this.hls?.recoverMediaError();\n            break;\n          default:\n            this.callbacks.onFatalDestroy();\n            break;\n        }\n      }\n    });\n    this.hls.attachMedia(this.video);\n  }\n  onId3Tag(tag) {\n    if (typeof tag.ptsSeconds === \"number\") {\n      this.timing.updatePtsDrift(tag.ptsSeconds);\n    }\n    const marker = parseScte35FromId3(tag);\n    if (marker) {\n      this.callbacks.onScte35Cue(marker, {\n        source: \"id3\",\n        readiness: \"playback\"\n      });\n    }\n  }\n  processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {\n    const payload = normalizeFragmentPayload(payloadData);\n    if (!payload) {\n      return;\n    }\n    const markers = parseScte35FromTsPackets(\n      payload,\n      this.cueManager.tsScte35Pids,\n      this.cueManager.pmtPids,\n      this.cueManager.processedTsScte35Sections\n    );\n    markers.forEach((marker) => {\n      const context = {\n        source: \"ts\",\n        readiness: \"early\"\n      };\n      if (fragmentSn !== void 0) {\n        context.fragmentSn = fragmentSn;\n      }\n      if (fragmentStartSeconds !== void 0) {\n        context.fragmentStartSeconds = fragmentStartSeconds;\n      }\n      this.callbacks.onScte35Cue(marker, context);\n    });\n  }\n  getLiveSyncPosition() {\n    const pos = this.hls?.liveSyncPosition;\n    return typeof pos === \"number\" && Number.isFinite(pos) ? pos : void 0;\n  }\n  restartLoadAt(position) {\n    if (!this.hls) {\n      return;\n    }\n    try {\n      this.hls.stopLoad();\n      this.hls.startLoad(position);\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to restart HLS load at live edge:\", error);\n      }\n    }\n  }\n  recoverMediaError() {\n    if (!this.hls) {\n      return;\n    }\n    try {\n      this.hls.recoverMediaError();\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] recoverMediaError() failed:\", error);\n      }\n    }\n  }\n  reloadLiveStream() {\n    const hls = this.hls;\n    if (!hls) {\n      return;\n    }\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Hard-reloading live stream (detach \\u2192 reset video \\u2192 re-attach)\");\n    }\n    try {\n      this.reloadingLiveStream = true;\n      hls.stopLoad();\n      hls.detachMedia();\n      try {\n        this.video.removeAttribute(\"src\");\n        this.video.load();\n      } catch (error) {\n        console.warn(\"[StormcloudVideoPlayer] video.load() threw after src removal:\", error);\n      }\n      hls.attachMedia(this.video);\n    } catch (error) {\n      this.reloadingLiveStream = false;\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to hard-reload live stream:\", error);\n      }\n    }\n  }\n  destroy() {\n    this.hls?.destroy();\n    this.hls = void 0;\n  }\n};\n\n// src/player/PlayerControls.ts\nfunction getAdAudioVolume(adPlayer) {\n  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();\n}\nfunction toggleMute(video, adPlayer, debug) {\n  if (adPlayer.isAdPlaying()) {\n    const newMutedState = !adPlayer.getOriginalMutedState();\n    const restoreVolume = adPlayer.getOriginalVolume() || 1;\n    adPlayer.updateOriginalMutedState(newMutedState, video.volume);\n    adPlayer.setAdVolume(newMutedState ? 0 : restoreVolume);\n    if (debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n        newMutedState\n      );\n    }\n  } else {\n    video.muted = !video.muted;\n    adPlayer.updateOriginalMutedState(video.muted, video.volume);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] Muted:\", video.muted);\n    }\n  }\n}\nfunction toggleFullscreen(video, debug) {\n  return new Promise((resolve, reject) => {\n    if (!document.fullscreenElement) {\n      const container = video.parentElement;\n      if (!container) {\n        reject(new Error(\"No parent container found for fullscreen\"));\n        return;\n      }\n      container.requestFullscreen().then(() => {\n        if (debug) {\n          console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n        }\n        resolve();\n      }).catch((err) => {\n        if (debug) {\n          console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n        }\n        reject(err);\n      });\n    } else {\n      document.exitFullscreen().then(() => {\n        if (debug) {\n          console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n        }\n        resolve();\n      }).catch((err) => {\n        if (debug) {\n          console.error(\n            \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n            err\n          );\n        }\n        reject(err);\n      });\n    }\n  });\n}\nfunction isMuted(video, adPlayer) {\n  if (adPlayer.isAdPlaying()) {\n    return adPlayer.getOriginalMutedState();\n  }\n  return video.muted;\n}\nfunction setMuted(video, adPlayer, muted, debug) {\n  const adPlaying = adPlayer.isAdPlaying();\n  if (adPlaying && muted === video.muted) {\n    if (debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n        { muted }\n      );\n    }\n    return;\n  }\n  video.muted = muted;\n  if (adPlaying) {\n    adPlayer.updateOriginalMutedState(muted, video.volume);\n    adPlayer.setAdVolume(muted ? 0 : 1);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n        muted\n      });\n    }\n    return;\n  }\n  adPlayer.updateOriginalMutedState(muted, video.volume);\n  if (debug) {\n    console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n  }\n}\nfunction setVolume(video, adPlayer, volume, debug) {\n  const clampedVolume = Math.max(0, Math.min(1, volume));\n  const adPlaying = adPlayer.isAdPlaying();\n  if (adPlaying) {\n    adPlayer.setAdVolume(clampedVolume);\n    adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n        volume: clampedVolume\n      });\n    }\n  } else {\n    video.volume = clampedVolume;\n    video.muted = clampedVolume === 0;\n    adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n    }\n  }\n}\nfunction getVolume(video, adPlayer) {\n  const adPlaying = adPlayer.isAdPlaying();\n  if (adPlaying) {\n    return adPlayer.getAdVolume();\n  }\n  return video.volume;\n}\nfunction isFullscreen() {\n  return !!document.fullscreenElement;\n}\nfunction resizePlayer(video, adPlayer, debug) {\n  if (debug) {\n    console.log(\"[StormcloudVideoPlayer] Resizing player\");\n  }\n  if (adPlayer && adPlayer.isAdPlaying()) {\n    const width = video.clientWidth || 640;\n    const height = video.clientHeight || 480;\n    if (debug) {\n      console.log(\n        `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n      );\n    }\n    adPlayer.resize(width, height);\n  }\n}\n\n// src/player/AdBreakOrchestrator.ts\nvar AdBreakOrchestrator = class {\n  constructor(host, timing, adConfig, cueManager, placeholder) {\n    this.inAdBreak = false;\n    this.showAds = false;\n    this.isShowingPlaceholder = false;\n    this.adDetectSentForCurrentBreak = false;\n    this.continuousFetchingActive = false;\n    this.continuousFetchLoopRunning = false;\n    this.adRequestQueue = [];\n    this.adPodQueue = [];\n    this.maxPlaceholderDurationMs = 5e3;\n    this.pendingAdBreak = null;\n    this.host = host;\n    this.timing = timing;\n    this.adConfig = adConfig;\n    this.cueManager = cueManager;\n    this.placeholder = placeholder;\n  }\n  get debug() {\n    return !!this.host.config.debugAdTiming;\n  }\n  get analyticsContext() {\n    return buildAnalyticsContext(this.host.config);\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  IMA event listeners\n  // ───────────────────────────────────────────────────────────────\n  nextAdRequestUrl(baseVastUrl) {\n    const remaining = Math.min(\n      this.timing.getWallClockRemainingAdMs(),\n      this.timing.getDurationBudgetRemainingMs()\n    );\n    const breakDurationMs = remaining > 0 ? remaining : void 0;\n    return this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);\n  }\n  attachImaEventListeners() {\n    const adPlayer = this.host.getAdPlayer();\n    adPlayer.on(\"pod_ad_started\", (payload) => {\n      this.timing.notePodAdStarted();\n      if (this.debug) {\n        console.log(\n          `[POD] Playing pod ad ${payload?.index != null ? payload.index + 1 : \"?\"}/${payload?.total ?? \"?\"}`\n        );\n      }\n    });\n    adPlayer.on(\"all_ads_completed\", () => {\n      sendAdImpressionTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() },\n        this.analyticsContext\n      ).catch(() => {\n      });\n      this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n      const remaining = this.timing.getRemainingAdMs();\n      this.timing.consecutiveFailures = 0;\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n          this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n        );\n      }\n      if (this.inAdBreak) {\n        if (this.timing.hasTimeToStartAnotherAd()) {\n          this.tryNextAvailableAdWithRateLimit();\n        } else {\n          this.handleAdPodComplete();\n        }\n      }\n    });\n    adPlayer.on(\"ad_error\", (errorPayload) => {\n      let errorMessage = \"Ad playback failed\";\n      if (errorPayload) {\n        const errorCode = errorPayload.code || errorPayload.errorCode || \"unknown\";\n        const vastErrorCode = errorPayload.vastErrorCode;\n        const message = errorPayload.message || errorPayload.errorMessage || \"Unknown error\";\n        const cause = errorPayload.cause || errorPayload.innerError || errorPayload.error;\n        errorMessage = `Ad error: AdError ${errorCode}: ${message}`;\n        if (vastErrorCode && vastErrorCode !== \"N/A\" && vastErrorCode !== errorCode) {\n          errorMessage += ` (VAST Error Code: ${vastErrorCode})`;\n        }\n        if (cause) {\n          const causeMessage = typeof cause === \"string\" ? cause : cause.message || String(cause);\n          errorMessage += `. Caused by: ${causeMessage}`;\n        }\n      }\n      console.error(\"[AD-ERROR]\", errorMessage, errorPayload || \"\");\n      this.handleAdFailure();\n    });\n    adPlayer.on(\"content_pause\", () => {\n      this.timing.clearAdFailsafeTimer();\n      this.timing.clearAdRequestWatchdog();\n      this.timing.activeAdRequestToken = null;\n      this.showAds = true;\n      this.timing.resetGamNoFillCounter();\n      if (this.inAdBreak && this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n        this.timing.scheduleAdStopAtBreakBoundary();\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n        }\n      }\n      this.host.getAdPlayer().setAdVolume(getAdAudioVolume(this.host.getAdPlayer()));\n      if (this.isShowingPlaceholder) {\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n        }\n        this.host.getAdPlayer().hidePlaceholder();\n        this.isShowingPlaceholder = false;\n      }\n    });\n    adPlayer.on(\"content_resume\", () => {\n      sendAdImpressionTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: (/* @__PURE__ */ new Date()).toISOString() },\n        this.analyticsContext\n      ).catch(() => {\n      });\n      if (!this.host.video.muted) {\n        this.host.video.muted = true;\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n        }\n      }\n      this.timing.clearAdFailsafeTimer();\n      this.timing.clearAdRequestWatchdog();\n      this.timing.activeAdRequestToken = null;\n      this.showAds = false;\n      if (!this.inAdBreak) {\n        return;\n      }\n      this.timing.consecutiveFailures = 0;\n      this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n      const remaining = this.timing.getRemainingAdMs();\n      if (this.debug) {\n        console.log(\n          `[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n          this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n        );\n      }\n      if (this.timing.hasTimeToStartAnotherAd()) {\n        this.tryNextAvailableAdWithRateLimit();\n      } else {\n        this.handleAdPodComplete();\n      }\n    });\n  }\n  recreateAdController() {\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Recreating AdController for new ad\");\n    }\n    const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n    const adPlayer = this.host.getAdPlayer();\n    if (shouldShowPlaceholder && adPlayer) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old AdController\");\n      }\n      this.placeholder.show();\n      adPlayer.showPlaceholder();\n      this.isShowingPlaceholder = true;\n    }\n    const preservedMutedState = adPlayer.getOriginalMutedState();\n    const preservedVolumeState = adPlayer.getOriginalVolume();\n    if (adPlayer) {\n      try {\n        adPlayer.destroy();\n        this.host.video.muted = true;\n      } catch (error) {\n        if (this.debug) {\n          console.warn(\"[StormcloudVideoPlayer] Error destroying old AdController:\", error);\n        }\n      }\n    }\n    const continueLiveStreamDuringAds = this.host.shouldContinueLiveStreamDuringAds();\n    const newAdPlayer = this.host.createAdPlayer(continueLiveStreamDuringAds);\n    this.host.setAdPlayer(newAdPlayer);\n    newAdPlayer.initialize();\n    newAdPlayer.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n    this.attachImaEventListeners();\n    if (shouldShowPlaceholder) {\n      this.placeholder.show();\n      newAdPlayer.showPlaceholder();\n      this.isShowingPlaceholder = true;\n    }\n  }\n  clearPendingAdBreak() {\n    if (this.prefetchTimerId != null) {\n      clearTimeout(this.prefetchTimerId);\n      this.prefetchTimerId = void 0;\n    }\n    this.pendingAdBreak = null;\n    this.cueManager.pendingScte35CueKey = void 0;\n    this.adConfig.podAssignedByPrefetch = false;\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Ad break start\n  // ───────────────────────────────────────────────────────────────\n  async handleAdStart(_marker) {\n    const scheduled = this.adConfig.findCurrentOrNextBreak(\n      this.host.video.currentTime * 1e3\n    );\n    if (scheduled) {\n      this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));\n    }\n    const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n    let baseVastUrl;\n    if (tags && tags.length > 0 && tags[0]) {\n      baseVastUrl = tags[0];\n    } else if (this.adConfig.apiVastTagUrl) {\n      baseVastUrl = this.adConfig.apiVastTagUrl;\n    } else {\n      this.clearPendingAdBreak();\n      return;\n    }\n    const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled?.durationMs;\n    if (this.debug) {\n      const mode = this.host.config.isLiveStream ? \"LIVE\" : \"VOD\";\n      console.log(\n        `[CONTINUOUS-FETCH] ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n      );\n    }\n    this.timing.failedVastUrls.clear();\n    this.timing.temporaryFailureUrls.clear();\n    this.timing.consecutiveFailures = 0;\n    this.continuousFetchingActive = true;\n    this.isShowingPlaceholder = false;\n    this.timing.totalAdRequestsInBreak = 0;\n    if (this.adConfig.podAssignedByPrefetch) {\n      this.adConfig.podAssignedByPrefetch = false;\n    } else {\n      this.adConfig.beginNewAdPod();\n    }\n    const currentMuted = this.host.video.muted;\n    const currentVolume = this.host.video.volume;\n    this.host.getAdPlayer().updateOriginalMutedState(currentMuted, currentVolume);\n    this.inAdBreak = true;\n    this.timing.adBreakPlayedDurationMs = 0;\n    this.timing.currentAdIndex = 0;\n    this.timing.totalAdsInBreak = 0;\n    this.adPodQueue = [];\n    this.showAds = false;\n    if (this.timing.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n      this.timing.expectedAdBreakDurationMs = adBreakDurationMs;\n    }\n    const podPlayed = await this.startOptimizedPod(\n      baseVastUrl,\n      adBreakDurationMs,\n      currentMuted,\n      currentVolume\n    );\n    if (!podPlayed) {\n      if (this.debug) {\n        console.log(\"[POD] Initial pod request did not fill; attempting top-up pod request\");\n      }\n      this.continuousFetchingActive = true;\n      this.startContinuousFetching(baseVastUrl);\n      await this.tryNextAvailableAdWithRateLimit();\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Optimized pod (single multi-ad request)\n  // ───────────────────────────────────────────────────────────────\n  async startOptimizedPod(baseVastUrl, breakDurationMs, currentMuted, currentVolume) {\n    let podUrl;\n    if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n      podUrl = this.pendingAdBreak.vastUrls[0];\n      this.clearPendingAdBreak();\n    } else {\n      podUrl = this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);\n    }\n    if (!podUrl) {\n      return false;\n    }\n    this.continuousFetchingActive = false;\n    this.recreateAdController();\n    const adPlayer = this.host.getAdPlayer();\n    const requestToken = ++this.timing.adRequestTokenCounter;\n    this.timing.activeAdRequestToken = requestToken;\n    this.timing.startAdRequestWatchdog(requestToken);\n    try {\n      await this.timing.enforceGlobalRateLimit();\n      this.timing.lastAdRequestTime = Date.now();\n      await adPlayer.requestAds(podUrl);\n      this.timing.clearAdRequestWatchdog();\n      if (this.timing.activeAdRequestToken !== requestToken) {\n        return true;\n      }\n      const podCount = adPlayer.getPodAdCount?.() ?? 1;\n      if (podCount < 1) {\n        return false;\n      }\n      if (this.debug) {\n        console.log(\n          podCount === 1 ? \"[POD] Response contained a single ad; playing it and enabling pod top-up\" : `[POD] Optimized pod returned ${podCount} ads; playing pod in one controller`\n        );\n      }\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: podUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() },\n        this.analyticsContext\n      ).catch(() => {\n      });\n      this.timing.startAdFailsafeTimer(requestToken);\n      await adPlayer.play();\n      this.timing.markAdStarted();\n      if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n        this.timing.scheduleAdStopAtBreakBoundary();\n      }\n      adPlayer.setAdVolume(currentMuted ? 0 : currentVolume);\n      this.timing.consecutiveFailures = 0;\n      this.continuousFetchingActive = true;\n      this.startContinuousFetching(baseVastUrl);\n      return true;\n    } catch (error) {\n      this.timing.clearAdRequestWatchdog();\n      this.timing.clearAdFailsafeTimer();\n      if (this.timing.activeAdRequestToken === requestToken) {\n        this.timing.activeAdRequestToken = null;\n      }\n      if (this.debug) {\n        console.warn(\"[POD] Optimized pod request/play failed:\", error);\n      }\n      if (this.timing.isTemporaryAdError(error)) {\n        this.timing.temporaryFailureUrls.set(podUrl, Date.now());\n      }\n      this.continuousFetchingActive = true;\n      this.recreateAdController();\n      return false;\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Continuous fetching\n  // ───────────────────────────────────────────────────────────────\n  startContinuousFetching(baseVastUrl) {\n    if (!this.continuousFetchingActive) {\n      return;\n    }\n    if (this.continuousFetchLoopRunning) {\n      if (this.debug) {\n        console.log(\"[CONTINUOUS-FETCH] Fetch loop already running, skipping duplicate start\");\n      }\n      return;\n    }\n    if (this.debug) {\n      console.log(\"[CONTINUOUS-FETCH] Starting continuous ad fetching loop\");\n    }\n    this.continuousFetchLoopRunning = true;\n    this.continuousFetchLoop(baseVastUrl);\n  }\n  async continuousFetchLoop(baseVastUrl) {\n    const epoch = this.timing.adBreakEpoch;\n    while (this.continuousFetchingActive && this.inAdBreak && epoch === this.timing.adBreakEpoch) {\n      const remaining = Math.min(\n        this.timing.getWallClockRemainingAdMs(),\n        this.timing.getDurationBudgetRemainingMs()\n      );\n      if (remaining <= this.timing.getMinRemainingMsToStartAd()) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] Not enough ad break time left (wall=${this.timing.getWallClockRemainingAdMs()}ms, budget=${this.timing.getDurationBudgetRemainingMs()}ms), stopping URL generation`);\n        }\n        break;\n      }\n      if (this.timing.isGamInCooldown()) {\n        if (this.debug) {\n          console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n        }\n        break;\n      }\n      if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), stopping URL generation`);\n        }\n        break;\n      }\n      if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] Maximum ad requests reached (${this.timing.maxTotalAdRequestsPerBreak}), stopping`);\n        }\n        break;\n      }\n      const maxQueueSize = 5;\n      if (this.adRequestQueue.length >= maxQueueSize) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] URL queue full (${this.adRequestQueue.length}), waiting...`);\n        }\n        await new Promise((resolve) => setTimeout(resolve, 1e3));\n        continue;\n      }\n      const newAdUrl = this.nextAdRequestUrl(baseVastUrl);\n      if (!newAdUrl || this.timing.failedVastUrls.has(newAdUrl) || this.timing.isUrlInCooldown(newAdUrl)) {\n        await new Promise((resolve) => setTimeout(resolve, 500));\n        continue;\n      }\n      if (this.debug) {\n        const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n        console.log(\n          `[CONTINUOUS-FETCH] Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n          { queuedUrls: queuedUrlsPreview }\n        );\n      }\n      this.adRequestQueue.push(newAdUrl);\n      const generationDelay = this.timing.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, this.timing.consecutiveFailures), 5e3) : 500;\n      await new Promise((resolve) => setTimeout(resolve, generationDelay));\n    }\n    this.continuousFetchLoopRunning = false;\n    if (this.debug) {\n      console.log(\n        `[CONTINUOUS-FETCH] URL generation loop ended (queued: ${this.adRequestQueue.length})`,\n        this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n      );\n    }\n  }\n  stopContinuousFetching() {\n    this.continuousFetchingActive = false;\n    this.continuousFetchLoopRunning = false;\n    this.placeholder.hide();\n    if (this.debug) {\n      console.log(\"[CONTINUOUS-FETCH] Stopping continuous ad fetching\");\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Ad iteration\n  // ───────────────────────────────────────────────────────────────\n  async tryNextAvailableAdWithRateLimit() {\n    if (!this.inAdBreak) {\n      return;\n    }\n    const epoch = this.timing.adBreakEpoch;\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n    const backoffMultiplier = Math.pow(2, this.timing.consecutiveFailures);\n    const backoffDelay = Math.min(this.timing.backoffBaseMs * backoffMultiplier, this.timing.maxBackoffMs);\n    const effectiveMinInterval = this.timing.minAdRequestIntervalMs + (this.timing.consecutiveFailures > 0 ? backoffDelay : 0);\n    const timeSinceLastRequest = Date.now() - this.timing.lastAdRequestTime;\n    if (timeSinceLastRequest < effectiveMinInterval) {\n      const waitTime = effectiveMinInterval - timeSinceLastRequest;\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.timing.consecutiveFailures} failures)`);\n      }\n      await new Promise((resolve) => setTimeout(resolve, waitTime));\n    }\n    if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) {\n      return;\n    }\n    return this.tryNextAvailableAd(0);\n  }\n  async tryNextAvailableAd(retryCount = 0) {\n    if (!this.inAdBreak) {\n      return;\n    }\n    const remaining = this.timing.getRemainingAdMs();\n    if (!this.timing.hasTimeToStartAnotherAd()) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Not enough time remaining (${remaining}ms) to start another ad, ending ad break`);\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n    if (this.timing.isGamInCooldown()) {\n      if (this.debug) {\n        console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break`);\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n    this.timing.cleanupTemporaryFailures();\n    while (this.adRequestQueue.length > 0) {\n      const nextAdUrl = this.adRequestQueue.shift();\n      if (!nextAdUrl) continue;\n      if (this.timing.failedVastUrls.has(nextAdUrl)) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping permanently-failed URL, trying next...\");\n        continue;\n      }\n      if (this.timing.isUrlInCooldown(nextAdUrl)) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping URL in cooldown (recent no-fill), trying next...\");\n        continue;\n      }\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Requesting next ad via HLS ad player (${this.timing.currentAdIndex + 1}, ${this.adRequestQueue.length} remaining in queue)`);\n      }\n      try {\n        await this.playSingleAd(nextAdUrl);\n        this.timing.consecutiveFailures = 0;\n      } catch (error) {\n        const errorMessage = error.message;\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad request failed:\", errorMessage);\n        if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n        if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n          this.timing.consecutiveFailures++;\n        }\n        await this.tryNextAvailableAdWithRateLimit();\n      }\n      return;\n    }\n    const maxRetries = 3;\n    if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n      }\n      await new Promise((resolve) => setTimeout(resolve, 500));\n      await this.tryNextAvailableAd(retryCount + 1);\n      return;\n    }\n    if (!this.isShowingPlaceholder && remaining > 1e3) {\n      this.showPlaceholderAndWaitForAds();\n    } else {\n      if (this.debug) console.log(\"[CONTINUOUS-FETCH] No more ads available, ending ad break\");\n      this.handleAdPodComplete();\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Single ad playback\n  // ───────────────────────────────────────────────────────────────\n  async playSingleAd(vastTagUrl) {\n    const adPlayer = this.host.getAdPlayer();\n    if (adPlayer.isAdPlaying()) return;\n    if (this.timing.failedVastUrls.has(vastTagUrl)) {\n      if (this.debug) console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n      throw new Error(\"VAST URL permanently failed\");\n    }\n    if (this.timing.isUrlInCooldown(vastTagUrl)) {\n      if (this.debug) console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n      throw new Error(\"VAST URL in cooldown after no-fill\");\n    }\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n      throw new Error(\"Too many consecutive failures\");\n    }\n    if (this.timing.isGamInCooldown()) {\n      if (this.debug) console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n      throw new Error(\"GAM in cooldown\");\n    }\n    this.recreateAdController();\n    const requestToken = ++this.timing.adRequestTokenCounter;\n    this.timing.activeAdRequestToken = requestToken;\n    this.timing.startAdRequestWatchdog(requestToken);\n    try {\n      await this.timing.enforceGlobalRateLimit();\n      this.timing.lastAdRequestTime = Date.now();\n      const ap = this.host.getAdPlayer();\n      await ap.requestAds(vastTagUrl);\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: vastTagUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() },\n        this.analyticsContext\n      ).catch(() => {\n      });\n      this.timing.clearAdRequestWatchdog();\n      if (this.timing.activeAdRequestToken !== requestToken) return;\n      if (!this.timing.ensureLoadedAdFitsBudget(ap)) {\n        this.timing.rejectLoadedAdForDuration(ap);\n        this.recreateAdController();\n        throw new Error(\"ad_duration_exceeds_budget\");\n      }\n      try {\n        this.timing.startAdFailsafeTimer(requestToken);\n        await ap.play();\n        this.timing.markAdStarted();\n        if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n          this.timing.scheduleAdStopAtBreakBoundary();\n        }\n        ap.setAdVolume(getAdAudioVolume(ap));\n        this.timing.consecutiveFailures = 0;\n        this.timing.temporaryFailureUrls.delete(vastTagUrl);\n      } catch (playError) {\n        if (this.debug) console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n        if (this.timing.isTemporaryAdError(playError)) {\n          this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n          if (this.debug) console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n        } else {\n          this.timing.failedVastUrls.add(vastTagUrl);\n          if (this.debug) console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n        }\n        this.timing.clearAdFailsafeTimer();\n        if (this.timing.activeAdRequestToken === requestToken) {\n          this.timing.activeAdRequestToken = null;\n        }\n        throw playError;\n      }\n    } catch (error) {\n      const errorMessage = error?.message || \"\";\n      if (this.debug) console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n      if (this.timing.isTemporaryAdError(error)) {\n        this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n        if (this.debug) console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n      } else {\n        this.timing.failedVastUrls.add(vastTagUrl);\n        if (this.debug) console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n      }\n      this.timing.clearAdRequestWatchdog();\n      this.timing.clearAdFailsafeTimer();\n      if (this.timing.activeAdRequestToken === requestToken) {\n        this.timing.activeAdRequestToken = null;\n      }\n      throw error;\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Placeholder wait\n  // ───────────────────────────────────────────────────────────────\n  async showPlaceholderAndWaitForAds() {\n    const remaining = this.timing.getRemainingAdMs();\n    const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n    if (this.timing.isGamInCooldown()) {\n      if (this.debug) console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n      this.handleAdPodComplete();\n      return;\n    }\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping placeholder - too many consecutive failures\");\n      this.handleAdPodComplete();\n      return;\n    }\n    if (waitTime < 1e3) {\n      this.handleAdPodComplete();\n      return;\n    }\n    if (this.debug) {\n      console.log(`[CONTINUOUS-FETCH] Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n    }\n    this.isShowingPlaceholder = true;\n    this.host.getAdPlayer().showPlaceholder();\n    const checkInterval = 300;\n    const maxChecks = Math.floor(waitTime / checkInterval);\n    for (let i = 0; i < maxChecks; i++) {\n      await new Promise((resolve) => setTimeout(resolve, checkInterval));\n      if (!this.inAdBreak) return;\n      if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Too many failures during placeholder wait\");\n        break;\n      }\n      if (!this.timing.hasTimeToStartAnotherAd()) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Not enough time remaining during placeholder wait, ending ad break\");\n        break;\n      }\n      while (this.adRequestQueue.length > 0) {\n        if (!this.timing.hasTimeToStartAnotherAd()) break;\n        const nextAdUrl = this.adRequestQueue.shift();\n        if (!nextAdUrl) continue;\n        if (this.timing.failedVastUrls.has(nextAdUrl)) continue;\n        if (this.timing.isUrlInCooldown(nextAdUrl)) continue;\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad URL available, requesting via HLS ad player\");\n        this.isShowingPlaceholder = false;\n        this.host.getAdPlayer().hidePlaceholder();\n        try {\n          await this.playSingleAd(nextAdUrl);\n          this.timing.consecutiveFailures = 0;\n        } catch (error) {\n          const errorMessage = error.message;\n          if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n            await this.tryNextAvailableAdWithRateLimit();\n            return;\n          }\n          if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n            this.timing.consecutiveFailures++;\n          }\n          await this.tryNextAvailableAdWithRateLimit();\n        }\n        return;\n      }\n    }\n    if (this.debug) console.log(\"[CONTINUOUS-FETCH] Placeholder timeout, ending ad break\");\n    this.isShowingPlaceholder = false;\n    this.host.getAdPlayer().hidePlaceholder();\n    this.handleAdPodComplete();\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Ad break completion\n  // ───────────────────────────────────────────────────────────────\n  handleAdPodComplete() {\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Ad pod complete - cleaning up\");\n    }\n    this.timing.resetForBreakEnd();\n    this.stopContinuousFetching();\n    this.clearPendingAdBreak();\n    if (this.isShowingPlaceholder) {\n      this.host.getAdPlayer().hidePlaceholder();\n      this.isShowingPlaceholder = false;\n    }\n    this.adRequestQueue = [];\n    this.inAdBreak = false;\n    this.adDetectSentForCurrentBreak = false;\n    this.cueManager.activeScte35BreakKey = void 0;\n    this.cueManager.scheduledScte35BreakKey = void 0;\n    this.adPodQueue = [];\n    this.showAds = false;\n    this.host.getAdPlayer().stop().catch(() => {\n    });\n    const restoredMuted = this.host.getAdPlayer().getOriginalMutedState();\n    const restoredVolume = this.host.getAdPlayer().getOriginalVolume();\n    if (this.host.video.muted !== restoredMuted) {\n      this.host.video.muted = restoredMuted;\n    }\n    if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {\n      this.host.video.volume = restoredVolume;\n    }\n    this.host.video.style.visibility = \"visible\";\n    this.host.video.style.opacity = \"1\";\n    if (this.host.isLiveStream()) {\n      const liveSyncPos = this.host.getLiveSyncPosition();\n      if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {\n        if (this.debug) {\n          console.log(\n            `[StormcloudVideoPlayer] Live break end \\u2014 snapping to live edge: ${this.host.video.currentTime.toFixed(2)}s \\u2192 ${liveSyncPos.toFixed(2)}s`\n          );\n        }\n        this.host.video.currentTime = liveSyncPos;\n        this.host.restartHlsLoad(liveSyncPos);\n      }\n      this.resumeContentPlayback();\n      this.monitorLiveResumeStall(this.host.video.currentTime);\n      return;\n    }\n    this.resumeContentPlayback();\n  }\n  getBufferedAhead() {\n    const video = this.host.video;\n    const t = video.currentTime;\n    const ranges = video.buffered;\n    for (let i = 0; i < ranges.length; i++) {\n      if (t >= ranges.start(i) - 0.5 && t <= ranges.end(i)) {\n        return ranges.end(i) - t;\n      }\n    }\n    return 0;\n  }\n  describeVideoState() {\n    const v = this.host.video;\n    const networkStates = [\"EMPTY\", \"IDLE\", \"LOADING\", \"NO_SOURCE\"];\n    const readyStates = [\n      \"HAVE_NOTHING\",\n      \"HAVE_METADATA\",\n      \"HAVE_CURRENT_DATA\",\n      \"HAVE_FUTURE_DATA\",\n      \"HAVE_ENOUGH_DATA\"\n    ];\n    const net = networkStates[v.networkState] ?? String(v.networkState);\n    const ready = readyStates[v.readyState] ?? String(v.readyState);\n    const err = v.error ? `code=${v.error.code}${v.error.message ? ` (${v.error.message})` : \"\"}` : \"none\";\n    const ranges = [];\n    for (let i = 0; i < v.buffered.length; i++) {\n      ranges.push(`[${v.buffered.start(i).toFixed(2)}\\u2013${v.buffered.end(i).toFixed(2)}]`);\n    }\n    return `t=${v.currentTime.toFixed(2)}s paused=${v.paused} ended=${v.ended} seeking=${v.seeking} readyState=${ready} networkState=${net} error=${err} buffered=${ranges.length ? ranges.join(\",\") : \"none\"}`;\n  }\n  monitorLiveResumeStall(resumeBaseline) {\n    const pollIntervalMs = 1e3;\n    const graceMs = 5e3;\n    const recoveryCooldownMs = 5e3;\n    const maxRecoveries = 3;\n    const maxMonitorMs = 45e3;\n    const startTime = Date.now();\n    let baseline = resumeBaseline;\n    let recoveries = 0;\n    let lastRecoveryAt = 0;\n    const video = this.host.video;\n    let listenersAttached = false;\n    let onMediaEvent;\n    const diagEvents = [\n      \"loadstart\",\n      \"loadedmetadata\",\n      \"loadeddata\",\n      \"canplay\",\n      \"canplaythrough\",\n      \"play\",\n      \"playing\",\n      \"pause\",\n      \"waiting\",\n      \"stalled\",\n      \"suspend\",\n      \"seeking\",\n      \"seeked\",\n      \"emptied\",\n      \"error\",\n      \"ended\"\n    ];\n    if (this.debug) {\n      onMediaEvent = (e) => {\n        const dt = ((Date.now() - startTime) / 1e3).toFixed(1);\n        console.log(\n          `[ResumeDiag] +${dt}s event=${e.type} \\u2014 ${this.describeVideoState()}`\n        );\n      };\n      for (const name of diagEvents) {\n        video.addEventListener(name, onMediaEvent);\n      }\n      listenersAttached = true;\n      console.log(\n        `[ResumeDiag] +0.0s monitor start \\u2014 ${this.describeVideoState()}`\n      );\n    }\n    const cleanup = () => {\n      if (listenersAttached && onMediaEvent) {\n        for (const name of diagEvents) {\n          video.removeEventListener(name, onMediaEvent);\n        }\n        listenersAttached = false;\n      }\n    };\n    const poll = () => {\n      if (this.inAdBreak) {\n        cleanup();\n        return;\n      }\n      const currentTime = video.currentTime;\n      const advanced = currentTime > baseline + 0.5;\n      const playing = !video.paused && video.readyState >= 3;\n      if (advanced && playing) {\n        if (this.debug) {\n          console.log(\n            `[StormcloudVideoPlayer] Live stream resumed successfully after ad break \\u2014 ${this.describeVideoState()}`\n          );\n        }\n        cleanup();\n        return;\n      }\n      if (video.paused) {\n        video.play()?.catch(() => {\n        });\n      }\n      const elapsed = Date.now() - startTime;\n      const bufferedAhead = this.getBufferedAhead();\n      const wedged = bufferedAhead < 0.5 && !advanced;\n      if (elapsed >= maxMonitorMs) {\n        if (this.debug && !advanced) {\n          console.warn(\n            `[StormcloudVideoPlayer] Live stream failed to resume after ${(maxMonitorMs / 1e3).toFixed(0)}s \\u2014 ${this.describeVideoState()}`\n          );\n        }\n        cleanup();\n        return;\n      }\n      const canRecover = wedged && elapsed >= graceMs && Date.now() - lastRecoveryAt >= recoveryCooldownMs && recoveries < maxRecoveries;\n      if (canRecover) {\n        recoveries++;\n        lastRecoveryAt = Date.now();\n        if (recoveries === 1) {\n          if (this.debug) {\n            console.warn(\n              `[StormcloudVideoPlayer] Content wedged after ad break \\u2014 calling recoverMediaError() (recovery ${recoveries}/${maxRecoveries}) \\u2014 ${this.describeVideoState()}`\n            );\n          }\n          this.host.recoverMediaError();\n        } else if (recoveries === 2) {\n          const liveSyncPos = this.host.getLiveSyncPosition();\n          const reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;\n          if (this.debug) {\n            console.warn(\n              `[StormcloudVideoPlayer] Content wedged after ad break \\u2014 restarting HLS load at ${reloadPos.toFixed(2)}s (recovery ${recoveries}/${maxRecoveries}) \\u2014 ${this.describeVideoState()}`\n            );\n          }\n          if (liveSyncPos != null && liveSyncPos > currentTime) {\n            video.currentTime = liveSyncPos;\n          }\n          this.host.restartHlsLoad(reloadPos);\n        } else {\n          if (this.debug) {\n            console.warn(\n              `[StormcloudVideoPlayer] Content still wedged after ad break \\u2014 hard-reloading live stream (recovery ${recoveries}/${maxRecoveries}) \\u2014 ${this.describeVideoState()}`\n            );\n          }\n          this.host.reloadLiveStream();\n        }\n        baseline = video.currentTime;\n        if (video.paused) {\n          video.play()?.catch(() => {\n          });\n        }\n      }\n      window.setTimeout(poll, pollIntervalMs);\n    };\n    window.setTimeout(poll, pollIntervalMs);\n  }\n  resumeContentPlayback(attempt = 0) {\n    const maxAttempts = 5;\n    const video = this.host.video;\n    if (!video.paused) {\n      if (this.debug && attempt === 0) {\n        console.log(\"[StormcloudVideoPlayer] Content video already playing after ads\");\n      }\n      return;\n    }\n    if (this.debug) {\n      console.log(\n        `[StormcloudVideoPlayer] Resuming content playback after ads (attempt ${attempt + 1}/${maxAttempts}, readyState=${video.readyState})`\n      );\n    }\n    if (video.readyState < 3) {\n      if (attempt + 1 >= maxAttempts) {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] readyState never reached HAVE_FUTURE_DATA, forcing play()\"\n          );\n        }\n        video.play()?.catch(() => {\n        });\n        return;\n      }\n      const onReady = () => {\n        video.removeEventListener(\"canplay\", onReady);\n        this.resumeContentPlayback(attempt + 1);\n      };\n      video.addEventListener(\"canplay\", onReady);\n      const backoffMs = 500 * (attempt + 1);\n      window.setTimeout(() => {\n        video.removeEventListener(\"canplay\", onReady);\n        if (video.paused) {\n          this.resumeContentPlayback(attempt + 1);\n        }\n      }, backoffMs);\n      return;\n    }\n    const playResult = video.play();\n    if (playResult && typeof playResult.catch === \"function\") {\n      playResult.catch((error) => {\n        if (attempt + 1 >= maxAttempts) {\n          if (this.debug) {\n            console.warn(\n              \"[StormcloudVideoPlayer] Failed to resume content playback after ads:\",\n              error\n            );\n          }\n          return;\n        }\n        const backoffMs = 250 * (attempt + 1);\n        window.setTimeout(() => {\n          this.resumeContentPlayback(attempt + 1);\n        }, backoffMs);\n      });\n    }\n  }\n  handleAdFailure() {\n    this.timing.consecutiveFailures++;\n    this.timing.recordGamNoFill();\n    const remaining = this.timing.getRemainingAdMs();\n    if (this.debug) {\n      console.log(\n        `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.timing.consecutiveFailures}`,\n        this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n      );\n    }\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) console.log(`[CONTINUOUS-FETCH] Max consecutive failures reached (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n      this.handleAdPodComplete();\n      return;\n    }\n    if (this.timing.hasTimeToStartAnotherAd()) {\n      this.tryNextAvailableAdWithRateLimit();\n    } else {\n      if (this.debug) console.log(\"[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:\", this.timing.failedVastUrls.size);\n      this.handleAdPodComplete();\n    }\n  }\n};\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n  constructor(config) {\n    this.attached = false;\n    this.palPlaybackStarted = false;\n    initializePolyfills();\n    const browserOverrides = getBrowserConfigOverrides();\n    this.config = { ...browserOverrides, ...config };\n    this.video = config.videoElement;\n    logBrowserInfo(config.debugAdTiming);\n    this.adPlayer = this.createAdPlayer(false);\n    this.palNonce = createPalNonceManager();\n    this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {\n      onEarlyStartCue: (marker, fragmentSn, cueKey) => {\n        this.startAdPrefetch(marker, fragmentSn, cueKey);\n      },\n      onPlaybackCue: (marker, cueKey) => {\n        this.onScte35Marker(marker, cueKey);\n      },\n      isInAdBreak: () => this.adBreak.inAdBreak\n    });\n    this.adConfig = new AdConfigManager(this.config, this.video);\n    this.timing = new AdTimingService(this.config, this.video, {\n      onAdStopTimerFired: () => this.onAdStopTimerFired(),\n      onAdStartTimerFired: (marker, cueKey) => {\n        this.startScte35AdBreak(\n          marker,\n          cueKey,\n          marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.timing.expectedAdBreakDurationMs\n        );\n      },\n      onWatchdogTimeout: () => this.adBreak.handleAdFailure(),\n      onFailsafeTimeout: () => this.adBreak.handleAdFailure()\n    });\n    this.placeholder = new PlaceholderLayer(this.video, !!this.config.debugAdTiming);\n    this.hlsEngine = new HlsEngine(this.config, this.video, this.cueManager, this.timing, {\n      onManifestParsed: async (isLive) => this.onManifestParsed(isLive),\n      onScte35Cue: (marker, context) => this.cueManager.onScte35Cue(marker, context),\n      activatePendingCuesForFragment: (frag) => this.cueManager.activatePendingScte35CuesForFragment(frag),\n      onFatalDestroy: () => this.destroy(),\n      isInAdBreak: () => this.adBreak.inAdBreak,\n      hasPendingAdBreak: () => this.adBreak.pendingAdBreak !== null\n    });\n    this.adBreak = new AdBreakOrchestrator(\n      {\n        config: this.config,\n        video: this.video,\n        getAdPlayer: () => this.adPlayer,\n        setAdPlayer: (p) => {\n          this.adPlayer = p;\n        },\n        createAdPlayer: (c) => this.createAdPlayer(c),\n        shouldContinueLiveStreamDuringAds: () => this.shouldContinueLiveStreamDuringAds(),\n        isLiveStream: () => this.hlsEngine.isLiveStream,\n        getLiveSyncPosition: () => this.hlsEngine.getLiveSyncPosition(),\n        restartHlsLoad: (position) => this.hlsEngine.restartLoadAt(position),\n        reloadLiveStream: () => this.hlsEngine.reloadLiveStream(),\n        recoverMediaError: () => this.hlsEngine.recoverMediaError(),\n        generatePodVastUrl: (base, breakDurationMs) => this.generatePodVastUrl(base, breakDurationMs)\n      },\n      this.timing,\n      this.adConfig,\n      this.cueManager,\n      this.placeholder\n    );\n  }\n  get debug() {\n    return !!this.config.debugAdTiming;\n  }\n  createAdPlayer(continueLiveStreamDuringAds) {\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Creating HLS ad player\");\n    }\n    return createHlsAdPlayer(this.video, {\n      continueLiveStreamDuringAds,\n      ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},\n      ...this.hlsEngine?.hls ? { mainHlsInstance: this.hlsEngine.hls } : {}\n    });\n  }\n  generatePodVastUrl(baseUrl, breakDurationMs) {\n    const podParams = this.adConfig.resolvePodParams(breakDurationMs);\n    return this.adConfig.generatePodVastUrl(\n      baseUrl,\n      podParams,\n      this.adPlayer,\n      this.palNonce,\n      this.adBreak.inAdBreak\n    );\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Lifecycle\n  // ───────────────────────────────────────────────────────────────\n  async load() {\n    if (!this.attached) {\n      this.attach();\n    }\n    try {\n      await this.adConfig.fetchAdConfiguration();\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] Failed to fetch ad configuration:\",\n          error\n        );\n      }\n    }\n    this.palNonce.generateNonce({\n      videoWidth: this.video.offsetWidth || this.video.clientWidth || 640,\n      videoHeight: this.video.offsetHeight || this.video.clientHeight || 480,\n      adWillAutoPlay: !!this.config.autoplay,\n      adWillPlayMuted: true,\n      playerVolume: 0,\n      continuousPlayback: this.config.lowLatencyMode ?? false\n    }).catch(() => {\n    });\n    fetchConsentSignals().then((signals) => {\n      this.adConfig.consentSignals = signals;\n    }).catch(() => {\n    });\n    this.adConfig.initializeTracking();\n    if (this.hlsEngine.shouldUseNativeHls(() => this.getStreamType())) {\n      await this.hlsEngine.setupNativeHls();\n      const continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Native HLS ad behavior:\", {\n          isLive: this.hlsEngine.isLiveStream,\n          continueLiveStreamDuringAds\n        });\n      }\n      this.adPlayer.destroy();\n      this.adPlayer = this.createAdPlayer(continueLiveStreamDuringAds);\n      this.adPlayer.initialize();\n      return;\n    }\n    this.hlsEngine.setupHls();\n  }\n  async onManifestParsed(isLive) {\n    if (this.hlsEngine.reloadingLiveStream) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Manifest re-parsed after hard reload \\u2014 skipping ad-player setup\");\n      }\n      return;\n    }\n    if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {\n      const prerollKey = \"synthetic-vod-preroll\";\n      if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {\n        this.adConfig.vmapBreaks = [\n          { id: prerollKey, startTimeMs: 0, vastTagUrl: this.adConfig.apiVastTagUrl }\n        ];\n        if (this.debug) {\n          console.log(\n            \"[StormcloudVideoPlayer] Injected synthetic VOD preroll from apiVastTagUrl\"\n          );\n        }\n      }\n    }\n    if (this.debug) {\n      const adBehavior = this.shouldContinueLiveStreamDuringAds() ? \"live (main video continues muted during ads)\" : \"vod (main video pauses during ads)\";\n      console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n        isLive,\n        allowNativeHls: this.config.allowNativeHls,\n        adBehavior\n      });\n    }\n    this.adPlayer.destroy();\n    this.adPlayer = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());\n    this.adPlayer.initialize();\n  }\n  attach() {\n    if (this.attached) return;\n    this.attached = true;\n    this.video.autoplay = !!this.config.autoplay;\n    this.video.muted = !!this.config.muted;\n    this.adPlayer.initialize();\n    this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n    this.adBreak.attachImaEventListeners();\n    this.video.addEventListener(\"play\", () => {\n      if (!this.palPlaybackStarted && !this.adPlayer.isAdPlaying()) {\n        this.palPlaybackStarted = true;\n        this.palNonce.sendPlaybackStart();\n      }\n    });\n    this.endedHandler = () => {\n      if (this.palPlaybackStarted) {\n        this.palPlaybackStarted = false;\n        this.palNonce.sendPlaybackEnd();\n      }\n      this.onVideoEnded();\n    };\n    this.video.addEventListener(\"ended\", this.endedHandler);\n    this.video.addEventListener(\"mousedown\", (e) => {\n      this.palNonce.sendAdTouch(e);\n    });\n    this.video.addEventListener(\"touchstart\", (e) => {\n      this.palNonce.sendAdTouch(e);\n    });\n    this.timeUpdateHandler = () => {\n      this.onTimeUpdate(this.video.currentTime);\n    };\n    this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n    this.emptiedHandler = () => {\n      if (this.hlsEngine.nativeHlsMode && this.hlsEngine.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n        if (this.debug) {\n          console.log(\n            \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n            this.hlsEngine.videoSrcProtection\n          );\n        }\n        const currentTime = this.video.currentTime;\n        const wasPaused = this.video.paused;\n        this.video.src = this.hlsEngine.videoSrcProtection;\n        this.video.currentTime = currentTime;\n        if (!wasPaused) {\n          this.video.play().catch(() => {\n          });\n        }\n      }\n    };\n    this.video.addEventListener(\"emptied\", this.emptiedHandler);\n  }\n  shouldContinueLiveStreamDuringAds() {\n    if (this.config.pauseContentDuringAds) {\n      return false;\n    }\n    if (this.hlsEngine.isLiveStream) {\n      return true;\n    }\n    const duration = this.video.duration;\n    if (!Number.isFinite(duration) || duration === Infinity) {\n      return true;\n    }\n    return false;\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  SCTE-35 marker orchestration\n  // ───────────────────────────────────────────────────────────────\n  onScte35Marker(marker, cueKey) {\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n        type: marker.type,\n        ptsSeconds: marker.ptsSeconds,\n        durationSeconds: marker.durationSeconds,\n        currentTime: this.video.currentTime,\n        raw: marker.raw,\n        hasPendingAdBreak: !!this.adBreak.pendingAdBreak\n      });\n    }\n    if (marker.type === \"start\") {\n      if (this.adBreak.inAdBreak) {\n        if (marker.durationSeconds != null) {\n          const newDurationMs = marker.durationSeconds * 1e3;\n          if (this.timing.expectedAdBreakDurationMs == null || newDurationMs > this.timing.expectedAdBreakDurationMs) {\n            this.timing.setAdBreakDurationBoundary(newDurationMs);\n            this.timing.scheduleAdStopAtBreakBoundary();\n            if (this.debug) {\n              console.log(\n                `[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${newDurationMs}ms, remaining: ${this.timing.getWallClockRemainingAdMs()}ms`\n              );\n            }\n          }\n        }\n        return;\n      }\n      if (!this.adBreak.adDetectSentForCurrentBreak) {\n        this.adBreak.adDetectSentForCurrentBreak = true;\n        const detectPayload = {};\n        if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n        if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n        sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...detectPayload }, buildAnalyticsContext(this.config)).catch(() => {\n        });\n      }\n      const hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;\n      const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.adBreak.pendingAdBreak?.marker.durationSeconds != null ? this.adBreak.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n      const isManifest = isManifestBasedMarker(marker);\n      const forceImmediate = this.config.immediateManifestAds ?? true;\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n          isManifestMarker: isManifest,\n          forceImmediate,\n          hasPts: typeof marker.ptsSeconds === \"number\",\n          hasPrefetchedAds\n        });\n      }\n      if (isManifest && forceImmediate) {\n        if (this.debug) {\n          console.log(\n            `[StormcloudVideoPlayer] Starting ad immediately (manifest-based)${hasPrefetchedAds ? \" with prefetched ads\" : \"\"}`\n          );\n        }\n        this.timing.clearAdStartTimer();\n        this.startScte35AdBreak(marker, cueKey, durationMs);\n      } else if (typeof marker.ptsSeconds === \"number\") {\n        const tol = this.config.driftToleranceMs ?? 1e3;\n        const nowMs = this.video.currentTime * 1e3;\n        const estCurrentPtsMs = nowMs - this.timing.ptsDriftEmaMs;\n        const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n            nowMs,\n            estCurrentPtsMs,\n            markerPtsMs: marker.ptsSeconds * 1e3,\n            deltaMs,\n            tolerance: tol\n          });\n        }\n        if (deltaMs > tol) {\n          if (this.debug) {\n            console.log(`[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`);\n          }\n          this.timing.expectedAdBreakDurationMs = durationMs;\n          this.cueManager.scheduledScte35BreakKey = cueKey;\n          this.timing.scheduleAdStartIn(deltaMs, marker, cueKey);\n        } else {\n          if (this.debug) {\n            console.log(\"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\");\n          }\n          this.timing.clearAdStartTimer();\n          this.startScte35AdBreak(marker, cueKey, durationMs);\n        }\n      } else {\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Starting ad immediately (fallback)\");\n        }\n        this.timing.clearAdStartTimer();\n        this.startScte35AdBreak(marker, cueKey, durationMs);\n      }\n      return;\n    }\n    if (marker.type === \"progress\" && this.adBreak.inAdBreak) {\n      if (marker.durationSeconds != null) {\n        this.timing.setAdBreakDurationBoundary(marker.durationSeconds * 1e3);\n      }\n      this.timing.scheduleAdStopAtBreakBoundary();\n      if (!this.adPlayer.isAdPlaying() && this.timing.activeAdRequestToken === null && this.adBreak.adRequestQueue.length > 0 && this.timing.hasTimeToStartAnotherAd()) {\n        this.adBreak.tryNextAvailableAdWithRateLimit();\n      }\n      return;\n    }\n    if (marker.type === \"end\") {\n      if (!this.video.muted) {\n        this.video.muted = true;\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n        }\n      }\n      const remaining = this.timing.getRemainingAdMs();\n      const adPlaying = this.adPlayer.isAdPlaying();\n      const hasQueuedAds = this.adBreak.adRequestQueue.length > 0;\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n          remaining,\n          adPlaying,\n          hasQueuedAds,\n          activeAdRequest: this.timing.activeAdRequestToken !== null\n        });\n      }\n      this.timing.scteAdBreakEndWallClockMs = Date.now();\n      this.timing.clearAdStartTimer();\n      this.timing.clearAdStopTimer();\n      if (adPlaying) {\n        this.adPlayer.stop().catch(() => {\n        });\n      }\n      this.adBreak.handleAdPodComplete();\n      return;\n    }\n  }\n  startScte35AdBreak(marker, cueKey, durationMs) {\n    this.adBreak.inAdBreak = true;\n    this.cueManager.activeScte35BreakKey = cueKey ?? this.cueManager.pendingScte35CueKey;\n    this.cueManager.scheduledScte35BreakKey = void 0;\n    this.timing.currentAdBreakStartWallClockMs = this.timing.resolveScteBreakStartWallClockMs(marker);\n    this.timing.setAdBreakDurationBoundary(durationMs);\n    this.adBreak.handleAdStart(marker);\n    this.timing.scheduleAdStopAtBreakBoundary();\n  }\n  onAdStopTimerFired() {\n    if (!this.adBreak.inAdBreak) return;\n    const adPlaying = this.adPlayer.isAdPlaying();\n    const checkIntervalMs = Math.max(\n      250,\n      Math.floor(this.config.adBreakCheckIntervalMs ?? 1e3)\n    );\n    const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n    const maxExtensionMs = typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 0;\n    const endWallClockMs = this.timing.getAdBreakEndWallClockMs() ?? Date.now();\n    const overrunMs = Math.max(0, Date.now() - endWallClockMs);\n    const shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;\n    if (shouldExtendAdBreak) {\n      this.timing.scheduleAdStopCountdown(checkIntervalMs);\n      return;\n    }\n    if (this.debug) {\n      console.log(\n        `[StormcloudVideoPlayer] Ad break boundary reached (overrun=${overrunMs}ms) - hard-stopping ads and resuming stream`\n      );\n    }\n    if (adPlaying) {\n      this.adPlayer.stop().catch(() => {\n      });\n    }\n    this.adBreak.handleAdPodComplete();\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Ad prefetch\n  // ───────────────────────────────────────────────────────────────\n  startAdPrefetch(marker, fragmentSn, cueKey) {\n    if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;\n    const scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);\n    const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n    let baseVastUrl;\n    if (tags && tags.length > 0 && tags[0]) {\n      baseVastUrl = tags[0];\n    } else if (this.adConfig.apiVastTagUrl) {\n      baseVastUrl = this.adConfig.apiVastTagUrl;\n    } else {\n      if (this.debug) console.warn(\"[StormcloudVideoPlayer] No VAST URL available for prefetch\");\n      return;\n    }\n    this.adConfig.beginNewAdPod();\n    this.adConfig.podAssignedByPrefetch = true;\n    const breakDurationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;\n    const generatedUrls = [this.generatePodVastUrl(baseVastUrl, breakDurationMs)];\n    this.adBreak.pendingAdBreak = {\n      marker,\n      ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n      vastUrls: generatedUrls,\n      isFetching: false,\n      fetchStartTime: Date.now()\n    };\n    this.cueManager.pendingScte35CueKey = cueKey;\n    this.adBreak.adDetectSentForCurrentBreak = true;\n    const detectPayload = {};\n    if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;\n    if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;\n    if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;\n    sendAdDetectTracking(this.config.licenseKey, { source: \"scte35\", timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...detectPayload }, buildAnalyticsContext(this.config)).catch(() => {\n    });\n    if (this.debug) {\n      console.log(\"[PREFETCH] Starting ad prefetch for upcoming ad break\");\n      console.log(`[PREFETCH] Pre-generated pod request URL`);\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  VMAP time-based ad breaks\n  // ───────────────────────────────────────────────────────────────\n  onTimeUpdate(currentTimeSec) {\n    if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;\n    if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;\n    const nowMs = currentTimeSec * 1e3;\n    const breakToPlay = this.adConfig.findBreakForTime(nowMs);\n    if (breakToPlay) {\n      void this.handleVmapAdBreak(breakToPlay, nowMs).catch((error) => {\n        if (this.debug) {\n          console.warn(\"[StormcloudVideoPlayer] VMAP ad break failed gracefully:\", error);\n        }\n      });\n    }\n  }\n  onVideoEnded() {\n    if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;\n    if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;\n    const durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;\n    const postroll = this.adConfig.vmapBreaks.find(\n      (b) => b.startTimeMs === -1 && !this.adConfig.consumedVmapBreakIds.has(this.adConfig.getAdBreakKey(b))\n    );\n    if (postroll) {\n      void this.handleVmapAdBreak(postroll, durationMs).catch((error) => {\n        if (this.debug) {\n          console.warn(\"[StormcloudVideoPlayer] VMAP post-roll failed gracefully:\", error);\n        }\n      });\n    }\n  }\n  async handleVmapAdBreak(adBreak, nowMs) {\n    const key = this.adConfig.getAdBreakKey(adBreak);\n    if (this.adConfig.consumedVmapBreakIds.has(key)) return;\n    const breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);\n    if (breakStartMs == null) return;\n    const durationMs = adBreak.durationMs ?? 0;\n    const endMs = breakStartMs + durationMs;\n    const inWindow = durationMs > 0 ? nowMs >= breakStartMs && nowMs < endMs : nowMs >= breakStartMs;\n    if (inWindow) {\n      this.adConfig.consumedVmapBreakIds.add(key);\n      const tags = this.adConfig.selectVastTagsForBreak(adBreak);\n      if (!tags || tags.length === 0) return;\n      const first = tags[0];\n      const rest = tags.slice(1);\n      this.adBreak.adPodQueue = rest;\n      this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n      this.adBreak.showAds = true;\n      this.adBreak.inAdBreak = true;\n      this.timing.currentAdBreakStartWallClockMs = Date.now();\n      try {\n        await this.adBreak.playSingleAd(first);\n      } catch (error) {\n        if (this.debug) {\n          console.warn(\"[StormcloudVideoPlayer] VMAP ad request failed:\", error);\n        }\n        this.adBreak.handleAdPodComplete();\n      }\n    }\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Public API\n  // ───────────────────────────────────────────────────────────────\n  getCurrentAdIndex() {\n    return this.timing.currentAdIndex;\n  }\n  getTotalAdsInBreak() {\n    return this.timing.totalAdsInBreak;\n  }\n  getAdRemainingMs() {\n    return this.timing.getRemainingAdMs();\n  }\n  isAdPlaying() {\n    return this.adBreak.inAdBreak && this.adPlayer.isAdPlaying();\n  }\n  isShowingAds() {\n    return this.adBreak.showAds;\n  }\n  getStreamType() {\n    const url = this.config.src.toLowerCase();\n    if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n      return \"hls\";\n    }\n    return \"other\";\n  }\n  shouldShowNativeControls() {\n    const streamType = this.getStreamType();\n    if (streamType === \"other\") {\n      return !(this.config.showCustomControls ?? false);\n    }\n    return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n  }\n  isLive() {\n    return this.hlsEngine.isLiveStream;\n  }\n  get videoElement() {\n    return this.video;\n  }\n  toggleMute() {\n    toggleMute(this.video, this.adPlayer, this.debug);\n  }\n  toggleFullscreen() {\n    return toggleFullscreen(this.video, this.debug);\n  }\n  isMuted() {\n    return isMuted(this.video, this.adPlayer);\n  }\n  setMuted(muted) {\n    setMuted(this.video, this.adPlayer, muted, this.debug);\n  }\n  setVolume(volume) {\n    setVolume(this.video, this.adPlayer, volume, this.debug);\n  }\n  getVolume() {\n    return getVolume(this.video, this.adPlayer);\n  }\n  isFullscreen() {\n    return isFullscreen();\n  }\n  resize() {\n    resizePlayer(this.video, this.adPlayer, this.debug);\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  Destroy\n  // ───────────────────────────────────────────────────────────────\n  destroy() {\n    this.adBreak.stopContinuousFetching();\n    this.timing.destroy();\n    this.adBreak.clearPendingAdBreak();\n    this.placeholder.destroy();\n    if (this.timeUpdateHandler) {\n      this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n      delete this.timeUpdateHandler;\n    }\n    if (this.endedHandler) {\n      this.video.removeEventListener(\"ended\", this.endedHandler);\n      delete this.endedHandler;\n    }\n    if (this.emptiedHandler) {\n      this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n      delete this.emptiedHandler;\n    }\n    this.adConfig.destroyTracking();\n    this.hlsEngine.destroy();\n    this.adPlayer?.destroy();\n    if (this.palPlaybackStarted) {\n      this.palPlaybackStarted = false;\n      this.palNonce.sendPlaybackEnd();\n    }\n    this.palNonce.reset();\n    this.adBreak.adRequestQueue = [];\n    this.timing.consecutiveFailures = 0;\n  }\n};\n\n// src/ui/StormcloudVideoPlayer.tsx\nvar import_fa = require(\"react-icons/fa\");\nvar import_jsx_runtime = require(\"react/jsx-runtime\");\nvar ExpandIcon = ({ size = 18 }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n  \"svg\",\n  {\n    width: size,\n    height: size,\n    viewBox: \"0 0 24 24\",\n    fill: \"none\",\n    stroke: \"currentColor\",\n    strokeWidth: 2,\n    strokeLinecap: \"round\",\n    strokeLinejoin: \"round\",\n    \"aria-hidden\": \"true\",\n    focusable: \"false\",\n    children: [\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M9 4H4v5\" }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M20 9V4h-5\" }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M15 20h5v-5\" }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M4 15v5h5\" })\n    ]\n  }\n);\nvar CompressIcon = ({ size = 18 }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n  \"svg\",\n  {\n    width: size,\n    height: size,\n    viewBox: \"0 0 24 24\",\n    fill: \"none\",\n    stroke: \"currentColor\",\n    strokeWidth: 2,\n    strokeLinecap: \"round\",\n    strokeLinejoin: \"round\",\n    \"aria-hidden\": \"true\",\n    focusable: \"false\",\n    children: [\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M4 9h5V4\" }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M15 4v5h5\" }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M20 15h-5v5\" }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"path\", { d: \"M9 20v-5H4\" })\n    ]\n  }\n);\nvar CRITICAL_PROPS = [\n  \"src\",\n  \"allowNativeHls\",\n  \"isLiveStream\",\n  \"licenseKey\",\n  \"isVmap\",\n  \"vmapUrl\",\n  \"lowLatencyMode\",\n  \"driftToleranceMs\",\n  \"vastMode\",\n  \"ctvAdRequest\"\n];\nvar CONTROLS_HIDE_DELAY = 3e3;\nvar DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;\nvar StormcloudVideoPlayerComponent = import_react.default.memo(\n  (props) => {\n    const {\n      src,\n      autoplay,\n      muted,\n      lowLatencyMode,\n      allowNativeHls,\n      isLiveStream,\n      driftToleranceMs,\n      immediateManifestAds,\n      debugAdTiming,\n      showCustomControls,\n      hideLoadingIndicator,\n      onVolumeToggle,\n      onFullscreenToggle,\n      onControlClick,\n      onReady,\n      wrapperClassName,\n      wrapperStyle,\n      className,\n      style,\n      controls,\n      playsInline,\n      preload,\n      poster,\n      children,\n      licenseKey,\n      vastMode,\n      vastTagUrl,\n      isVmap,\n      vmapUrl,\n      minSegmentsBeforePlay,\n      ctvAdRequest,\n      ...restVideoAttrs\n    } = props;\n    const videoRef = (0, import_react.useRef)(null);\n    const playerRef = (0, import_react.useRef)(null);\n    const bufferingTimeoutRef = (0, import_react.useRef)(null);\n    const controlsTimerRef = (0, import_react.useRef)(null);\n    const wrapperRef = (0, import_react.useRef)(null);\n    const [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0, remainingSeconds: 0 });\n    const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);\n    const [isMuted2, setIsMuted] = import_react.default.useState(false);\n    const [isFullscreen2, setIsFullscreen] = import_react.default.useState(false);\n    const [isPlaying, setIsPlaying] = import_react.default.useState(false);\n    const [currentTime, setCurrentTime] = import_react.default.useState(0);\n    const [duration, setDuration] = import_react.default.useState(0);\n    const [volume, setVolume2] = import_react.default.useState(1);\n    const [playbackRate, setPlaybackRate] = import_react.default.useState(1);\n    const [showVolumeSlider, setShowVolumeSlider] = import_react.default.useState(false);\n    const [showSpeedMenu, setShowSpeedMenu] = import_react.default.useState(false);\n    const [isLoading, setIsLoading] = import_react.default.useState(true);\n    const [isBuffering, setIsBuffering] = import_react.default.useState(false);\n    const [showCenterPlay, setShowCenterPlay] = import_react.default.useState(false);\n    const [showLicenseWarning, setShowLicenseWarning] = import_react.default.useState(false);\n    const [controlsVisible, setControlsVisible] = import_react.default.useState(true);\n    const [viewportWidth, setViewportWidth] = import_react.default.useState(\n      typeof window !== \"undefined\" ? window.innerWidth : 1920\n    );\n    const [isPortrait, setIsPortrait] = import_react.default.useState(\n      typeof window !== \"undefined\" ? window.innerHeight > window.innerWidth : false\n    );\n    const [playerAspectRatio, setPlayerAspectRatio] = import_react.default.useState(\n      DEFAULT_PLAYER_ASPECT_RATIO\n    );\n    const getResponsiveScale = () => {\n      if (viewportWidth < 480) return 0.7;\n      if (viewportWidth < 768) return 0.8;\n      if (viewportWidth < 1024) return 0.9;\n      return 1;\n    };\n    const responsiveScale = getResponsiveScale();\n    const resetControlsTimer = (0, import_react.useCallback)(() => {\n      if (controlsTimerRef.current) {\n        clearTimeout(controlsTimerRef.current);\n      }\n      setControlsVisible(true);\n      controlsTimerRef.current = window.setTimeout(() => {\n        if (!showVolumeSlider && !showSpeedMenu) {\n          setControlsVisible(false);\n        }\n      }, CONTROLS_HIDE_DELAY);\n    }, [showVolumeSlider, showSpeedMenu]);\n    const handleWrapperMouseMove = (0, import_react.useCallback)(() => {\n      resetControlsTimer();\n    }, [resetControlsTimer]);\n    const handleWrapperMouseLeave = (0, import_react.useCallback)(() => {\n      if (!showVolumeSlider && !showSpeedMenu) {\n        setControlsVisible(false);\n      }\n    }, [showVolumeSlider, showSpeedMenu]);\n    const formatTime = (seconds) => {\n      if (!isFinite(seconds)) return \"0:00:00\";\n      const hours = Math.floor(seconds / 3600);\n      const minutes = Math.floor(seconds % 3600 / 60);\n      const remainingSeconds = Math.floor(seconds % 60);\n      return `${hours}:${minutes.toString().padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n    };\n    const handlePlayPause = () => {\n      if (videoRef.current) {\n        if (videoRef.current.paused) {\n          const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== \"\" || videoRef.current.readyState >= 1;\n          if (hasValidSource) {\n            videoRef.current.play()?.catch((error) => {\n              console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n            });\n            setShowCenterPlay(false);\n          } else {\n            console.warn(\n              \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n            );\n          }\n        } else {\n          videoRef.current.pause();\n          setShowCenterPlay(true);\n        }\n      }\n      resetControlsTimer();\n    };\n    const handleCenterPlayClick = () => {\n      if (videoRef.current && videoRef.current.paused) {\n        const hasValidSource = videoRef.current.src || videoRef.current.currentSrc && videoRef.current.currentSrc !== \"\" || videoRef.current.readyState >= 1;\n        if (hasValidSource) {\n          videoRef.current.play()?.catch((error) => {\n            console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n          });\n          setShowCenterPlay(false);\n        } else {\n          console.warn(\n            \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n          );\n        }\n      }\n    };\n    const handleTimelineSeek = (e) => {\n      if (videoRef.current && duration > 0 && isFinite(duration)) {\n        const rect = e.currentTarget.getBoundingClientRect();\n        const clickX = e.clientX - rect.left;\n        const progress = Math.max(0, Math.min(1, clickX / rect.width));\n        const newTime = progress * duration;\n        if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {\n          videoRef.current.currentTime = newTime;\n        }\n      }\n      resetControlsTimer();\n    };\n    const handleVolumeChange = (newVolume) => {\n      if (playerRef.current && isFinite(newVolume)) {\n        const clampedVolume = Math.max(0, Math.min(1, newVolume));\n        playerRef.current.setVolume(clampedVolume);\n      }\n    };\n    const handlePlaybackRateChange = (rate) => {\n      if (videoRef.current && isFinite(rate) && rate > 0) {\n        videoRef.current.playbackRate = rate;\n      }\n      setShowSpeedMenu(false);\n    };\n    const isHlsStream = src?.toLowerCase().includes(\".m3u8\") || src?.toLowerCase().includes(\"/hls/\");\n    const isLiveUiMode = isLiveStream === true;\n    const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? !isLiveUiMode : true);\n    const criticalPropsKey = (0, import_react.useMemo)(() => {\n      return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n    }, [\n      src,\n      allowNativeHls,\n      isLiveStream,\n      licenseKey,\n      isVmap,\n      vmapUrl,\n      lowLatencyMode,\n      driftToleranceMs,\n      vastMode\n    ]);\n    (0, import_react.useEffect)(() => {\n      if (typeof window === \"undefined\") return;\n      const el = videoRef.current;\n      if (!el || !src) return;\n      if (!licenseKey) {\n        setShowLicenseWarning(true);\n        setIsLoading(false);\n        console.warn(\n          \"StormcloudVideoPlayer: License key is required but not provided. Please set the licenseKey prop to use the player.\"\n        );\n        return;\n      }\n      setShowLicenseWarning(false);\n      if (debugAdTiming) {\n        console.log(\"[StormcloudUI] Initializing player, isLoading=true\");\n      }\n      if (playerRef.current) {\n        try {\n          playerRef.current.destroy();\n        } catch {\n        }\n        playerRef.current = null;\n      }\n      const cfg = {\n        src,\n        videoElement: el\n      };\n      if (autoplay !== void 0) cfg.autoplay = autoplay;\n      if (muted !== void 0) cfg.muted = muted;\n      if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;\n      if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;\n      if (isLiveStream !== void 0) cfg.isLiveStream = isLiveStream;\n      if (driftToleranceMs !== void 0)\n        cfg.driftToleranceMs = driftToleranceMs;\n      if (immediateManifestAds !== void 0)\n        cfg.immediateManifestAds = immediateManifestAds;\n      if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;\n      if (showCustomControls !== void 0)\n        cfg.showCustomControls = showCustomControls;\n      if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;\n      if (onFullscreenToggle !== void 0)\n        cfg.onFullscreenToggle = onFullscreenToggle;\n      if (onControlClick !== void 0) cfg.onControlClick = onControlClick;\n      if (licenseKey !== void 0) cfg.licenseKey = licenseKey;\n      if (vastMode !== void 0) cfg.vastMode = vastMode;\n      if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;\n      if (isVmap !== void 0) cfg.isVmap = isVmap;\n      if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;\n      if (minSegmentsBeforePlay !== void 0)\n        cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n      if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;\n      const player = new StormcloudVideoPlayer(cfg);\n      playerRef.current = player;\n      player.load().then(() => {\n        const showNative = player.shouldShowNativeControls();\n        setShouldShowNativeControls(showNative);\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Player loaded successfully, waiting for video ready\"\n          );\n        }\n        onReady?.(player);\n      }).catch((error) => {\n        console.error(\n          \"StormcloudVideoPlayer: Failed to load player:\",\n          error\n        );\n        setIsLoading(false);\n        onReady?.(player);\n      });\n      return () => {\n        try {\n          player.destroy();\n        } catch {\n        }\n        playerRef.current = null;\n      };\n    }, [criticalPropsKey]);\n    (0, import_react.useEffect)(() => {\n      if (!playerRef.current) return;\n      try {\n        if (autoplay !== void 0 && playerRef.current.videoElement) {\n          playerRef.current.videoElement.autoplay = autoplay;\n        }\n        if (muted !== void 0 && !playerRef.current.isShowingAds()) {\n          playerRef.current.setMuted(muted);\n        }\n      } catch (error) {\n        console.warn(\"Failed to update player properties:\", error);\n      }\n    }, [autoplay, muted]);\n    (0, import_react.useEffect)(() => {\n      if (!playerRef.current) return;\n      const checkAdStatus = () => {\n        if (playerRef.current) {\n          const showAdsFromMethod = playerRef.current.isShowingAds();\n          const showAdsFromAttribute = videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n          const showAds = showAdsFromMethod || showAdsFromAttribute;\n          const currentIndex = playerRef.current.getCurrentAdIndex();\n          const totalAds = playerRef.current.getTotalAdsInBreak();\n          const remainingMs = playerRef.current.getAdRemainingMs();\n          const remainingSeconds = showAds ? Math.max(0, Math.ceil(remainingMs / 1e3)) : 0;\n          setAdStatus((prev) => {\n            if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds || prev.remainingSeconds !== remainingSeconds) {\n              if (showAds && !prev.showAds) {\n                setShowCenterPlay(false);\n              }\n              return { showAds, currentIndex, totalAds, remainingSeconds };\n            }\n            return prev;\n          });\n        }\n      };\n      const interval = setInterval(checkAdStatus, 50);\n      return () => clearInterval(interval);\n    }, []);\n    (0, import_react.useEffect)(() => {\n      if (typeof window === \"undefined\" || !playerRef.current) return;\n      const handleResize = () => {\n        if (playerRef.current && videoRef.current) {\n          if (typeof playerRef.current.resize === \"function\") {\n            playerRef.current.resize();\n          }\n        }\n        setViewportWidth(window.innerWidth);\n        setIsPortrait(window.innerHeight > window.innerWidth);\n      };\n      window.addEventListener(\"resize\", handleResize);\n      return () => window.removeEventListener(\"resize\", handleResize);\n    }, []);\n    (0, import_react.useEffect)(() => {\n      if (!playerRef.current || !videoRef.current) return;\n      const updateStates = () => {\n        if (playerRef.current && videoRef.current) {\n          setIsMuted(playerRef.current.isMuted());\n          setIsPlaying(!videoRef.current.paused);\n          const currentTimeValue = videoRef.current.currentTime;\n          setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);\n          const durationValue = videoRef.current.duration;\n          setDuration(isFinite(durationValue) ? durationValue : 0);\n          const volumeValue = playerRef.current.getVolume();\n          setVolume2(\n            isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1\n          );\n          const rateValue = videoRef.current.playbackRate;\n          setPlaybackRate(\n            isFinite(rateValue) && rateValue > 0 ? rateValue : 1\n          );\n        }\n        setIsFullscreen(\n          document.fullscreenElement === wrapperRef.current\n        );\n      };\n      const interval = setInterval(updateStates, 200);\n      const handleFullscreenChange = () => {\n        setIsFullscreen(\n          document.fullscreenElement === wrapperRef.current\n        );\n      };\n      document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n      return () => {\n        clearInterval(interval);\n        document.removeEventListener(\n          \"fullscreenchange\",\n          handleFullscreenChange\n        );\n      };\n    }, []);\n    (0, import_react.useEffect)(() => {\n      if (!videoRef.current) return;\n      const handleLoadedMetadata = () => {\n        const video2 = videoRef.current;\n        if (video2) {\n          if (video2.videoWidth > 0 && video2.videoHeight > 0) {\n            setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);\n          }\n          void video2.offsetHeight;\n        }\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: loadedmetadata, readyState:\",\n            videoRef.current?.readyState\n          );\n        }\n      };\n      const handleLoadedData = () => {\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: loadeddata, readyState:\",\n            videoRef.current?.readyState\n          );\n        }\n      };\n      const handleLoadStart = () => {\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: loadstart, readyState:\",\n            videoRef.current?.readyState\n          );\n        }\n      };\n      const handleCanPlay = () => {\n        setIsLoading(false);\n        if (bufferingTimeoutRef.current) {\n          clearTimeout(bufferingTimeoutRef.current);\n          bufferingTimeoutRef.current = null;\n        }\n        setIsBuffering(false);\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: canplay, readyState:\",\n            videoRef.current?.readyState,\n            \"- clearing loading state, isLoading=false\"\n          );\n        }\n      };\n      const handleCanPlayThrough = () => {\n        setIsLoading(false);\n        if (bufferingTimeoutRef.current) {\n          clearTimeout(bufferingTimeoutRef.current);\n          bufferingTimeoutRef.current = null;\n        }\n        setIsBuffering(false);\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: canplaythrough, readyState:\",\n            videoRef.current?.readyState,\n            \"- clearing loading state, isLoading=false\"\n          );\n        }\n      };\n      const handleWaiting = () => {\n        if (bufferingTimeoutRef.current) {\n          clearTimeout(bufferingTimeoutRef.current);\n        }\n        bufferingTimeoutRef.current = window.setTimeout(() => {\n          setIsBuffering(true);\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:\",\n              videoRef.current?.readyState,\n              \"- showing spinner, isBuffering=true\"\n            );\n          }\n        }, 300);\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: waiting, readyState:\",\n            videoRef.current?.readyState,\n            \"- buffering delay started (300ms)\"\n          );\n        }\n      };\n      const handlePlaying = () => {\n        setIsLoading(false);\n        if (bufferingTimeoutRef.current) {\n          clearTimeout(bufferingTimeoutRef.current);\n          bufferingTimeoutRef.current = null;\n        }\n        setIsBuffering(false);\n        setShowCenterPlay(false);\n        if (debugAdTiming) {\n          console.log(\n            \"[StormcloudUI] Video event: playing, readyState:\",\n            videoRef.current?.readyState,\n            \"- playback started, isLoading=false, isBuffering=false\"\n          );\n        }\n      };\n      const handlePause = () => {\n        const isAdActive = playerRef.current?.isShowingAds() || videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n        if (playerRef.current && !isAdActive) {\n          setShowCenterPlay(true);\n        } else {\n          setShowCenterPlay(false);\n        }\n      };\n      const handleEnded = () => {\n        setShowCenterPlay(true);\n      };\n      const video = videoRef.current;\n      video.addEventListener(\"loadstart\", handleLoadStart);\n      video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n      video.addEventListener(\"loadeddata\", handleLoadedData);\n      video.addEventListener(\"canplay\", handleCanPlay);\n      video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n      video.addEventListener(\"waiting\", handleWaiting);\n      video.addEventListener(\"playing\", handlePlaying);\n      video.addEventListener(\"pause\", handlePause);\n      video.addEventListener(\"ended\", handleEnded);\n      if (video.paused) {\n        setShowCenterPlay(true);\n      }\n      return () => {\n        if (bufferingTimeoutRef.current) {\n          clearTimeout(bufferingTimeoutRef.current);\n          bufferingTimeoutRef.current = null;\n        }\n        video.removeEventListener(\"loadstart\", handleLoadStart);\n        video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n        video.removeEventListener(\"loadeddata\", handleLoadedData);\n        video.removeEventListener(\"canplay\", handleCanPlay);\n        video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n        video.removeEventListener(\"waiting\", handleWaiting);\n        video.removeEventListener(\"playing\", handlePlaying);\n        video.removeEventListener(\"pause\", handlePause);\n        video.removeEventListener(\"ended\", handleEnded);\n      };\n    }, [debugAdTiming]);\n    (0, import_react.useEffect)(() => {\n      setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);\n    }, [src]);\n    (0, import_react.useEffect)(() => {\n      return () => {\n        if (controlsTimerRef.current) {\n          clearTimeout(controlsTimerRef.current);\n        }\n      };\n    }, []);\n    const progressPercent = duration > 0 ? currentTime / duration * 100 : 0;\n    const VolumeIcon = isMuted2 || volume === 0 ? import_fa.FaVolumeMute : volume < 0.5 ? import_fa.FaVolumeDown : import_fa.FaVolumeUp;\n    return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: `\n              @keyframes sc-spin {\n                from { transform: rotate(0deg); }\n                to { transform: rotate(360deg); }\n              }\n              @keyframes sc-loading-glow {\n                0%, 100% { opacity: 0.85; transform: scale(1); }\n                50% { opacity: 1; transform: scale(1.05); }\n              }\n              @keyframes sc-pulse {\n                0%, 100% { opacity: 1; }\n                50% { opacity: 0.6; }\n              }\n              @keyframes sc-fade-in {\n                from { opacity: 0; transform: translateY(8px); }\n                to { opacity: 1; transform: translateY(0); }\n              }\n              .sc-wrapper:fullscreen,\n              .sc-wrapper:has(*:fullscreen) {\n                border-radius: 0 !important;\n                box-shadow: none !important;\n                width: 100vw !important;\n                height: 100vh !important;\n                max-width: 100vw !important;\n                max-height: 100vh !important;\n                position: fixed !important;\n                top: 0 !important;\n                left: 0 !important;\n                z-index: 999999 !important;\n                background: #000 !important;\n                display: flex !important;\n                align-items: center !important;\n                justify-content: center !important;\n              }\n              .sc-ctrl-btn {\n                background: none;\n                border: none;\n                color: #fff;\n                cursor: pointer;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                border-radius: 50%;\n                padding: 8px;\n                transition: background 0.15s ease, opacity 0.15s ease;\n                opacity: 0.9;\n              }\n              .sc-ctrl-btn:hover {\n                opacity: 1;\n                background: rgba(255, 255, 255, 0.1);\n              }\n              .sc-ctrl-btn:active {\n                opacity: 0.7;\n              }\n              .sc-controls-bar {\n                transition: opacity 0.35s ease, transform 0.35s ease;\n              }\n              .sc-progress-track:hover .sc-progress-thumb {\n                transform: translate(-50%, -50%) scale(1) !important;\n              }\n              .sc-loading-hidden .sc-loading-indicator {\n                display: none !important;\n              }\n            ` }),\n      /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n        \"div\",\n        {\n          ref: wrapperRef,\n          className: `sc-wrapper ${wrapperClassName || \"\"}`,\n          onMouseMove: handleWrapperMouseMove,\n          onMouseLeave: handleWrapperMouseLeave,\n          style: {\n            display: \"flex\",\n            alignItems: \"center\",\n            justifyContent: \"center\",\n            position: isFullscreen2 ? \"fixed\" : \"relative\",\n            top: isFullscreen2 ? 0 : void 0,\n            left: isFullscreen2 ? 0 : void 0,\n            overflow: \"hidden\",\n            width: isFullscreen2 ? \"100vw\" : \"100%\",\n            height: isFullscreen2 ? \"100vh\" : \"auto\",\n            minHeight: isFullscreen2 ? \"100vh\" : \"auto\",\n            aspectRatio: isFullscreen2 ? void 0 : playerAspectRatio,\n            maxWidth: isFullscreen2 ? \"100vw\" : \"100%\",\n            maxHeight: isFullscreen2 ? \"100vh\" : \"none\",\n            zIndex: isFullscreen2 ? 999999 : void 0,\n            backgroundColor: \"#000\",\n            borderRadius: isFullscreen2 ? 0 : void 0,\n            boxShadow: isFullscreen2 ? \"none\" : void 0,\n            ...wrapperStyle\n          },\n          children: [\n            /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n              \"video\",\n              {\n                ref: videoRef,\n                className,\n                style: {\n                  display: \"block\",\n                  width: \"100%\",\n                  height: \"100%\",\n                  maxWidth: \"100%\",\n                  maxHeight: isFullscreen2 ? \"100%\" : \"none\",\n                  objectFit: isFullscreen2 ? \"cover\" : \"contain\",\n                  backgroundColor: \"#000\",\n                  aspectRatio: isFullscreen2 ? \"unset\" : void 0,\n                  ...style\n                },\n                controls: shouldShowNativeControls && controls && !showCustomControls,\n                playsInline,\n                preload,\n                poster,\n                ...restVideoAttrs,\n                children\n              }\n            ),\n            (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n              \"div\",\n              {\n                className: \"sc-loading-indicator\",\n                style: {\n                  position: \"absolute\",\n                  top: \"50%\",\n                  left: \"50%\",\n                  transform: \"translate(-50%, -50%)\",\n                  zIndex: 20,\n                  width: `${Math.max(34, 38 * responsiveScale)}px`,\n                  height: `${Math.max(34, 38 * responsiveScale)}px`,\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  justifyContent: \"center\",\n                  animation: \"sc-loading-glow 1.4s ease-in-out infinite\",\n                  filter: \"drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))\"\n                },\n                children: [\n                  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                    \"div\",\n                    {\n                      style: {\n                        position: \"absolute\",\n                        inset: 0,\n                        borderRadius: \"50%\",\n                        border: \"3px solid rgba(255, 255, 255, 0.25)\",\n                        borderTopColor: \"#ff0000\",\n                        borderRightColor: \"rgba(255, 255, 255, 0.85)\",\n                        animation: \"sc-spin 0.8s linear infinite\"\n                      }\n                    }\n                  ),\n                  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                    \"div\",\n                    {\n                      style: {\n                        width: \"7px\",\n                        height: \"7px\",\n                        borderRadius: \"50%\",\n                        background: \"#ff0000\",\n                        boxShadow: \"0 0 10px rgba(255, 0, 0, 0.65)\"\n                      }\n                    }\n                  )\n                ]\n              }\n            ),\n            showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n              \"div\",\n              {\n                style: {\n                  position: \"absolute\",\n                  top: \"50%\",\n                  left: \"50%\",\n                  transform: \"translate(-50%, -50%)\",\n                  zIndex: 25,\n                  background: \"rgba(220, 38, 38, 0.92)\",\n                  backdropFilter: \"blur(24px)\",\n                  color: \"white\",\n                  padding: \"28px 36px\",\n                  borderRadius: \"14px\",\n                  border: \"1px solid rgba(255, 255, 255, 0.15)\",\n                  boxShadow: \"0 24px 64px rgba(0, 0, 0, 0.5)\",\n                  textAlign: \"center\",\n                  maxWidth: \"400px\",\n                  margin: \"0 16px\"\n                },\n                children: [\n                  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { fontSize: \"18px\", fontWeight: \"700\", marginBottom: \"10px\", letterSpacing: \"-0.02em\" }, children: \"License Key Required\" }),\n                  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { fontSize: \"13px\", lineHeight: \"1.6\", color: \"rgba(255, 255, 255, 0.85)\" }, children: [\n                    \"Please provide a valid license key to use the Stormcloud Video Player.\",\n                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"br\", {}),\n                    \"Contact your administrator for licensing information.\"\n                  ] })\n                ]\n              }\n            ),\n            adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n              \"div\",\n              {\n                style: {\n                  position: \"absolute\",\n                  top: `${12 * responsiveScale}px`,\n                  left: `${12 * responsiveScale}px`,\n                  zIndex: 50,\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  gap: \"8px\",\n                  pointerEvents: \"none\",\n                  animation: \"sc-fade-in 0.3s ease\"\n                },\n                children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                  \"div\",\n                  {\n                    style: {\n                      background: \"rgba(234, 179, 8, 0.95)\",\n                      color: \"#111\",\n                      padding: `${4 * responsiveScale}px ${12 * responsiveScale}px`,\n                      borderRadius: \"6px\",\n                      fontSize: `${11 * responsiveScale}px`,\n                      fontWeight: 700,\n                      letterSpacing: \"0.08em\",\n                      textTransform: \"uppercase\",\n                      boxShadow: \"0 2px 12px rgba(234, 179, 8, 0.35)\"\n                    },\n                    children: `Ad ${Math.max(1, adStatus.currentIndex)}`\n                  }\n                )\n              }\n            ),\n            showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n              \"div\",\n              {\n                onClick: handleCenterPlayClick,\n                style: {\n                  position: \"absolute\",\n                  top: \"50%\",\n                  left: \"50%\",\n                  transform: \"translate(-50%, -50%)\",\n                  zIndex: 15,\n                  cursor: \"pointer\",\n                  background: \"rgba(0, 0, 0, 0.55)\",\n                  backdropFilter: \"blur(8px)\",\n                  borderRadius: \"50%\",\n                  width: `${92 * responsiveScale}px`,\n                  height: `${92 * responsiveScale}px`,\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  justifyContent: \"center\",\n                  transition: \"background 0.2s ease, transform 0.2s ease\",\n                  animation: \"sc-fade-in 0.2s ease\"\n                },\n                onMouseEnter: (e) => {\n                  e.currentTarget.style.background = \"rgba(0, 0, 0, 0.72)\";\n                  e.currentTarget.style.transform = \"translate(-50%, -50%) scale(1.06)\";\n                },\n                onMouseLeave: (e) => {\n                  e.currentTarget.style.background = \"rgba(0, 0, 0, 0.55)\";\n                  e.currentTarget.style.transform = \"translate(-50%, -50%) scale(1)\";\n                },\n                title: \"Play\",\n                children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                  import_fa.FaPlay,\n                  {\n                    size: Math.max(24, 32 * responsiveScale),\n                    color: \"white\",\n                    style: { marginLeft: \"4px\" }\n                  }\n                )\n              }\n            ),\n            shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n              \"div\",\n              {\n                className: \"sc-controls-bar\",\n                style: {\n                  position: \"absolute\",\n                  bottom: 0,\n                  left: 0,\n                  right: 0,\n                  background: \"linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)\",\n                  padding: `${20 * responsiveScale}px ${12 * responsiveScale}px ${8 * responsiveScale}px`,\n                  zIndex: 10,\n                  opacity: controlsVisible || adStatus.showAds ? 1 : 0,\n                  transform: controlsVisible || adStatus.showAds ? \"translateY(0)\" : \"translateY(6px)\",\n                  pointerEvents: controlsVisible || adStatus.showAds ? \"auto\" : \"none\"\n                },\n                children: [\n                  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                    \"div\",\n                    {\n                      className: \"sc-progress-track\",\n                      style: {\n                        width: \"100%\",\n                        height: \"3px\",\n                        background: \"rgba(255, 255, 255, 0.2)\",\n                        borderRadius: \"1.5px\",\n                        marginBottom: `${8 * responsiveScale}px`,\n                        cursor: \"pointer\",\n                        position: \"relative\",\n                        transition: \"height 0.1s ease\"\n                      },\n                      onClick: handleTimelineSeek,\n                      onMouseEnter: (e) => {\n                        e.currentTarget.style.height = \"5px\";\n                      },\n                      onMouseLeave: (e) => {\n                        e.currentTarget.style.height = \"3px\";\n                      },\n                      children: [\n                        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                          \"div\",\n                          {\n                            style: {\n                              position: \"absolute\",\n                              top: 0,\n                              left: 0,\n                              bottom: 0,\n                              background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n                              borderRadius: \"1.5px\",\n                              width: `${progressPercent}%`,\n                              transition: \"width 0.15s linear\"\n                            }\n                          }\n                        ),\n                        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                          \"div\",\n                          {\n                            className: \"sc-progress-thumb\",\n                            style: {\n                              position: \"absolute\",\n                              top: \"50%\",\n                              left: `${progressPercent}%`,\n                              transform: \"translate(-50%, -50%) scale(0)\",\n                              width: \"13px\",\n                              height: \"13px\",\n                              background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n                              borderRadius: \"50%\",\n                              boxShadow: \"0 0 4px rgba(0, 0, 0, 0.3)\",\n                              transition: \"transform 0.1s ease, left 0.15s linear\"\n                            }\n                          }\n                        )\n                      ]\n                    }\n                  ),\n                  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                    \"div\",\n                    {\n                      style: {\n                        display: \"flex\",\n                        alignItems: \"center\",\n                        justifyContent: \"space-between\",\n                        color: \"white\",\n                        gap: `${8 * responsiveScale}px`\n                      },\n                      children: [\n                        /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                          \"div\",\n                          {\n                            style: {\n                              display: \"flex\",\n                              alignItems: \"center\",\n                              gap: `${8 * responsiveScale}px`\n                            },\n                            children: [\n                              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                \"button\",\n                                {\n                                  className: \"sc-ctrl-btn\",\n                                  onClick: handlePlayPause,\n                                  style: {\n                                    padding: `${8 * responsiveScale}px`,\n                                    borderRadius: \"50%\",\n                                    minWidth: `${36 * responsiveScale}px`,\n                                    minHeight: `${36 * responsiveScale}px`\n                                  },\n                                  title: isPlaying ? \"Pause\" : \"Play\",\n                                  children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, { size: Math.max(14, 18 * responsiveScale), style: { marginLeft: \"2px\" } })\n                                }\n                              ),\n                              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                                \"div\",\n                                {\n                                  style: {\n                                    display: \"flex\",\n                                    alignItems: \"center\",\n                                    paddingRight: `${6 * responsiveScale}px`\n                                  },\n                                  onMouseEnter: () => setShowVolumeSlider(true),\n                                  onMouseLeave: () => setShowVolumeSlider(false),\n                                  children: [\n                                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                      \"button\",\n                                      {\n                                        className: \"sc-ctrl-btn\",\n                                        onClick: () => {\n                                          if (playerRef.current) playerRef.current.toggleMute();\n                                          onVolumeToggle?.();\n                                          resetControlsTimer();\n                                        },\n                                        style: {\n                                          padding: `${8 * responsiveScale}px`,\n                                          borderRadius: \"50%\",\n                                          minWidth: `${36 * responsiveScale}px`,\n                                          minHeight: `${36 * responsiveScale}px`\n                                        },\n                                        title: isMuted2 ? \"Unmute\" : \"Mute\",\n                                        children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, { size: Math.max(14, 18 * responsiveScale) })\n                                      }\n                                    ),\n                                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                      \"div\",\n                                      {\n                                        style: {\n                                          width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n                                          overflow: \"hidden\",\n                                          transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n                                          display: \"flex\",\n                                          alignItems: \"center\",\n                                          paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n                                          paddingRight: showVolumeSlider ? `${8 * responsiveScale}px` : \"0\"\n                                        },\n                                        children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                                          \"div\",\n                                          {\n                                            style: {\n                                              position: \"relative\",\n                                              width: `${56 * responsiveScale}px`,\n                                              height: \"3px\",\n                                              cursor: \"pointer\",\n                                              borderRadius: \"1.5px\"\n                                            },\n                                            onMouseDown: (e) => {\n                                              e.preventDefault();\n                                              const el = e.currentTarget;\n                                              const move = (ev) => {\n                                                const r2 = el.getBoundingClientRect();\n                                                handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));\n                                              };\n                                              const up = () => {\n                                                document.removeEventListener(\"mousemove\", move);\n                                                document.removeEventListener(\"mouseup\", up);\n                                              };\n                                              document.addEventListener(\"mousemove\", move);\n                                              document.addEventListener(\"mouseup\", up);\n                                              const r = el.getBoundingClientRect();\n                                              handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                                            },\n                                            onClick: (e) => {\n                                              e.stopPropagation();\n                                              const r = e.currentTarget.getBoundingClientRect();\n                                              handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                                            },\n                                            children: [\n                                              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" } }),\n                                              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                                \"div\",\n                                                {\n                                                  style: {\n                                                    position: \"absolute\",\n                                                    top: 0,\n                                                    left: 0,\n                                                    bottom: 0,\n                                                    width: `${(isMuted2 ? 0 : volume) * 100}%`,\n                                                    background: \"#fff\",\n                                                    borderRadius: \"1.5px\",\n                                                    transition: \"width 0.1s ease-out\"\n                                                  }\n                                                }\n                                              ),\n                                              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                                \"div\",\n                                                {\n                                                  style: {\n                                                    position: \"absolute\",\n                                                    top: \"50%\",\n                                                    left: `${(isMuted2 ? 0 : volume) * 100}%`,\n                                                    transform: \"translate(-50%, -50%)\",\n                                                    width: \"12px\",\n                                                    height: \"12px\",\n                                                    background: \"#fff\",\n                                                    borderRadius: \"50%\",\n                                                    boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n                                                    transition: \"left 0.1s ease-out\"\n                                                  }\n                                                }\n                                              )\n                                            ]\n                                          }\n                                        )\n                                      }\n                                    )\n                                  ]\n                                }\n                              ),\n                              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                                \"div\",\n                                {\n                                  style: {\n                                    fontSize: `${13 * responsiveScale}px`,\n                                    fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n                                    color: \"rgba(255, 255, 255, 0.9)\",\n                                    display: viewportWidth < 480 ? \"none\" : \"block\",\n                                    fontVariantNumeric: \"tabular-nums\",\n                                    userSelect: \"none\",\n                                    marginLeft: `${4 * responsiveScale}px`\n                                  },\n                                  children: [\n                                    formatTime(currentTime),\n                                    \" \",\n                                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"span\", { style: { color: \"rgba(255,255,255,0.5)\" }, children: \"/\" }),\n                                    \" \",\n                                    formatTime(duration)\n                                  ]\n                                }\n                              )\n                            ]\n                          }\n                        ),\n                        /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                          \"div\",\n                          {\n                            style: {\n                              display: \"flex\",\n                              alignItems: \"center\",\n                              gap: `${8 * responsiveScale}px`\n                            },\n                            children: [\n                              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\"div\", { style: { position: \"relative\", display: viewportWidth < 600 ? \"none\" : \"block\" }, children: [\n                                /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                                  \"button\",\n                                  {\n                                    className: \"sc-ctrl-btn\",\n                                    onClick: () => {\n                                      setShowSpeedMenu(!showSpeedMenu);\n                                      resetControlsTimer();\n                                    },\n                                    style: {\n                                      padding: `${6 * responsiveScale}px ${10 * responsiveScale}px`,\n                                      borderRadius: `${6 * responsiveScale}px`,\n                                      fontSize: `${13 * responsiveScale}px`,\n                                      fontFamily: \"'SF Mono', 'Cascadia Code', monospace\",\n                                      fontWeight: \"600\",\n                                      minHeight: `${32 * responsiveScale}px`\n                                    },\n                                    title: \"Playback Speed\",\n                                    children: [\n                                      playbackRate,\n                                      \"x\"\n                                    ]\n                                  }\n                                ),\n                                showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                  \"div\",\n                                  {\n                                    style: {\n                                      position: \"absolute\",\n                                      bottom: \"100%\",\n                                      right: 0,\n                                      marginBottom: \"8px\",\n                                      background: \"rgba(0, 0, 0, 0.8)\",\n                                      backdropFilter: \"blur(24px)\",\n                                      WebkitBackdropFilter: \"blur(24px)\",\n                                      borderRadius: \"10px\",\n                                      border: \"1px solid rgba(255, 255, 255, 0.1)\",\n                                      overflow: \"hidden\",\n                                      minWidth: \"80px\",\n                                      boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5)\",\n                                      animation: \"sc-fade-in 0.15s ease\"\n                                    },\n                                    children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map((speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                                      \"button\",\n                                      {\n                                        onClick: () => handlePlaybackRateChange(speed),\n                                        style: {\n                                          display: \"block\",\n                                          width: \"100%\",\n                                          padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n                                          background: playbackRate === speed ? \"rgba(255, 255, 255, 0.12)\" : \"transparent\",\n                                          border: \"none\",\n                                          color: playbackRate === speed ? \"#fff\" : \"rgba(255, 255, 255, 0.7)\",\n                                          cursor: \"pointer\",\n                                          fontSize: `${12 * responsiveScale}px`,\n                                          fontFamily: \"'SF Mono', monospace\",\n                                          fontWeight: playbackRate === speed ? \"700\" : \"500\",\n                                          textAlign: \"center\",\n                                          transition: \"background 0.15s ease, color 0.15s ease\"\n                                        },\n                                        onMouseEnter: (e) => {\n                                          if (playbackRate !== speed) {\n                                            e.target.style.background = \"rgba(255, 255, 255, 0.08)\";\n                                            e.target.style.color = \"#fff\";\n                                          }\n                                        },\n                                        onMouseLeave: (e) => {\n                                          if (playbackRate !== speed) {\n                                            e.target.style.background = \"transparent\";\n                                            e.target.style.color = \"rgba(255, 255, 255, 0.7)\";\n                                          }\n                                        },\n                                        children: [\n                                          speed,\n                                          \"x\"\n                                        ]\n                                      },\n                                      speed\n                                    ))\n                                  }\n                                )\n                              ] }),\n                              /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                \"button\",\n                                {\n                                  className: \"sc-ctrl-btn\",\n                                  onClick: () => {\n                                    if (onFullscreenToggle) {\n                                      onFullscreenToggle();\n                                    } else if (wrapperRef.current) {\n                                      if (!document.fullscreenElement) {\n                                        wrapperRef.current.requestFullscreen().catch(() => {\n                                        });\n                                      } else {\n                                        document.exitFullscreen().catch(() => {\n                                        });\n                                      }\n                                    }\n                                    resetControlsTimer();\n                                  },\n                                  style: {\n                                    padding: `${8 * responsiveScale}px`,\n                                    borderRadius: \"50%\",\n                                    minWidth: `${36 * responsiveScale}px`,\n                                    minHeight: `${36 * responsiveScale}px`\n                                  },\n                                  title: isFullscreen2 ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n                                  children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompressIcon, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpandIcon, { size: Math.max(14, 18 * responsiveScale) })\n                                }\n                              )\n                            ]\n                          }\n                        )\n                      ]\n                    }\n                  )\n                ]\n              }\n            ) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                \"div\",\n                {\n                  style: {\n                    position: \"absolute\",\n                    top: `${10 * responsiveScale}px`,\n                    left: `${10 * responsiveScale}px`,\n                    display: \"flex\",\n                    alignItems: \"center\",\n                    gap: \"6px\",\n                    zIndex: 10,\n                    opacity: controlsVisible ? 1 : 0,\n                    transition: \"opacity 0.35s ease\"\n                  },\n                  children: [\n                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                      \"div\",\n                      {\n                        style: {\n                          width: \"8px\",\n                          height: \"8px\",\n                          borderRadius: \"50%\",\n                          background: \"#ff3b30\",\n                          animation: \"sc-pulse 1.5s ease-in-out infinite\",\n                          flexShrink: 0\n                        }\n                      }\n                    ),\n                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                      \"span\",\n                      {\n                        style: {\n                          fontSize: `${12 * responsiveScale}px`,\n                          fontFamily: \"'SF Pro Display', 'Segoe UI', Arial, sans-serif\",\n                          fontWeight: 700,\n                          letterSpacing: \"0.08em\",\n                          color: \"#fff\",\n                          textShadow: \"0 1px 3px rgba(0,0,0,0.6)\",\n                          userSelect: \"none\"\n                        },\n                        children: \"LIVE\"\n                      }\n                    )\n                  ]\n                }\n              ),\n              /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                \"div\",\n                {\n                  className: \"sc-controls-bar\",\n                  style: {\n                    position: \"absolute\",\n                    bottom: `${10 * responsiveScale}px`,\n                    right: `${10 * responsiveScale}px`,\n                    display: \"flex\",\n                    flexDirection: isPortrait ? \"column\" : \"row\",\n                    alignItems: isPortrait ? \"flex-end\" : \"center\",\n                    gap: `${8 * responsiveScale}px`,\n                    zIndex: 10,\n                    opacity: controlsVisible ? 1 : 0,\n                    transform: controlsVisible ? \"translateY(0)\" : \"translateY(4px)\",\n                    pointerEvents: controlsVisible ? \"auto\" : \"none\"\n                  },\n                  children: [\n                    /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                      \"div\",\n                      {\n                        style: {\n                          display: \"flex\",\n                          alignItems: \"center\",\n                          background: \"rgba(0, 0, 0, 0.6)\",\n                          borderRadius: `${18 * responsiveScale}px`,\n                          padding: \"2px\",\n                          paddingRight: `${8 * responsiveScale}px`\n                        },\n                        onMouseEnter: () => setShowVolumeSlider(true),\n                        onMouseLeave: () => setShowVolumeSlider(false),\n                        children: [\n                          /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                            \"button\",\n                            {\n                              className: \"sc-ctrl-btn\",\n                              onClick: () => {\n                                if (playerRef.current) playerRef.current.toggleMute();\n                                onVolumeToggle?.();\n                                resetControlsTimer();\n                              },\n                              style: {\n                                padding: `${8 * responsiveScale}px`,\n                                borderRadius: \"50%\",\n                                minWidth: `${36 * responsiveScale}px`,\n                                minHeight: `${36 * responsiveScale}px`\n                              },\n                              title: isMuted2 ? \"Unmute\" : \"Mute\",\n                              children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, { size: Math.max(14, 18 * responsiveScale) })\n                            }\n                          ),\n                          /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                            \"div\",\n                            {\n                              style: {\n                                width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n                                overflow: \"hidden\",\n                                transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n                                display: \"flex\",\n                                alignItems: \"center\",\n                                paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n                                paddingRight: showVolumeSlider ? `${10 * responsiveScale}px` : \"0\"\n                              },\n                              children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n                                \"div\",\n                                {\n                                  style: {\n                                    position: \"relative\",\n                                    width: `${56 * responsiveScale}px`,\n                                    height: \"3px\",\n                                    cursor: \"pointer\",\n                                    borderRadius: \"1.5px\"\n                                  },\n                                  onMouseDown: (e) => {\n                                    e.preventDefault();\n                                    const el = e.currentTarget;\n                                    const move = (ev) => {\n                                      const r2 = el.getBoundingClientRect();\n                                      handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));\n                                    };\n                                    const up = () => {\n                                      document.removeEventListener(\"mousemove\", move);\n                                      document.removeEventListener(\"mouseup\", up);\n                                    };\n                                    document.addEventListener(\"mousemove\", move);\n                                    document.addEventListener(\"mouseup\", up);\n                                    const r = el.getBoundingClientRect();\n                                    handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                                  },\n                                  onClick: (e) => {\n                                    e.stopPropagation();\n                                    const r = e.currentTarget.getBoundingClientRect();\n                                    handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                                  },\n                                  children: [\n                                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"div\", { style: { position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" } }),\n                                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                      \"div\",\n                                      {\n                                        style: {\n                                          position: \"absolute\",\n                                          top: 0,\n                                          left: 0,\n                                          bottom: 0,\n                                          width: `${(isMuted2 ? 0 : volume) * 100}%`,\n                                          background: \"#fff\",\n                                          borderRadius: \"1.5px\",\n                                          transition: \"width 0.1s ease-out\"\n                                        }\n                                      }\n                                    ),\n                                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                                      \"div\",\n                                      {\n                                        style: {\n                                          position: \"absolute\",\n                                          top: \"50%\",\n                                          left: `${(isMuted2 ? 0 : volume) * 100}%`,\n                                          transform: \"translate(-50%, -50%)\",\n                                          width: \"12px\",\n                                          height: \"12px\",\n                                          background: \"#fff\",\n                                          borderRadius: \"50%\",\n                                          boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n                                          transition: \"left 0.1s ease-out\"\n                                        }\n                                      }\n                                    )\n                                  ]\n                                }\n                              )\n                            }\n                          )\n                        ]\n                      }\n                    ),\n                    /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n                      \"button\",\n                      {\n                        className: \"sc-ctrl-btn\",\n                        onClick: () => {\n                          if (onFullscreenToggle) {\n                            onFullscreenToggle();\n                          } else if (wrapperRef.current) {\n                            if (!document.fullscreenElement) {\n                              wrapperRef.current.requestFullscreen().catch(() => {\n                              });\n                            } else {\n                              document.exitFullscreen().catch(() => {\n                              });\n                            }\n                          }\n                          resetControlsTimer();\n                        },\n                        style: {\n                          padding: `${8 * responsiveScale}px`,\n                          borderRadius: \"50%\",\n                          minWidth: `${36 * responsiveScale}px`,\n                          minHeight: `${36 * responsiveScale}px`,\n                          background: \"rgba(0, 0, 0, 0.6)\"\n                        },\n                        title: isFullscreen2 ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n                        children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompressIcon, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpandIcon, { size: Math.max(14, 18 * responsiveScale) })\n                      }\n                    )\n                  ]\n                }\n              )\n            ] }),\n            onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n              \"div\",\n              {\n                onClick: onControlClick,\n                style: {\n                  position: \"absolute\",\n                  top: 0,\n                  left: 0,\n                  right: 0,\n                  bottom: 0,\n                  zIndex: 1,\n                  cursor: \"pointer\"\n                }\n              }\n            )\n          ]\n        }\n      )\n    ] });\n  },\n  (prevProps, nextProps) => {\n    for (const prop of CRITICAL_PROPS) {\n      if (prevProps[prop] !== nextProps[prop]) {\n        return false;\n      }\n    }\n    const uiProps = [\n      \"autoplay\",\n      \"muted\",\n      \"controls\",\n      \"showCustomControls\",\n      \"className\",\n      \"style\",\n      \"wrapperClassName\",\n      \"wrapperStyle\",\n      \"playsInline\",\n      \"preload\",\n      \"poster\",\n      \"children\"\n    ];\n    for (const prop of uiProps) {\n      if (prevProps[prop] !== nextProps[prop]) {\n        return false;\n      }\n    }\n    const callbackProps = [\n      \"onReady\",\n      \"onVolumeToggle\",\n      \"onFullscreenToggle\",\n      \"onControlClick\"\n    ];\n    for (const prop of callbackProps) {\n      if (prevProps[prop] !== nextProps[prop]) {\n        return false;\n      }\n    }\n    return true;\n  }\n);\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n  StormcloudVideoPlayerComponent\n});\n","import React, { useEffect, useRef, useMemo, useCallback } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport {\n  FaPlay,\n  FaPause,\n  FaVolumeUp,\n  FaVolumeMute,\n  FaVolumeDown,\n} from \"react-icons/fa\";\n\nconst ExpandIcon: React.FC<{ size?: number }> = ({ size = 18 }) => (\n  <svg\n    width={size}\n    height={size}\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    stroke=\"currentColor\"\n    strokeWidth={2}\n    strokeLinecap=\"round\"\n    strokeLinejoin=\"round\"\n    aria-hidden=\"true\"\n    focusable=\"false\"\n  >\n    <path d=\"M9 4H4v5\" />\n    <path d=\"M20 9V4h-5\" />\n    <path d=\"M15 20h5v-5\" />\n    <path d=\"M4 15v5h5\" />\n  </svg>\n);\n\nconst CompressIcon: React.FC<{ size?: number }> = ({ size = 18 }) => (\n  <svg\n    width={size}\n    height={size}\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    stroke=\"currentColor\"\n    strokeWidth={2}\n    strokeLinecap=\"round\"\n    strokeLinejoin=\"round\"\n    aria-hidden=\"true\"\n    focusable=\"false\"\n  >\n    <path d=\"M4 9h5V4\" />\n    <path d=\"M15 4v5h5\" />\n    <path d=\"M20 15h-5v5\" />\n    <path d=\"M9 20v-5H4\" />\n  </svg>\n);\n\nexport type StormcloudVideoPlayerProps = Omit<\n  StormcloudVideoPlayerConfig,\n  \"videoElement\"\n> &\n  React.VideoHTMLAttributes<HTMLVideoElement> & {\n    onReady?: (player: StormcloudVideoPlayer) => void;\n    wrapperClassName?: string;\n    wrapperStyle?: React.CSSProperties;\n    licenseKey?: string;\n  };\n\nconst CRITICAL_PROPS = [\n  \"src\",\n  \"allowNativeHls\",\n  \"isLiveStream\",\n  \"licenseKey\",\n  \"isVmap\",\n  \"vmapUrl\",\n  \"lowLatencyMode\",\n  \"driftToleranceMs\",\n  \"vastMode\",\n  \"ctvAdRequest\",\n] as const;\n\nconst CONTROLS_HIDE_DELAY = 3000;\nconst DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;\n\nexport const StormcloudVideoPlayerComponent: React.FC<StormcloudVideoPlayerProps> =\n  React.memo(\n    (props) => {\n      const {\n        src,\n        autoplay,\n        muted,\n        lowLatencyMode,\n        allowNativeHls,\n        isLiveStream,\n        driftToleranceMs,\n        immediateManifestAds,\n        debugAdTiming,\n        showCustomControls,\n        hideLoadingIndicator,\n        onVolumeToggle,\n        onFullscreenToggle,\n        onControlClick,\n        onReady,\n        wrapperClassName,\n        wrapperStyle,\n        className,\n        style,\n        controls,\n        playsInline,\n        preload,\n        poster,\n        children,\n        licenseKey,\n        vastMode,\n        vastTagUrl,\n        isVmap,\n        vmapUrl,\n        minSegmentsBeforePlay,\n        ctvAdRequest,\n        ...restVideoAttrs\n      } = props;\n\n      const videoRef = useRef<HTMLVideoElement | null>(null);\n      const playerRef = useRef<StormcloudVideoPlayer | null>(null);\n      const bufferingTimeoutRef = useRef<number | null>(null);\n      const controlsTimerRef = useRef<number | null>(null);\n      const wrapperRef = useRef<HTMLDivElement | null>(null);\n      const [adStatus, setAdStatus] = React.useState<{\n        showAds: boolean;\n        currentIndex: number;\n        totalAds: number;\n        remainingSeconds: number;\n      }>({ showAds: false, currentIndex: 0, totalAds: 0, remainingSeconds: 0 });\n\n      const [shouldShowNativeControls, setShouldShowNativeControls] =\n        React.useState(true);\n\n      const [isMuted, setIsMuted] = React.useState(false);\n      const [isFullscreen, setIsFullscreen] = React.useState(false);\n      const [isPlaying, setIsPlaying] = React.useState(false);\n      const [currentTime, setCurrentTime] = React.useState(0);\n      const [duration, setDuration] = React.useState(0);\n      const [volume, setVolume] = React.useState(1);\n      const [playbackRate, setPlaybackRate] = React.useState(1);\n      const [showVolumeSlider, setShowVolumeSlider] = React.useState(false);\n      const [showSpeedMenu, setShowSpeedMenu] = React.useState(false);\n      const [isLoading, setIsLoading] = React.useState(true);\n      const [isBuffering, setIsBuffering] = React.useState(false);\n      const [showCenterPlay, setShowCenterPlay] = React.useState(false);\n      const [showLicenseWarning, setShowLicenseWarning] = React.useState(false);\n      const [controlsVisible, setControlsVisible] = React.useState(true);\n      const [viewportWidth, setViewportWidth] = React.useState(\n        typeof window !== \"undefined\" ? window.innerWidth : 1920\n      );\n      const [isPortrait, setIsPortrait] = React.useState(\n        typeof window !== \"undefined\"\n          ? window.innerHeight > window.innerWidth\n          : false\n      );\n      const [playerAspectRatio, setPlayerAspectRatio] = React.useState(\n        DEFAULT_PLAYER_ASPECT_RATIO\n      );\n\n      const getResponsiveScale = () => {\n        if (viewportWidth < 480) return 0.7;\n        if (viewportWidth < 768) return 0.8;\n        if (viewportWidth < 1024) return 0.9;\n        return 1;\n      };\n\n      const responsiveScale = getResponsiveScale();\n\n      const resetControlsTimer = useCallback(() => {\n        if (controlsTimerRef.current) {\n          clearTimeout(controlsTimerRef.current);\n        }\n        setControlsVisible(true);\n        controlsTimerRef.current = window.setTimeout(() => {\n          if (!showVolumeSlider && !showSpeedMenu) {\n            setControlsVisible(false);\n          }\n        }, CONTROLS_HIDE_DELAY);\n      }, [showVolumeSlider, showSpeedMenu]);\n\n      const handleWrapperMouseMove = useCallback(() => {\n        resetControlsTimer();\n      }, [resetControlsTimer]);\n\n      const handleWrapperMouseLeave = useCallback(() => {\n        if (!showVolumeSlider && !showSpeedMenu) {\n          setControlsVisible(false);\n        }\n      }, [showVolumeSlider, showSpeedMenu]);\n\n      const formatTime = (seconds: number): string => {\n        if (!isFinite(seconds)) return \"0:00:00\";\n        const hours = Math.floor(seconds / 3600);\n        const minutes = Math.floor((seconds % 3600) / 60);\n        const remainingSeconds = Math.floor(seconds % 60);\n        return `${hours}:${minutes\n          .toString()\n          .padStart(2, \"0\")}:${remainingSeconds.toString().padStart(2, \"0\")}`;\n      };\n\n      const handlePlayPause = () => {\n        if (videoRef.current) {\n          if (videoRef.current.paused) {\n            const hasValidSource =\n              videoRef.current.src ||\n              (videoRef.current.currentSrc &&\n                videoRef.current.currentSrc !== \"\") ||\n              videoRef.current.readyState >= 1;\n\n            if (hasValidSource) {\n              videoRef.current.play()?.catch((error) => {\n                console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n              });\n              setShowCenterPlay(false);\n            } else {\n              console.warn(\n                \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n              );\n            }\n          } else {\n            videoRef.current.pause();\n            setShowCenterPlay(true);\n          }\n        }\n        resetControlsTimer();\n      };\n\n      const handleCenterPlayClick = () => {\n        if (videoRef.current && videoRef.current.paused) {\n          const hasValidSource =\n            videoRef.current.src ||\n            (videoRef.current.currentSrc &&\n              videoRef.current.currentSrc !== \"\") ||\n            videoRef.current.readyState >= 1;\n\n          if (hasValidSource) {\n            videoRef.current.play()?.catch((error) => {\n              console.error(\"[StormcloudVideoPlayer] Failed to play:\", error);\n            });\n            setShowCenterPlay(false);\n          } else {\n            console.warn(\n              \"[StormcloudVideoPlayer] Cannot play: video has no valid source\"\n            );\n          }\n        }\n      };\n\n      const handleTimelineSeek = (e: React.MouseEvent<HTMLDivElement>) => {\n        if (videoRef.current && duration > 0 && isFinite(duration)) {\n          const rect = e.currentTarget.getBoundingClientRect();\n          const clickX = e.clientX - rect.left;\n          const progress = Math.max(0, Math.min(1, clickX / rect.width));\n          const newTime = progress * duration;\n\n          if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {\n            videoRef.current.currentTime = newTime;\n          }\n        }\n        resetControlsTimer();\n      };\n\n      const handleVolumeChange = (newVolume: number) => {\n        if (playerRef.current && isFinite(newVolume)) {\n          const clampedVolume = Math.max(0, Math.min(1, newVolume));\n          playerRef.current.setVolume(clampedVolume);\n        }\n      };\n\n      const handlePlaybackRateChange = (rate: number) => {\n        if (videoRef.current && isFinite(rate) && rate > 0) {\n          videoRef.current.playbackRate = rate;\n        }\n        setShowSpeedMenu(false);\n      };\n\n      const isHlsStream =\n        src?.toLowerCase().includes(\".m3u8\") ||\n        src?.toLowerCase().includes(\"/hls/\");\n      const isLiveUiMode = isLiveStream === true;\n      const shouldShowEnhancedControls =\n        showCustomControls &&\n        (isHlsStream ? !isLiveUiMode : true);\n\n      const criticalPropsKey = useMemo(() => {\n        return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n      }, [\n        src,\n        allowNativeHls,\n        isLiveStream,\n        licenseKey,\n        isVmap,\n        vmapUrl,\n        lowLatencyMode,\n        driftToleranceMs,\n        vastMode,\n      ]);\n\n      useEffect(() => {\n        if (typeof window === \"undefined\") return;\n        const el = videoRef.current;\n        if (!el || !src) return;\n\n        if (!licenseKey) {\n          setShowLicenseWarning(true);\n          setIsLoading(false);\n          console.warn(\n            \"StormcloudVideoPlayer: License key is required but not provided. Please set the licenseKey prop to use the player.\"\n          );\n          return;\n        }\n\n        setShowLicenseWarning(false);\n\n        if (debugAdTiming) {\n          console.log(\"[StormcloudUI] Initializing player, isLoading=true\");\n        }\n\n        if (playerRef.current) {\n          try {\n            playerRef.current.destroy();\n          } catch {}\n          playerRef.current = null;\n        }\n\n        const cfg: StormcloudVideoPlayerConfig = {\n          src,\n          videoElement: el,\n        } as StormcloudVideoPlayerConfig;\n        if (autoplay !== undefined) cfg.autoplay = autoplay;\n        if (muted !== undefined) cfg.muted = muted;\n        if (lowLatencyMode !== undefined) cfg.lowLatencyMode = lowLatencyMode;\n        if (allowNativeHls !== undefined) cfg.allowNativeHls = allowNativeHls;\n        if (isLiveStream !== undefined) cfg.isLiveStream = isLiveStream;\n        if (driftToleranceMs !== undefined)\n          cfg.driftToleranceMs = driftToleranceMs;\n        if (immediateManifestAds !== undefined)\n          cfg.immediateManifestAds = immediateManifestAds;\n        if (debugAdTiming !== undefined) cfg.debugAdTiming = debugAdTiming;\n        if (showCustomControls !== undefined)\n          cfg.showCustomControls = showCustomControls;\n        if (onVolumeToggle !== undefined) cfg.onVolumeToggle = onVolumeToggle;\n        if (onFullscreenToggle !== undefined)\n          cfg.onFullscreenToggle = onFullscreenToggle;\n        if (onControlClick !== undefined) cfg.onControlClick = onControlClick;\n        if (licenseKey !== undefined) cfg.licenseKey = licenseKey;\n        if (vastMode !== undefined) cfg.vastMode = vastMode;\n        if (vastTagUrl !== undefined) cfg.vastTagUrl = vastTagUrl;\n        if (isVmap !== undefined) cfg.isVmap = isVmap;\n        if (vmapUrl !== undefined) cfg.vmapUrl = vmapUrl;\n        if (minSegmentsBeforePlay !== undefined)\n          cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\n        if (ctvAdRequest !== undefined) cfg.ctvAdRequest = ctvAdRequest;\n\n        const player = new StormcloudVideoPlayer(cfg);\n        playerRef.current = player;\n        player\n          .load()\n          .then(() => {\n            const showNative = player.shouldShowNativeControls();\n            setShouldShowNativeControls(showNative);\n            if (debugAdTiming) {\n              console.log(\n                \"[StormcloudUI] Player loaded successfully, waiting for video ready\"\n              );\n            }\n            onReady?.(player);\n          })\n          .catch((error) => {\n            console.error(\n              \"StormcloudVideoPlayer: Failed to load player:\",\n              error\n            );\n            setIsLoading(false);\n            onReady?.(player);\n          });\n\n        return () => {\n          try {\n            player.destroy();\n          } catch {}\n          playerRef.current = null;\n        };\n      }, [criticalPropsKey]);\n\n      useEffect(() => {\n        if (!playerRef.current) return;\n\n        try {\n          if (autoplay !== undefined && playerRef.current.videoElement) {\n            playerRef.current.videoElement.autoplay = autoplay;\n          }\n          if (muted !== undefined && !playerRef.current.isShowingAds()) {\n            playerRef.current.setMuted(muted);\n          }\n        } catch (error) {\n          console.warn(\"Failed to update player properties:\", error);\n        }\n      }, [autoplay, muted]);\n\n      useEffect(() => {\n        if (!playerRef.current) return;\n\n        const checkAdStatus = () => {\n          if (playerRef.current) {\n            const showAdsFromMethod = playerRef.current.isShowingAds();\n            const showAdsFromAttribute = videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n            const showAds = showAdsFromMethod || showAdsFromAttribute;\n            const currentIndex = playerRef.current.getCurrentAdIndex();\n            const totalAds = playerRef.current.getTotalAdsInBreak();\n            const remainingMs = playerRef.current.getAdRemainingMs();\n            const remainingSeconds = showAds\n              ? Math.max(0, Math.ceil(remainingMs / 1000))\n              : 0;\n\n            setAdStatus((prev) => {\n              if (\n                prev.showAds !== showAds ||\n                prev.currentIndex !== currentIndex ||\n                prev.totalAds !== totalAds ||\n                prev.remainingSeconds !== remainingSeconds\n              ) {\n                if (showAds && !prev.showAds) {\n                  setShowCenterPlay(false);\n                }\n                return { showAds, currentIndex, totalAds, remainingSeconds };\n              }\n              return prev;\n            });\n          }\n        };\n\n        const interval = setInterval(checkAdStatus, 50);\n        return () => clearInterval(interval);\n      }, []);\n\n      useEffect(() => {\n        if (typeof window === \"undefined\" || !playerRef.current) return;\n\n        const handleResize = () => {\n          if (playerRef.current && videoRef.current) {\n            if (typeof playerRef.current.resize === \"function\") {\n              playerRef.current.resize();\n            }\n          }\n          setViewportWidth(window.innerWidth);\n          setIsPortrait(window.innerHeight > window.innerWidth);\n        };\n\n        window.addEventListener(\"resize\", handleResize);\n        return () => window.removeEventListener(\"resize\", handleResize);\n      }, []);\n\n      useEffect(() => {\n        if (!playerRef.current || !videoRef.current) return;\n\n        const updateStates = () => {\n          if (playerRef.current && videoRef.current) {\n            setIsMuted(playerRef.current.isMuted());\n            setIsPlaying(!videoRef.current.paused);\n\n            const currentTimeValue = videoRef.current.currentTime;\n            setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);\n\n            const durationValue = videoRef.current.duration;\n            setDuration(isFinite(durationValue) ? durationValue : 0);\n\n            const volumeValue = playerRef.current.getVolume();\n            setVolume(\n              isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1\n            );\n\n            const rateValue = videoRef.current.playbackRate;\n            setPlaybackRate(\n              isFinite(rateValue) && rateValue > 0 ? rateValue : 1\n            );\n          }\n          setIsFullscreen(\n            document.fullscreenElement === wrapperRef.current\n          );\n        };\n\n        const interval = setInterval(updateStates, 200);\n\n        const handleFullscreenChange = () => {\n          setIsFullscreen(\n            document.fullscreenElement === wrapperRef.current\n          );\n        };\n\n        document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n\n        return () => {\n          clearInterval(interval);\n          document.removeEventListener(\n            \"fullscreenchange\",\n            handleFullscreenChange\n          );\n        };\n      }, []);\n\n      useEffect(() => {\n        if (!videoRef.current) return;\n\n        const handleLoadedMetadata = () => {\n          const video = videoRef.current;\n          if (video) {\n            if (video.videoWidth > 0 && video.videoHeight > 0) {\n              setPlayerAspectRatio(video.videoWidth / video.videoHeight);\n            }\n            void video.offsetHeight;\n          }\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: loadedmetadata, readyState:\",\n              videoRef.current?.readyState\n            );\n          }\n        };\n\n        const handleLoadedData = () => {\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: loadeddata, readyState:\",\n              videoRef.current?.readyState\n            );\n          }\n        };\n\n        const handleLoadStart = () => {\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: loadstart, readyState:\",\n              videoRef.current?.readyState\n            );\n          }\n        };\n\n        const handleCanPlay = () => {\n          setIsLoading(false);\n          if (bufferingTimeoutRef.current) {\n            clearTimeout(bufferingTimeoutRef.current);\n            bufferingTimeoutRef.current = null;\n          }\n          setIsBuffering(false);\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: canplay, readyState:\",\n              videoRef.current?.readyState,\n              \"- clearing loading state, isLoading=false\"\n            );\n          }\n        };\n\n        const handleCanPlayThrough = () => {\n          setIsLoading(false);\n          if (bufferingTimeoutRef.current) {\n            clearTimeout(bufferingTimeoutRef.current);\n            bufferingTimeoutRef.current = null;\n          }\n          setIsBuffering(false);\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: canplaythrough, readyState:\",\n              videoRef.current?.readyState,\n              \"- clearing loading state, isLoading=false\"\n            );\n          }\n        };\n\n        const handleWaiting = () => {\n          if (bufferingTimeoutRef.current) {\n            clearTimeout(bufferingTimeoutRef.current);\n          }\n\n          bufferingTimeoutRef.current = window.setTimeout(() => {\n            setIsBuffering(true);\n            if (debugAdTiming) {\n              console.log(\n                \"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:\",\n                videoRef.current?.readyState,\n                \"- showing spinner, isBuffering=true\"\n              );\n            }\n          }, 300);\n\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: waiting, readyState:\",\n              videoRef.current?.readyState,\n              \"- buffering delay started (300ms)\"\n            );\n          }\n        };\n\n        const handlePlaying = () => {\n          setIsLoading(false);\n          if (bufferingTimeoutRef.current) {\n            clearTimeout(bufferingTimeoutRef.current);\n            bufferingTimeoutRef.current = null;\n          }\n          setIsBuffering(false);\n          setShowCenterPlay(false);\n          if (debugAdTiming) {\n            console.log(\n              \"[StormcloudUI] Video event: playing, readyState:\",\n              videoRef.current?.readyState,\n              \"- playback started, isLoading=false, isBuffering=false\"\n            );\n          }\n        };\n\n      const handlePause = () => {\n        const isAdActive = playerRef.current?.isShowingAds() || \n          videoRef.current?.dataset?.stormcloudAdPlaying === \"true\";\n        \n        if (playerRef.current && !isAdActive) {\n          setShowCenterPlay(true);\n        } else {\n          setShowCenterPlay(false);\n        }\n      };\n\n        const handleEnded = () => {\n          setShowCenterPlay(true);\n        };\n\n        const video = videoRef.current;\n        video.addEventListener(\"loadstart\", handleLoadStart);\n        video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n        video.addEventListener(\"loadeddata\", handleLoadedData);\n        video.addEventListener(\"canplay\", handleCanPlay);\n        video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n        video.addEventListener(\"waiting\", handleWaiting);\n        video.addEventListener(\"playing\", handlePlaying);\n        video.addEventListener(\"pause\", handlePause);\n        video.addEventListener(\"ended\", handleEnded);\n\n        if (video.paused) {\n          setShowCenterPlay(true);\n        }\n\n        return () => {\n          if (bufferingTimeoutRef.current) {\n            clearTimeout(bufferingTimeoutRef.current);\n            bufferingTimeoutRef.current = null;\n          }\n\n          video.removeEventListener(\"loadstart\", handleLoadStart);\n          video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n          video.removeEventListener(\"loadeddata\", handleLoadedData);\n          video.removeEventListener(\"canplay\", handleCanPlay);\n          video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n          video.removeEventListener(\"waiting\", handleWaiting);\n          video.removeEventListener(\"playing\", handlePlaying);\n          video.removeEventListener(\"pause\", handlePause);\n          video.removeEventListener(\"ended\", handleEnded);\n        };\n      }, [debugAdTiming]);\n\n      useEffect(() => {\n        setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);\n      }, [src]);\n\n      useEffect(() => {\n        return () => {\n          if (controlsTimerRef.current) {\n            clearTimeout(controlsTimerRef.current);\n          }\n        };\n      }, []);\n\n      const progressPercent = duration > 0 ? (currentTime / duration) * 100 : 0;\n\n      const VolumeIcon = isMuted || volume === 0\n        ? FaVolumeMute\n        : volume < 0.5\n          ? FaVolumeDown\n          : FaVolumeUp;\n\n      return (\n        <>\n          <style>\n            {`\n              @keyframes sc-spin {\n                from { transform: rotate(0deg); }\n                to { transform: rotate(360deg); }\n              }\n              @keyframes sc-loading-glow {\n                0%, 100% { opacity: 0.85; transform: scale(1); }\n                50% { opacity: 1; transform: scale(1.05); }\n              }\n              @keyframes sc-pulse {\n                0%, 100% { opacity: 1; }\n                50% { opacity: 0.6; }\n              }\n              @keyframes sc-fade-in {\n                from { opacity: 0; transform: translateY(8px); }\n                to { opacity: 1; transform: translateY(0); }\n              }\n              .sc-wrapper:fullscreen,\n              .sc-wrapper:has(*:fullscreen) {\n                border-radius: 0 !important;\n                box-shadow: none !important;\n                width: 100vw !important;\n                height: 100vh !important;\n                max-width: 100vw !important;\n                max-height: 100vh !important;\n                position: fixed !important;\n                top: 0 !important;\n                left: 0 !important;\n                z-index: 999999 !important;\n                background: #000 !important;\n                display: flex !important;\n                align-items: center !important;\n                justify-content: center !important;\n              }\n              .sc-ctrl-btn {\n                background: none;\n                border: none;\n                color: #fff;\n                cursor: pointer;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                border-radius: 50%;\n                padding: 8px;\n                transition: background 0.15s ease, opacity 0.15s ease;\n                opacity: 0.9;\n              }\n              .sc-ctrl-btn:hover {\n                opacity: 1;\n                background: rgba(255, 255, 255, 0.1);\n              }\n              .sc-ctrl-btn:active {\n                opacity: 0.7;\n              }\n              .sc-controls-bar {\n                transition: opacity 0.35s ease, transform 0.35s ease;\n              }\n              .sc-progress-track:hover .sc-progress-thumb {\n                transform: translate(-50%, -50%) scale(1) !important;\n              }\n              .sc-loading-hidden .sc-loading-indicator {\n                display: none !important;\n              }\n            `}\n          </style>\n          <div\n            ref={wrapperRef}\n            className={`sc-wrapper ${wrapperClassName || \"\"}`}\n            onMouseMove={handleWrapperMouseMove}\n            onMouseLeave={handleWrapperMouseLeave}\n            style={{\n              display: \"flex\",\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              position: isFullscreen ? \"fixed\" : \"relative\",\n              top: isFullscreen ? 0 : undefined,\n              left: isFullscreen ? 0 : undefined,\n              overflow: \"hidden\",\n              width: isFullscreen ? \"100vw\" : \"100%\",\n              height: isFullscreen ? \"100vh\" : \"auto\",\n              minHeight: isFullscreen ? \"100vh\" : \"auto\",\n              aspectRatio: isFullscreen ? undefined : playerAspectRatio,\n              maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n              maxHeight: isFullscreen ? \"100vh\" : \"none\",\n              zIndex: isFullscreen ? 999999 : undefined,\n              backgroundColor: \"#000\",\n              borderRadius: isFullscreen ? 0 : undefined,\n              boxShadow: isFullscreen ? \"none\" : undefined,\n              ...wrapperStyle,\n            }}\n          >\n            <video\n              ref={videoRef}\n              className={className}\n              style={{\n                display: \"block\",\n                width: \"100%\",\n                height: \"100%\",\n                maxWidth: \"100%\",\n                maxHeight: isFullscreen ? \"100%\" : \"none\",\n                objectFit: isFullscreen ? \"cover\" : \"contain\",\n                backgroundColor: \"#000\",\n                aspectRatio: isFullscreen ? \"unset\" : undefined,\n                ...style,\n              }}\n              controls={\n                shouldShowNativeControls && controls && !showCustomControls\n              }\n              playsInline={playsInline}\n              preload={preload}\n              poster={poster}\n              {...restVideoAttrs}\n            >\n              {children}\n            </video>\n\n            {(isLoading || isBuffering) && !hideLoadingIndicator && (\n              <div\n                className=\"sc-loading-indicator\"\n                style={{\n                  position: \"absolute\",\n                  top: \"50%\",\n                  left: \"50%\",\n                  transform: \"translate(-50%, -50%)\",\n                  zIndex: 20,\n                  width: `${Math.max(34, 38 * responsiveScale)}px`,\n                  height: `${Math.max(34, 38 * responsiveScale)}px`,\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  justifyContent: \"center\",\n                  animation: \"sc-loading-glow 1.4s ease-in-out infinite\",\n                  filter: \"drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))\",\n                }}\n              >\n                <div\n                  style={{\n                    position: \"absolute\",\n                    inset: 0,\n                    borderRadius: \"50%\",\n                    border: \"3px solid rgba(255, 255, 255, 0.25)\",\n                    borderTopColor: \"#ff0000\",\n                    borderRightColor: \"rgba(255, 255, 255, 0.85)\",\n                    animation: \"sc-spin 0.8s linear infinite\",\n                  }}\n                />\n                <div\n                  style={{\n                    width: \"7px\",\n                    height: \"7px\",\n                    borderRadius: \"50%\",\n                    background: \"#ff0000\",\n                    boxShadow: \"0 0 10px rgba(255, 0, 0, 0.65)\",\n                  }}\n                />\n              </div>\n            )}\n\n            {showLicenseWarning && (\n              <div\n                style={{\n                  position: \"absolute\",\n                  top: \"50%\",\n                  left: \"50%\",\n                  transform: \"translate(-50%, -50%)\",\n                  zIndex: 25,\n                  background: \"rgba(220, 38, 38, 0.92)\",\n                  backdropFilter: \"blur(24px)\",\n                  color: \"white\",\n                  padding: \"28px 36px\",\n                  borderRadius: \"14px\",\n                  border: \"1px solid rgba(255, 255, 255, 0.15)\",\n                  boxShadow: \"0 24px 64px rgba(0, 0, 0, 0.5)\",\n                  textAlign: \"center\",\n                  maxWidth: \"400px\",\n                  margin: \"0 16px\",\n                }}\n              >\n                <div style={{ fontSize: \"18px\", fontWeight: \"700\", marginBottom: \"10px\", letterSpacing: \"-0.02em\" }}>\n                  License Key Required\n                </div>\n                <div style={{ fontSize: \"13px\", lineHeight: \"1.6\", color: \"rgba(255, 255, 255, 0.85)\" }}>\n                  Please provide a valid license key to use the Stormcloud Video\n                  Player.\n                  <br />\n                  Contact your administrator for licensing information.\n                </div>\n              </div>\n            )}\n\n            {adStatus.showAds && (\n              <div\n                style={{\n                  position: \"absolute\",\n                  top: `${12 * responsiveScale}px`,\n                  left: `${12 * responsiveScale}px`,\n                  zIndex: 50,\n                  display: \"flex\",\n                  alignItems: \"center\",\n                  gap: \"8px\",\n                  pointerEvents: \"none\",\n                  animation: \"sc-fade-in 0.3s ease\",\n                }}\n              >\n                <div\n                  style={{\n                    background: \"rgba(234, 179, 8, 0.95)\",\n                    color: \"#111\",\n                    padding: `${4 * responsiveScale}px ${12 * responsiveScale}px`,\n                    borderRadius: \"6px\",\n                    fontSize: `${11 * responsiveScale}px`,\n                    fontWeight: 700,\n                    letterSpacing: \"0.08em\",\n                    textTransform: \"uppercase\" as const,\n                    boxShadow: \"0 2px 12px rgba(234, 179, 8, 0.35)\",\n                  }}\n                >\n                  {`Ad ${Math.max(1, adStatus.currentIndex)}`}\n                </div>\n              </div>\n            )}\n\n            {showCenterPlay &&\n              !isLoading &&\n              !isBuffering &&\n              !showLicenseWarning &&\n              !adStatus.showAds && (\n                <div\n                  onClick={handleCenterPlayClick}\n                  style={{\n                    position: \"absolute\",\n                    top: \"50%\",\n                    left: \"50%\",\n                    transform: \"translate(-50%, -50%)\",\n                    zIndex: 15,\n                    cursor: \"pointer\",\n                    background: \"rgba(0, 0, 0, 0.55)\",\n                    backdropFilter: \"blur(8px)\",\n                    borderRadius: \"50%\",\n                    width: `${92 * responsiveScale}px`,\n                    height: `${92 * responsiveScale}px`,\n                    display: \"flex\",\n                    alignItems: \"center\",\n                    justifyContent: \"center\",\n                    transition: \"background 0.2s ease, transform 0.2s ease\",\n                    animation: \"sc-fade-in 0.2s ease\",\n                  }}\n                  onMouseEnter={(e) => {\n                    (e.currentTarget as HTMLElement).style.background = \"rgba(0, 0, 0, 0.72)\";\n                    (e.currentTarget as HTMLElement).style.transform = \"translate(-50%, -50%) scale(1.06)\";\n                  }}\n                  onMouseLeave={(e) => {\n                    (e.currentTarget as HTMLElement).style.background = \"rgba(0, 0, 0, 0.55)\";\n                    (e.currentTarget as HTMLElement).style.transform = \"translate(-50%, -50%) scale(1)\";\n                  }}\n                  title=\"Play\"\n                >\n                  <FaPlay\n                    size={Math.max(24, 32 * responsiveScale)}\n                    color=\"white\"\n                    style={{ marginLeft: \"4px\" }}\n                  />\n                </div>\n              )}\n\n            {shouldShowEnhancedControls && !showLicenseWarning ? (\n              <div\n                className=\"sc-controls-bar\"\n                style={{\n                  position: \"absolute\",\n                  bottom: 0,\n                  left: 0,\n                  right: 0,\n                  background: \"linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)\",\n                  padding: `${20 * responsiveScale}px ${12 * responsiveScale}px ${8 * responsiveScale}px`,\n                  zIndex: 10,\n                  opacity: controlsVisible || adStatus.showAds ? 1 : 0,\n                  transform: controlsVisible || adStatus.showAds ? \"translateY(0)\" : \"translateY(6px)\",\n                  pointerEvents: controlsVisible || adStatus.showAds ? \"auto\" : \"none\",\n                }}\n              >\n                {/* Progress Bar */}\n                <div\n                  className=\"sc-progress-track\"\n                  style={{\n                    width: \"100%\",\n                    height: \"3px\",\n                    background: \"rgba(255, 255, 255, 0.2)\",\n                    borderRadius: \"1.5px\",\n                    marginBottom: `${8 * responsiveScale}px`,\n                    cursor: \"pointer\",\n                    position: \"relative\",\n                    transition: \"height 0.1s ease\",\n                  }}\n                  onClick={handleTimelineSeek}\n                  onMouseEnter={(e) => { e.currentTarget.style.height = \"5px\"; }}\n                  onMouseLeave={(e) => { e.currentTarget.style.height = \"3px\"; }}\n                >\n                  <div\n                    style={{\n                      position: \"absolute\",\n                      top: 0, left: 0, bottom: 0,\n                      background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n                      borderRadius: \"1.5px\",\n                      width: `${progressPercent}%`,\n                      transition: \"width 0.15s linear\",\n                    }}\n                  />\n                  <div\n                    className=\"sc-progress-thumb\"\n                    style={{\n                      position: \"absolute\",\n                      top: \"50%\",\n                      left: `${progressPercent}%`,\n                      transform: \"translate(-50%, -50%) scale(0)\",\n                      width: \"13px\",\n                      height: \"13px\",\n                      background: adStatus.showAds ? \"#f5c518\" : \"#ff0000\",\n                      borderRadius: \"50%\",\n                      boxShadow: \"0 0 4px rgba(0, 0, 0, 0.3)\",\n                      transition: \"transform 0.1s ease, left 0.15s linear\",\n                    }}\n                  />\n                </div>\n\n                {/* Controls Row */}\n                <div\n                  style={{\n                    display: \"flex\",\n                    alignItems: \"center\",\n                    justifyContent: \"space-between\",\n                    color: \"white\",\n                    gap: `${8 * responsiveScale}px`,\n                  }}\n                >\n                  {/* Left Group */}\n                  <div\n                    style={{\n                      display: \"flex\",\n                      alignItems: \"center\",\n                      gap: `${8 * responsiveScale}px`,\n                    }}\n                  >\n                    {/* Play/Pause */}\n                    <button\n                      className=\"sc-ctrl-btn\"\n                      onClick={handlePlayPause}\n                      style={{\n                        padding: `${8 * responsiveScale}px`,\n                        borderRadius: \"50%\",\n                        minWidth: `${36 * responsiveScale}px`,\n                        minHeight: `${36 * responsiveScale}px`,\n                      }}\n                      title={isPlaying ? \"Pause\" : \"Play\"}\n                    >\n                      {isPlaying ? (\n                        <FaPause size={Math.max(14, 18 * responsiveScale)} />\n                      ) : (\n                        <FaPlay size={Math.max(14, 18 * responsiveScale)} style={{ marginLeft: \"2px\" }} />\n                      )}\n                    </button>\n\n                    {/* Volume Group - YouTube Style */}\n                    <div\n                      style={{\n                        display: \"flex\",\n                        alignItems: \"center\",\n                        paddingRight: `${6 * responsiveScale}px`,\n                      }}\n                      onMouseEnter={() => setShowVolumeSlider(true)}\n                      onMouseLeave={() => setShowVolumeSlider(false)}\n                    >\n                      <button\n                        className=\"sc-ctrl-btn\"\n                        onClick={() => {\n                          if (playerRef.current) playerRef.current.toggleMute();\n                          onVolumeToggle?.();\n                          resetControlsTimer();\n                        }}\n                        style={{\n                          padding: `${8 * responsiveScale}px`,\n                          borderRadius: \"50%\",\n                          minWidth: `${36 * responsiveScale}px`,\n                          minHeight: `${36 * responsiveScale}px`,\n                        }}\n                        title={isMuted ? \"Unmute\" : \"Mute\"}\n                      >\n                        <VolumeIcon size={Math.max(14, 18 * responsiveScale)} />\n                      </button>\n                      <div\n                        style={{\n                          width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n                          overflow: \"hidden\",\n                          transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n                          display: \"flex\",\n                          alignItems: \"center\",\n                          paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n                          paddingRight: showVolumeSlider ? `${8 * responsiveScale}px` : \"0\",\n                        }}\n                      >\n                        <div\n                          style={{\n                            position: \"relative\",\n                            width: `${56 * responsiveScale}px`,\n                            height: \"3px\",\n                            cursor: \"pointer\",\n                            borderRadius: \"1.5px\",\n                          }}\n                          onMouseDown={(e) => {\n                            e.preventDefault();\n                            const el = e.currentTarget;\n                            const move = (ev: MouseEvent) => {\n                              const r = el.getBoundingClientRect();\n                              handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)));\n                            };\n                            const up = () => { document.removeEventListener(\"mousemove\", move); document.removeEventListener(\"mouseup\", up); };\n                            document.addEventListener(\"mousemove\", move);\n                            document.addEventListener(\"mouseup\", up);\n                            const r = el.getBoundingClientRect();\n                            handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                          }}\n                          onClick={(e) => {\n                            e.stopPropagation();\n                            const r = e.currentTarget.getBoundingClientRect();\n                            handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                          }}\n                        >\n                          <div style={{ position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" }} />\n                          <div\n                            style={{\n                              position: \"absolute\",\n                              top: 0, left: 0, bottom: 0,\n                              width: `${(isMuted ? 0 : volume) * 100}%`,\n                              background: \"#fff\",\n                              borderRadius: \"1.5px\",\n                              transition: \"width 0.1s ease-out\",\n                            }}\n                          />\n                          <div\n                            style={{\n                              position: \"absolute\",\n                              top: \"50%\",\n                              left: `${(isMuted ? 0 : volume) * 100}%`,\n                              transform: \"translate(-50%, -50%)\",\n                              width: \"12px\",\n                              height: \"12px\",\n                              background: \"#fff\",\n                              borderRadius: \"50%\",\n                              boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n                              transition: \"left 0.1s ease-out\",\n                            }}\n                          />\n                        </div>\n                      </div>\n                    </div>\n\n                    {/* Time Display */}\n                    <div\n                      style={{\n                        fontSize: `${13 * responsiveScale}px`,\n                        fontFamily: \"Roboto, 'Segoe UI', Arial, sans-serif\",\n                        color: \"rgba(255, 255, 255, 0.9)\",\n                        display: viewportWidth < 480 ? \"none\" : \"block\",\n                        fontVariantNumeric: \"tabular-nums\",\n                        userSelect: \"none\",\n                        marginLeft: `${4 * responsiveScale}px`,\n                      }}\n                    >\n                      {formatTime(currentTime)}{\" \"}\n                      <span style={{ color: \"rgba(255,255,255,0.5)\" }}>/</span>{\" \"}\n                      {formatTime(duration)}\n                    </div>\n                  </div>\n\n                  {/* Right Group */}\n                  <div\n                    style={{\n                      display: \"flex\",\n                      alignItems: \"center\",\n                      gap: `${8 * responsiveScale}px`,\n                    }}\n                  >\n                    {/* Speed Selector */}\n                    <div style={{ position: \"relative\", display: viewportWidth < 600 ? \"none\" : \"block\" }}>\n                      <button\n                        className=\"sc-ctrl-btn\"\n                        onClick={() => { setShowSpeedMenu(!showSpeedMenu); resetControlsTimer(); }}\n                        style={{\n                          padding: `${6 * responsiveScale}px ${10 * responsiveScale}px`,\n                          borderRadius: `${6 * responsiveScale}px`,\n                          fontSize: `${13 * responsiveScale}px`,\n                          fontFamily: \"'SF Mono', 'Cascadia Code', monospace\",\n                          fontWeight: \"600\",\n                          minHeight: `${32 * responsiveScale}px`,\n                        }}\n                        title=\"Playback Speed\"\n                      >\n                        {playbackRate}x\n                      </button>\n\n                      {showSpeedMenu && (\n                        <div\n                          style={{\n                            position: \"absolute\",\n                            bottom: \"100%\",\n                            right: 0,\n                            marginBottom: \"8px\",\n                            background: \"rgba(0, 0, 0, 0.8)\",\n                            backdropFilter: \"blur(24px)\",\n                            WebkitBackdropFilter: \"blur(24px)\",\n                            borderRadius: \"10px\",\n                            border: \"1px solid rgba(255, 255, 255, 0.1)\",\n                            overflow: \"hidden\",\n                            minWidth: \"80px\",\n                            boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5)\",\n                            animation: \"sc-fade-in 0.15s ease\",\n                          }}\n                        >\n                          {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map((speed) => (\n                            <button\n                              key={speed}\n                              onClick={() => handlePlaybackRateChange(speed)}\n                              style={{\n                                display: \"block\",\n                                width: \"100%\",\n                                padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n                                background: playbackRate === speed\n                                  ? \"rgba(255, 255, 255, 0.12)\"\n                                  : \"transparent\",\n                                border: \"none\",\n                                color: playbackRate === speed ? \"#fff\" : \"rgba(255, 255, 255, 0.7)\",\n                                cursor: \"pointer\",\n                                fontSize: `${12 * responsiveScale}px`,\n                                fontFamily: \"'SF Mono', monospace\",\n                                fontWeight: playbackRate === speed ? \"700\" : \"500\",\n                                textAlign: \"center\",\n                                transition: \"background 0.15s ease, color 0.15s ease\",\n                              }}\n                              onMouseEnter={(e) => {\n                                if (playbackRate !== speed) {\n                                  (e.target as HTMLElement).style.background = \"rgba(255, 255, 255, 0.08)\";\n                                  (e.target as HTMLElement).style.color = \"#fff\";\n                                }\n                              }}\n                              onMouseLeave={(e) => {\n                                if (playbackRate !== speed) {\n                                  (e.target as HTMLElement).style.background = \"transparent\";\n                                  (e.target as HTMLElement).style.color = \"rgba(255, 255, 255, 0.7)\";\n                                }\n                              }}\n                            >\n                              {speed}x\n                            </button>\n                          ))}\n                        </div>\n                      )}\n                    </div>\n\n                    {/* Fullscreen */}\n                    <button\n                      className=\"sc-ctrl-btn\"\n                      onClick={() => {\n                        if (onFullscreenToggle) {\n                          onFullscreenToggle();\n                        } else if (wrapperRef.current) {\n                          if (!document.fullscreenElement) {\n                            wrapperRef.current.requestFullscreen().catch(() => {});\n                          } else {\n                            document.exitFullscreen().catch(() => {});\n                          }\n                        }\n                        resetControlsTimer();\n                      }}\n                      style={{\n                        padding: `${8 * responsiveScale}px`,\n                        borderRadius: \"50%\",\n                        minWidth: `${36 * responsiveScale}px`,\n                        minHeight: `${36 * responsiveScale}px`,\n                      }}\n                      title={isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"}\n                    >\n                      {isFullscreen ? (\n                        <CompressIcon size={Math.max(14, 18 * responsiveScale)} />\n                      ) : (\n                        <ExpandIcon size={Math.max(14, 18 * responsiveScale)} />\n                      )}\n                    </button>\n                  </div>\n                </div>\n              </div>\n            ) : (\n              showCustomControls && !showLicenseWarning && (\n                <>\n                  <div\n                    style={{\n                      position: \"absolute\",\n                      top: `${10 * responsiveScale}px`,\n                      left: `${10 * responsiveScale}px`,\n                      display: \"flex\",\n                      alignItems: \"center\",\n                      gap: \"6px\",\n                      zIndex: 10,\n                      opacity: controlsVisible ? 1 : 0,\n                      transition: \"opacity 0.35s ease\",\n                    }}\n                  >\n                    <div\n                      style={{\n                        width: \"8px\",\n                        height: \"8px\",\n                        borderRadius: \"50%\",\n                        background: \"#ff3b30\",\n                        animation: \"sc-pulse 1.5s ease-in-out infinite\",\n                        flexShrink: 0,\n                      }}\n                    />\n                    <span\n                      style={{\n                        fontSize: `${12 * responsiveScale}px`,\n                        fontFamily: \"'SF Pro Display', 'Segoe UI', Arial, sans-serif\",\n                        fontWeight: 700,\n                        letterSpacing: \"0.08em\",\n                        color: \"#fff\",\n                        textShadow: \"0 1px 3px rgba(0,0,0,0.6)\",\n                        userSelect: \"none\",\n                      }}\n                    >\n                      LIVE\n                    </span>\n                  </div>\n\n                  <div\n                  className=\"sc-controls-bar\"\n                  style={{\n                    position: \"absolute\",\n                    bottom: `${10 * responsiveScale}px`,\n                    right: `${10 * responsiveScale}px`,\n                    display: \"flex\",\n                    flexDirection: isPortrait ? \"column\" : \"row\",\n                    alignItems: isPortrait ? \"flex-end\" : \"center\",\n                    gap: `${8 * responsiveScale}px`,\n                    zIndex: 10,\n                    opacity: controlsVisible ? 1 : 0,\n                    transform: controlsVisible ? \"translateY(0)\" : \"translateY(4px)\",\n                    pointerEvents: controlsVisible ? \"auto\" : \"none\",\n                  }}\n                >\n                  <div\n                    style={{\n                      display: \"flex\",\n                      alignItems: \"center\",\n                      background: \"rgba(0, 0, 0, 0.6)\",\n                      borderRadius: `${18 * responsiveScale}px`,\n                      padding: \"2px\",\n                      paddingRight: `${8 * responsiveScale}px`,\n                    }}\n                    onMouseEnter={() => setShowVolumeSlider(true)}\n                    onMouseLeave={() => setShowVolumeSlider(false)}\n                  >\n                    <button\n                      className=\"sc-ctrl-btn\"\n                      onClick={() => {\n                        if (playerRef.current) playerRef.current.toggleMute();\n                        onVolumeToggle?.();\n                        resetControlsTimer();\n                      }}\n                      style={{\n                        padding: `${8 * responsiveScale}px`,\n                        borderRadius: \"50%\",\n                        minWidth: `${36 * responsiveScale}px`,\n                        minHeight: `${36 * responsiveScale}px`,\n                      }}\n                      title={isMuted ? \"Unmute\" : \"Mute\"}\n                    >\n                      <VolumeIcon size={Math.max(14, 18 * responsiveScale)} />\n                    </button>\n                    <div\n                      style={{\n                        width: showVolumeSlider ? `${68 * responsiveScale}px` : \"0px\",\n                        overflow: \"hidden\",\n                        transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n                        display: \"flex\",\n                        alignItems: \"center\",\n                        paddingLeft: showVolumeSlider ? `${3 * responsiveScale}px` : \"0\",\n                        paddingRight: showVolumeSlider ? `${10 * responsiveScale}px` : \"0\",\n                      }}\n                    >\n                      <div\n                        style={{\n                          position: \"relative\",\n                          width: `${56 * responsiveScale}px`,\n                          height: \"3px\",\n                          cursor: \"pointer\",\n                          borderRadius: \"1.5px\",\n                        }}\n                        onMouseDown={(e) => {\n                          e.preventDefault();\n                          const el = e.currentTarget;\n                          const move = (ev: MouseEvent) => {\n                            const r = el.getBoundingClientRect();\n                            handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)));\n                          };\n                          const up = () => { document.removeEventListener(\"mousemove\", move); document.removeEventListener(\"mouseup\", up); };\n                          document.addEventListener(\"mousemove\", move);\n                          document.addEventListener(\"mouseup\", up);\n                          const r = el.getBoundingClientRect();\n                          handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                        }}\n                        onClick={(e) => {\n                          e.stopPropagation();\n                          const r = e.currentTarget.getBoundingClientRect();\n                          handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));\n                        }}\n                      >\n                        <div style={{ position: \"absolute\", inset: 0, background: \"rgba(255, 255, 255, 0.2)\", borderRadius: \"1.5px\" }} />\n                        <div\n                          style={{\n                            position: \"absolute\",\n                            top: 0, left: 0, bottom: 0,\n                            width: `${(isMuted ? 0 : volume) * 100}%`,\n                            background: \"#fff\",\n                            borderRadius: \"1.5px\",\n                            transition: \"width 0.1s ease-out\",\n                          }}\n                        />\n                        <div\n                          style={{\n                            position: \"absolute\",\n                            top: \"50%\",\n                            left: `${(isMuted ? 0 : volume) * 100}%`,\n                            transform: \"translate(-50%, -50%)\",\n                            width: \"12px\",\n                            height: \"12px\",\n                            background: \"#fff\",\n                            borderRadius: \"50%\",\n                            boxShadow: \"0 0 3px rgba(0, 0, 0, 0.3)\",\n                            transition: \"left 0.1s ease-out\",\n                          }}\n                        />\n                      </div>\n                    </div>\n                  </div>\n\n                  <button\n                    className=\"sc-ctrl-btn\"\n                    onClick={() => {\n                      if (onFullscreenToggle) {\n                        onFullscreenToggle();\n                      } else if (wrapperRef.current) {\n                        if (!document.fullscreenElement) {\n                          wrapperRef.current.requestFullscreen().catch(() => {});\n                        } else {\n                          document.exitFullscreen().catch(() => {});\n                        }\n                      }\n                      resetControlsTimer();\n                    }}\n                    style={{\n                      padding: `${8 * responsiveScale}px`,\n                      borderRadius: \"50%\",\n                      minWidth: `${36 * responsiveScale}px`,\n                      minHeight: `${36 * responsiveScale}px`,\n                      background: \"rgba(0, 0, 0, 0.6)\",\n                    }}\n                    title={isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"}\n                  >\n                    {isFullscreen ? (\n                      <CompressIcon size={Math.max(14, 18 * responsiveScale)} />\n                    ) : (\n                      <ExpandIcon size={Math.max(14, 18 * responsiveScale)} />\n                    )}\n                  </button>\n                  </div>\n                </>\n              )\n            )}\n\n            {onControlClick && (\n              <div\n                onClick={onControlClick}\n                style={{\n                  position: \"absolute\",\n                  top: 0,\n                  left: 0,\n                  right: 0,\n                  bottom: 0,\n                  zIndex: 1,\n                  cursor: \"pointer\",\n                }}\n              />\n            )}\n          </div>\n        </>\n      );\n    },\n    (prevProps, nextProps) => {\n      for (const prop of CRITICAL_PROPS) {\n        if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n          return false;\n        }\n      }\n\n      const uiProps = [\n        \"autoplay\",\n        \"muted\",\n        \"controls\",\n        \"showCustomControls\",\n        \"className\",\n        \"style\",\n        \"wrapperClassName\",\n        \"wrapperStyle\",\n        \"playsInline\",\n        \"preload\",\n        \"poster\",\n        \"children\",\n      ] as const;\n\n      for (const prop of uiProps) {\n        if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n          return false;\n        }\n      }\n\n      const callbackProps = [\n        \"onReady\",\n        \"onVolumeToggle\",\n        \"onFullscreenToggle\",\n        \"onControlClick\",\n      ] as const;\n      for (const prop of callbackProps) {\n        if ((prevProps as any)[prop] !== (nextProps as any)[prop]) {\n          return false;\n        }\n      }\n\n      return true;\n    }\n  );\n","import type { AdController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n  url: string;\n  type: string;\n  width: number;\n  height: number;\n  bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n  impression: 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  resume: string[];\n  fullscreen: string[];\n  exitFullscreen: string[];\n  skip: string[];\n  error: string[];\n}\n\ninterface VastAd {\n  id: string;\n  title: string;\n  duration: number;\n  mediaFiles: VastMediaFile[];\n  trackingUrls: VastTrackingUrls;\n  clickThrough?: string | undefined;\n}\n\ntype VastParseResult =\n  | { type: \"inline\"; ad: VastAd }\n  | {\n      type: \"wrapper\";\n      vastAdTagUri: string;\n      trackingUrls: VastTrackingUrls;\n      clickThrough?: string | undefined;\n    }\n  | { type: \"empty\" };\n\nconst MAX_VAST_WRAPPER_DEPTH = 5;\n\nexport function createHlsAdPlayer(\n  contentVideo: HTMLVideoElement,\n  options?: {\n    continueLiveStreamDuringAds?: boolean;\n    licenseKey?: string;\n    mainHlsInstance?: Hls;\n  }\n): AdController {\n  let adPlaying = false;\n  let originalMutedState = false;\n  let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n  const listeners = new Map<string, Set<(payload?: any) => void>>();\n  const licenseKey = options?.licenseKey;\n  const mainHlsInstance = options?.mainHlsInstance;\n\n  let adVideoElement: HTMLVideoElement | undefined;\n  let adHls: Hls | undefined;\n  let adContainerEl: HTMLDivElement | undefined;\n  let currentAd: VastAd | undefined;\n  let podAds: VastAd[] = [];\n  let podIndex = 0;\n  let sessionId: string | undefined;\n  const preloadedAds = new Map<string, VastAd>();\n  const preloadingAds = new Map<string, Promise<void>>();\n  let destroyed = false;\n  let pendingTimeouts: number[] = [];\n\n  const STALL_TIMEOUT_MS = 4000;\n  const STALL_CHECK_INTERVAL_MS = 1000;\n  let stallWatchdogId: number | undefined;\n  let lastAdProgressTime = 0;\n  let lastAdProgressPosition = 0;\n\n  let trackingFired = {\n    impression: false,\n    start: false,\n    firstQuartile: false,\n    midpoint: false,\n    thirdQuartile: false,\n    complete: false,\n  };\n\n  function emit(event: string, payload?: any): void {\n    const set = listeners.get(event);\n    if (!set) return;\n    for (const fn of Array.from(set)) {\n      try {\n        fn(payload);\n      } catch (error) {\n        console.warn(\n          `[HlsAdPlayer] Error in event listener for ${event}:`,\n          error\n        );\n      }\n    }\n  }\n\n  function generateSessionId(): string {\n    return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n  }\n\n  function fireTrackingPixels(urls: string[]): void {\n    if (!urls || urls.length === 0) return;\n\n    urls.forEach((url) => {\n      try {\n        let trackingUrl = url;\n\n        if (sessionId) {\n          trackingUrl = `${trackingUrl}${\n            trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n          }session_id=${sessionId}`;\n        }\n\n        if (licenseKey) {\n          trackingUrl = `${trackingUrl}${\n            trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n          }license_key=${licenseKey}`;\n        }\n\n        const img = new Image(1, 1);\n        img.src = trackingUrl;\n        console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n      } catch (error) {\n        console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n      }\n    });\n  }\n\n  function getMainStreamQuality(): {\n    width: number;\n    height: number;\n    bitrate: number;\n  } | null {\n    if (!mainHlsInstance || !mainHlsInstance.levels) {\n      return null;\n    }\n\n    const currentLevel = mainHlsInstance.currentLevel;\n    if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n      const autoLevel = mainHlsInstance.loadLevel;\n      if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n        const level = mainHlsInstance.levels[autoLevel];\n        return {\n          width: level.width || 1920,\n          height: level.height || 1080,\n          bitrate: level.bitrate || 5000000,\n        };\n      }\n      return null;\n    }\n\n    const level = mainHlsInstance.levels[currentLevel];\n    return {\n      width: level.width || 1920,\n      height: level.height || 1080,\n      bitrate: level.bitrate || 5000000,\n    };\n  }\n\n  function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n    if (mediaFiles.length === 0) {\n      throw new Error(\"No media files available\");\n    }\n\n    const firstFile = mediaFiles[0];\n    if (!firstFile) {\n      throw new Error(\"No media files available\");\n    }\n\n    if (mediaFiles.length === 1) {\n      return firstFile;\n    }\n\n    const mainQuality = getMainStreamQuality();\n    if (!mainQuality) {\n      console.log(\n        \"[HlsAdPlayer] No main stream quality info, using first media file\"\n      );\n      return firstFile;\n    }\n\n    console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n    const scoredFiles = mediaFiles.map((file) => {\n      const widthDiff = Math.abs(file.width - mainQuality.width);\n      const heightDiff = Math.abs(file.height - mainQuality.height);\n      const resolutionDiff = widthDiff + heightDiff;\n\n      const fileBitrate = (file.bitrate || 5000) * 1000;\n      const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n      const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n      return { file, score, resolutionDiff, bitrateDiff };\n    });\n\n    scoredFiles.sort((a, b) => a.score - b.score);\n\n    const bestMatch = scoredFiles[0];\n    if (!bestMatch) {\n      console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n      return firstFile;\n    }\n\n    console.log(\"[HlsAdPlayer] Selected media file:\", {\n      url: bestMatch.file.url,\n      resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n      bitrate: bestMatch.file.bitrate,\n      score: bestMatch.score,\n      resolutionDiff: bestMatch.resolutionDiff,\n      bitrateDiff: bestMatch.bitrateDiff,\n    });\n\n    return bestMatch.file;\n  }\n\n  function isHlsMediaFile(mediaFile: VastMediaFile): boolean {\n    const type = mediaFile.type.toLowerCase();\n    const url = mediaFile.url.toLowerCase();\n    return (\n      type === \"application/x-mpegurl\" ||\n      type === \"application/vnd.apple.mpegurl\" ||\n      type.includes(\"mpegurl\") ||\n      url.includes(\".m3u8\")\n    );\n  }\n\n  function isProgressiveMediaFile(mediaFile: VastMediaFile): boolean {\n    const type = mediaFile.type.toLowerCase();\n    const url = mediaFile.url.toLowerCase();\n    return (\n      type.startsWith(\"video/\") ||\n      url.endsWith(\".mp4\") ||\n      url.includes(\".mp4?\")\n    );\n  }\n\n  function createEmptyTrackingUrls(): VastTrackingUrls {\n    return {\n      impression: [],\n      start: [],\n      firstQuartile: [],\n      midpoint: [],\n      thirdQuartile: [],\n      complete: [],\n      mute: [],\n      unmute: [],\n      pause: [],\n      resume: [],\n      fullscreen: [],\n      exitFullscreen: [],\n      skip: [],\n      error: [],\n    };\n  }\n\n  function extractTrackingUrls(scope: Document | Element): VastTrackingUrls {\n    const trackingUrls = createEmptyTrackingUrls();\n\n    scope.querySelectorAll(\"Impression\").forEach((el) => {\n      const url = el.textContent?.trim();\n      if (url) trackingUrls.impression.push(url);\n    });\n\n    scope.querySelectorAll(\"Tracking\").forEach((el) => {\n      const event = el.getAttribute(\"event\");\n      const url = el.textContent?.trim();\n      if (event && url) {\n        const eventKey = event as keyof VastTrackingUrls;\n        if (trackingUrls[eventKey]) {\n          trackingUrls[eventKey].push(url);\n        }\n      }\n    });\n\n    scope.querySelectorAll(\"Error\").forEach((el) => {\n      const url = el.textContent?.trim();\n      if (url) trackingUrls.error.push(url);\n    });\n\n    return trackingUrls;\n  }\n\n  function mergeTrackingUrls(\n    target: VastTrackingUrls,\n    source: VastTrackingUrls\n  ): VastTrackingUrls {\n    (Object.keys(target) as Array<keyof VastTrackingUrls>).forEach((key) => {\n      if (source[key] && source[key].length > 0) {\n        target[key] = target[key].concat(source[key]);\n      }\n    });\n    return target;\n  }\n\n  function parseVastXml(xmlString: string): VastParseResult {\n    try {\n      const parser = new DOMParser();\n      const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n      const parserError = xmlDoc.querySelector(\"parsererror\");\n      if (parserError) {\n        console.error(\n          \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n          parserError.textContent\n        );\n        return { type: \"empty\" };\n      }\n\n      const adElement = xmlDoc.querySelector(\"Ad\");\n      if (!adElement) {\n        console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n        return { type: \"empty\" };\n      }\n\n      const adId = adElement.getAttribute(\"id\") || \"unknown\";\n      const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n      const clickThrough = xmlDoc\n        .querySelector(\"ClickThrough\")\n        ?.textContent?.trim();\n\n      const wrapperUri = xmlDoc\n        .querySelector(\"VASTAdTagURI\")\n        ?.textContent?.trim();\n      if (wrapperUri) {\n        console.log(\n          `[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ${wrapperUri}`\n        );\n        return {\n          type: \"wrapper\",\n          vastAdTagUri: wrapperUri,\n          trackingUrls: extractTrackingUrls(xmlDoc),\n          clickThrough,\n        };\n      }\n\n      const isNoAdAvailable =\n        adId === \"empty\" ||\n        title.toLowerCase().includes(\"no ad available\") ||\n        title.toLowerCase() === \"no ad available\";\n\n      const durationText =\n        xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n      const durationParts = durationText.split(\":\");\n      const duration =\n        parseInt(durationParts[0] || \"0\", 10) * 3600 +\n        parseInt(durationParts[1] || \"0\", 10) * 60 +\n        parseInt(durationParts[2] || \"0\", 10);\n\n      const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n      const mediaFiles: VastMediaFile[] = [];\n\n      console.log(\n        `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n      );\n\n      mediaFileElements.forEach((mf, index) => {\n        const type = mf.getAttribute(\"type\") || \"\";\n        const url = mf.textContent?.trim() || \"\";\n        const width = mf.getAttribute(\"width\") || \"\";\n        const height = mf.getAttribute(\"height\") || \"\";\n\n        console.log(\n          `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n        );\n\n        const mediaFile: VastMediaFile = {\n          url,\n          type,\n          width: parseInt(width || \"1920\", 10),\n          height: parseInt(height || \"1080\", 10),\n          bitrate: undefined,\n        };\n\n        if (!url) {\n          console.warn(`[HlsAdPlayer] MediaFile ${index} has empty URL`);\n          return;\n        }\n\n        const bitrateAttr = mf.getAttribute(\"bitrate\");\n        const bitrateValue = bitrateAttr\n          ? parseInt(bitrateAttr, 10)\n          : undefined;\n        mediaFile.bitrate =\n          bitrateValue && bitrateValue > 0 ? bitrateValue : undefined;\n\n        if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n          mediaFiles.push(mediaFile);\n          console.log(\n            `[HlsAdPlayer] Added ${isHlsMediaFile(mediaFile) ? \"HLS\" : \"progressive\"} MediaFile: ${url}`\n          );\n        } else {\n          console.log(\n            `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not supported)`\n          );\n        }\n      });\n\n      if (mediaFiles.length === 0) {\n        if (isNoAdAvailable) {\n          console.warn(\n            \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n          );\n        } else {\n          console.warn(\"[HlsAdPlayer] No supported media files found in VAST XML\");\n        }\n        return { type: \"empty\" };\n      }\n\n      return {\n        type: \"inline\",\n        ad: {\n          id: adId,\n          title,\n          duration,\n          mediaFiles,\n          trackingUrls: extractTrackingUrls(xmlDoc),\n          clickThrough,\n        },\n      };\n    } catch (error) {\n      console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n      return { type: \"empty\" };\n    }\n  }\n\n  function parseAdElement(adElement: Element): VastParseResult {\n    try {\n      const adId = adElement.getAttribute(\"id\") || \"unknown\";\n      const title = adElement.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n      const clickThrough = adElement\n        .querySelector(\"ClickThrough\")\n        ?.textContent?.trim();\n\n      const wrapperUri = adElement\n        .querySelector(\"VASTAdTagURI\")\n        ?.textContent?.trim();\n      if (wrapperUri) {\n        return {\n          type: \"wrapper\",\n          vastAdTagUri: wrapperUri,\n          trackingUrls: extractTrackingUrls(adElement),\n          clickThrough,\n        };\n      }\n\n      const isNoAdAvailable =\n        adId === \"empty\" ||\n        title.toLowerCase().includes(\"no ad available\") ||\n        title.toLowerCase() === \"no ad available\";\n\n      const durationText =\n        adElement.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n      const durationParts = durationText.split(\":\");\n      const duration =\n        parseInt(durationParts[0] || \"0\", 10) * 3600 +\n        parseInt(durationParts[1] || \"0\", 10) * 60 +\n        parseInt(durationParts[2] || \"0\", 10);\n\n      const mediaFileElements = adElement.querySelectorAll(\"MediaFile\");\n      const mediaFiles: VastMediaFile[] = [];\n\n      mediaFileElements.forEach((mf) => {\n        const type = mf.getAttribute(\"type\") || \"\";\n        const url = mf.textContent?.trim() || \"\";\n        const width = mf.getAttribute(\"width\") || \"\";\n        const height = mf.getAttribute(\"height\") || \"\";\n\n        if (!url) return;\n\n        const bitrateAttr = mf.getAttribute(\"bitrate\");\n        const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n        const mediaFile: VastMediaFile = {\n          url,\n          type,\n          width: parseInt(width || \"1920\", 10),\n          height: parseInt(height || \"1080\", 10),\n          bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n        };\n\n        if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {\n          mediaFiles.push(mediaFile);\n        }\n      });\n\n      if (mediaFiles.length === 0) {\n        if (isNoAdAvailable) {\n          console.warn(\n            \"[HlsAdPlayer] Pod <Ad> indicates no ad available\"\n          );\n        } else {\n          console.warn(\"[HlsAdPlayer] No supported media files in pod <Ad>\");\n        }\n        return { type: \"empty\" };\n      }\n\n      return {\n        type: \"inline\",\n        ad: {\n          id: adId,\n          title,\n          duration,\n          mediaFiles,\n          trackingUrls: extractTrackingUrls(adElement),\n          clickThrough,\n        },\n      };\n    } catch (error) {\n      console.error(\"[HlsAdPlayer] Error parsing pod <Ad> element:\", error);\n      return { type: \"empty\" };\n    }\n  }\n\n  async function fetchVastXml(\n    vastTagUrl: string,\n    credentials: RequestCredentials = \"include\"\n  ): Promise<string> {\n    const requestVast = (creds: RequestCredentials) =>\n      fetch(vastTagUrl, {\n        mode: \"cors\",\n        credentials: creds,\n        headers: {\n          \"Accept\": \"application/xml, text/xml, */*\",\n        },\n        referrerPolicy: \"no-referrer-when-downgrade\",\n      });\n\n    let response: Response;\n    try {\n      response = await requestVast(credentials);\n    } catch (error) {\n      if (credentials !== \"omit\") {\n        console.warn(\n          `[HlsAdPlayer] VAST fetch failed with credentials=\"${credentials}\", retrying without credentials:`,\n          error\n        );\n        response = await requestVast(\"omit\");\n      } else {\n        throw error;\n      }\n    }\n\n    if (!response.ok) {\n      throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n    }\n    return response.text();\n  }\n\n  async function fetchAndParseVastAd(\n    vastTagUrl: string,\n    depth = 0,\n    accumulatedTracking: VastTrackingUrls = createEmptyTrackingUrls()\n  ): Promise<VastAd | null> {\n    const vastXml = await fetchVastXml(\n      vastTagUrl,\n      depth === 0 ? \"include\" : \"omit\"\n    );\n    console.log(\"[HlsAdPlayer] VAST XML received\");\n    console.log(\n      \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n      vastXml.substring(0, 2000)\n    );\n\n    const parsed = parseVastXml(vastXml);\n\n    if (parsed.type === \"empty\") {\n      return null;\n    }\n\n    if (parsed.type === \"wrapper\") {\n      if (depth >= MAX_VAST_WRAPPER_DEPTH) {\n        console.warn(\n          `[HlsAdPlayer] VAST wrapper depth limit (${MAX_VAST_WRAPPER_DEPTH}) reached, aborting redirect chain`\n        );\n        return null;\n      }\n\n      mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);\n      return fetchAndParseVastAd(\n        parsed.vastAdTagUri,\n        depth + 1,\n        accumulatedTracking\n      );\n    }\n\n    mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);\n    return parsed.ad;\n  }\n\n  async function fetchAndParsePod(vastTagUrl: string): Promise<VastAd[]> {\n    const vastXml = await fetchVastXml(vastTagUrl);\n    console.log(\"[HlsAdPlayer] Pod VAST XML received\");\n\n    const parser = new DOMParser();\n    const xmlDoc = parser.parseFromString(vastXml, \"text/xml\");\n\n    if (xmlDoc.querySelector(\"parsererror\")) {\n      console.error(\"[HlsAdPlayer] Pod VAST XML parsing error (malformed)\");\n      return [];\n    }\n\n    const adElements = Array.from(xmlDoc.querySelectorAll(\"Ad\"));\n    if (adElements.length === 0) {\n      console.warn(\"[HlsAdPlayer] No <Ad> elements found in pod VAST response\");\n      return [];\n    }\n\n    adElements.sort((a, b) => {\n      const aSeq = parseInt(a.getAttribute(\"sequence\") || \"\", 10);\n      const bSeq = parseInt(b.getAttribute(\"sequence\") || \"\", 10);\n      const aVal = Number.isFinite(aSeq) ? aSeq : Number.MAX_SAFE_INTEGER;\n      const bVal = Number.isFinite(bSeq) ? bSeq : Number.MAX_SAFE_INTEGER;\n      return aVal - bVal;\n    });\n\n    const ads: VastAd[] = [];\n    for (const adElement of adElements) {\n      const parsed = parseAdElement(adElement);\n\n      if (parsed.type === \"inline\") {\n        ads.push(parsed.ad);\n      } else if (parsed.type === \"wrapper\") {\n        try {\n          const resolved = await fetchAndParseVastAd(\n            parsed.vastAdTagUri,\n            1,\n            parsed.trackingUrls\n          );\n          if (resolved) {\n            ads.push(resolved);\n          }\n        } catch (error) {\n          console.warn(\n            \"[HlsAdPlayer] Failed to resolve wrapper <Ad> in pod:\",\n            error\n          );\n        }\n      }\n    }\n\n    console.log(`[HlsAdPlayer] Parsed ${ads.length} ad(s) from pod VAST response`);\n    return ads;\n  }\n\n  function createAdVideoElement(): HTMLVideoElement {\n    const video = document.createElement(\"video\");\n    video.style.position = \"absolute\";\n    video.style.left = \"0\";\n    video.style.top = \"0\";\n    video.style.width = \"100%\";\n    video.style.height = \"100%\";\n    video.style.objectFit = \"contain\";\n    video.style.backgroundColor = \"#000\";\n    video.playsInline = true;\n    video.muted = false;\n\n    video.volume = 1.0;\n    console.log(\n      `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n    );\n\n    return video;\n  }\n\n  function setupAdEventListeners(): void {\n    if (!adVideoElement || !currentAd) return;\n\n    adVideoElement.addEventListener(\"timeupdate\", () => {\n      if (!currentAd || !adVideoElement) return;\n\n      noteAdProgress();\n\n      const progress = adVideoElement.currentTime / currentAd.duration;\n\n      if (progress >= 0.25 && !trackingFired.firstQuartile) {\n        trackingFired.firstQuartile = true;\n        fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n      }\n\n      if (progress >= 0.5 && !trackingFired.midpoint) {\n        trackingFired.midpoint = true;\n        fireTrackingPixels(currentAd.trackingUrls.midpoint);\n      }\n\n      if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n        trackingFired.thirdQuartile = true;\n        fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n      }\n    });\n\n    adVideoElement.addEventListener(\"playing\", () => {\n      startStallWatchdog();\n      if (!currentAd || trackingFired.start) return;\n      trackingFired.start = true;\n      fireTrackingPixels(currentAd.trackingUrls.start);\n      console.log(\"[HlsAdPlayer] Ad started playing\");\n    });\n\n    adVideoElement.addEventListener(\"ended\", () => {\n      if (!currentAd || trackingFired.complete) return;\n      trackingFired.complete = true;\n      fireTrackingPixels(currentAd.trackingUrls.complete);\n      console.log(\"[HlsAdPlayer] Ad completed\");\n\n      if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {\n        return;\n      }\n\n      handleAdComplete();\n    });\n\n    adVideoElement.addEventListener(\"error\", (e) => {\n      if (!adPlaying) return;\n      console.error(\"[HlsAdPlayer] Ad video error:\", e);\n      if (currentAd) {\n        fireTrackingPixels(currentAd.trackingUrls.error);\n      }\n\n      if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {\n        return;\n      }\n\n      handleAdError();\n    });\n\n    adVideoElement.addEventListener(\"volumechange\", () => {\n      if (!currentAd) return;\n      if (adVideoElement!.muted) {\n        fireTrackingPixels(currentAd.trackingUrls.mute);\n      } else {\n        fireTrackingPixels(currentAd.trackingUrls.unmute);\n      }\n    });\n\n    adVideoElement.addEventListener(\"pause\", () => {\n      if (currentAd && !adVideoElement!.ended) {\n        fireTrackingPixels(currentAd.trackingUrls.pause);\n      }\n    });\n\n    adVideoElement.addEventListener(\"play\", () => {\n      if (currentAd && adVideoElement!.currentTime > 0) {\n        fireTrackingPixels(currentAd.trackingUrls.resume);\n      }\n    });\n  }\n\n  function setAdPlayingFlag(isPlaying: boolean): void {\n    if (isPlaying) {\n      contentVideo.dataset.stormcloudAdPlaying = \"true\";\n    } else {\n      delete contentVideo.dataset.stormcloudAdPlaying;\n    }\n  }\n\n  function resetQuartileTracking(preserveImpression: boolean): void {\n    trackingFired = {\n      impression: preserveImpression ? trackingFired.impression : false,\n      start: false,\n      firstQuartile: false,\n      midpoint: false,\n      thirdQuartile: false,\n      complete: false,\n    };\n  }\n\n  function loadCurrentAdMedia(): void {\n    if (!adVideoElement || !currentAd) {\n      throw new Error(\"No ad video element or ad to load\");\n    }\n\n    const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n    if (!mediaFile) {\n      throw new Error(\"No media file available for ad\");\n    }\n\n    const isHlsAd = isHlsMediaFile(mediaFile);\n    console.log(\n      `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad (pod ${podIndex + 1}/${podAds.length || 1}) from: ${mediaFile.url}`\n    );\n\n    if (isHlsAd && Hls.isSupported()) {\n      if (adHls) {\n        adHls.destroy();\n      }\n\n      adHls = new Hls({\n        enableWorker: true,\n        lowLatencyMode: false,\n      });\n\n      adHls.loadSource(mediaFile.url);\n      adHls.attachMedia(adVideoElement);\n\n      adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n        console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n        adVideoElement!.play().catch((error) => {\n          console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n          handleAdError();\n        });\n      });\n\n      adHls.on(Hls.Events.ERROR, (_event, data) => {\n        console.error(\"[HlsAdPlayer] HLS error:\", data);\n        if (data.fatal) {\n          handleAdError();\n        }\n      });\n    } else if (\n      isHlsAd &&\n      adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n    ) {\n      adVideoElement.src = mediaFile.url;\n      adVideoElement.play().catch((error) => {\n        console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n        handleAdError();\n      });\n    } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {\n      if (adHls) {\n        adHls.destroy();\n        adHls = undefined;\n      }\n\n      adVideoElement.src = mediaFile.url;\n      adVideoElement.load();\n      adVideoElement.play().catch((error) => {\n        console.error(\"[HlsAdPlayer] Error starting progressive ad playback:\", error);\n        handleAdError();\n      });\n    } else {\n      throw new Error(`Unsupported ad media file type: ${mediaFile.type}`);\n    }\n  }\n\n  function advanceToNextPodAd(): boolean {\n    if (podIndex >= podAds.length - 1) {\n      return false;\n    }\n\n    podIndex++;\n    currentAd = podAds[podIndex];\n    resetQuartileTracking(false);\n\n    if (currentAd) {\n      fireTrackingPixels(currentAd.trackingUrls.impression);\n      trackingFired.impression = true;\n      console.log(\n        `[HlsAdPlayer] Advancing to next pod ad (${podIndex + 1}/${podAds.length}): ${currentAd.title}, duration: ${currentAd.duration}s`\n      );\n    }\n\n    try {\n      loadCurrentAdMedia();\n      emit(\"pod_ad_started\", { index: podIndex, total: podAds.length });\n      return true;\n    } catch (error) {\n      console.error(\"[HlsAdPlayer] Failed to load next pod ad:\", error);\n      return false;\n    }\n  }\n\n  function clearStallWatchdog(): void {\n    if (stallWatchdogId != null) {\n      clearInterval(stallWatchdogId);\n      stallWatchdogId = undefined;\n    }\n  }\n\n  function noteAdProgress(): void {\n    lastAdProgressTime = Date.now();\n    if (adVideoElement) {\n      lastAdProgressPosition = adVideoElement.currentTime;\n    }\n  }\n\n  function handleAdStall(): void {\n    console.warn(\n      \"[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame\"\n    );\n    clearStallWatchdog();\n\n    if (currentAd) {\n      fireTrackingPixels(currentAd.trackingUrls.error);\n    }\n\n    if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {\n      return;\n    }\n\n    handleAdError();\n  }\n\n  function startStallWatchdog(): void {\n    clearStallWatchdog();\n    noteAdProgress();\n    stallWatchdogId = window.setInterval(() => {\n      if (!adPlaying || !adVideoElement) {\n        return;\n      }\n\n      if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {\n        noteAdProgress();\n        return;\n      }\n\n      if (adVideoElement.paused) {\n        noteAdProgress();\n        return;\n      }\n\n      if (Date.now() - lastAdProgressTime >= STALL_TIMEOUT_MS) {\n        handleAdStall();\n      }\n    }, STALL_CHECK_INTERVAL_MS) as unknown as number;\n  }\n\n  function releaseAdDecoder(): void {\n    if (adHls) {\n      adHls.destroy();\n      adHls = undefined;\n    }\n\n    if (adVideoElement) {\n      adVideoElement.pause();\n      adVideoElement.removeAttribute(\"src\");\n      try {\n        adVideoElement.load();\n      } catch (error) {\n        console.warn(\"[HlsAdPlayer] adVideoElement.load() threw after src removal:\", error);\n      }\n      adVideoElement.remove();\n      adVideoElement = undefined;\n    }\n\n    if (adContainerEl) {\n      adContainerEl.style.display = \"none\";\n      adContainerEl.style.pointerEvents = \"none\";\n    }\n  }\n\n  function handleAdComplete(): void {\n    console.log(\"[HlsAdPlayer] Handling ad completion\");\n    clearStallWatchdog();\n    adPlaying = false;\n    setAdPlayingFlag(false);\n\n    contentVideo.muted = true;\n\n    releaseAdDecoder();\n\n    if (!options?.continueLiveStreamDuringAds) {\n      contentVideo.style.visibility = \"visible\";\n      contentVideo.style.opacity = \"1\";\n    }\n    \n    if (options?.continueLiveStreamDuringAds) {\n      if (contentVideo.paused) {\n        console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback\");\n        contentVideo.play().catch((error) => {\n          console.error(\"[HlsAdPlayer] Error resuming content playback in live mode:\", error);\n        });\n      } else {\n        console.log(\"[HlsAdPlayer] Content video already playing in live mode\");\n      }\n    }\n\n    emit(\"content_resume\");\n  }\n\n  function handleAdError(): void {\n    console.log(\"[HlsAdPlayer] Handling ad error\");\n    clearStallWatchdog();\n    adPlaying = false;\n    setAdPlayingFlag(false);\n\n    contentVideo.muted = true;\n\n    releaseAdDecoder();\n\n    if (!options?.continueLiveStreamDuringAds) {\n      contentVideo.style.visibility = \"visible\";\n      contentVideo.style.opacity = \"1\";\n    }\n\n    emit(\"ad_error\");\n  }\n\n  return {\n    initialize() {\n      console.log(\"[HlsAdPlayer] Initializing\");\n\n      if (!adContainerEl) {\n        const container = document.createElement(\"div\");\n        container.style.position = \"absolute\";\n        container.style.left = \"0\";\n        container.style.top = \"0\";\n        container.style.right = \"0\";\n        container.style.bottom = \"0\";\n        container.style.display = \"none\";\n        container.style.alignItems = \"center\";\n        container.style.justifyContent = \"center\";\n        container.style.pointerEvents = \"none\";\n        container.style.zIndex = \"30\";\n        container.style.backgroundColor = \"#000\";\n\n        contentVideo.parentElement?.appendChild(container);\n        adContainerEl = container;\n      }\n    },\n\n    async requestAds(vastTagUrl: string) {\n      console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n      if (adPlaying) {\n        console.warn(\n          \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n        );\n        return Promise.reject(new Error(\"Ad already playing\"));\n      }\n\n      try {\n        sessionId = generateSessionId();\n        let ads: VastAd[] = [];\n\n        if (preloadedAds.has(vastTagUrl)) {\n          const preloaded = preloadedAds.get(vastTagUrl);\n          preloadedAds.delete(vastTagUrl);\n          if (preloaded) {\n            ads = [preloaded];\n          }\n          console.log(\n            \"[HlsAdPlayer] Using preloaded VAST response:\",\n            vastTagUrl\n          );\n        } else {\n          ads = await fetchAndParsePod(vastTagUrl);\n        }\n\n        if (!ads.length) {\n          console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n          emit(\"ad_error\");\n          return Promise.reject(new Error(\"No ads available from VAST response\"));\n        }\n\n        podAds = ads;\n        podIndex = 0;\n        currentAd = ads[0];\n        console.log(\n          `[HlsAdPlayer] Pod parsed: ${ads.length} ad(s), first=\"${currentAd?.title}\", duration=${currentAd?.duration}s`\n        );\n\n        if (currentAd) {\n          fireTrackingPixels(currentAd.trackingUrls.impression);\n          trackingFired.impression = true;\n        }\n\n        return Promise.resolve();\n      } catch (error) {\n        console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n        emit(\"ad_error\");\n        return Promise.reject(error);\n      }\n    },\n    async play() {\n      if (!currentAd) {\n        console.warn(\n          \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n        );\n        return Promise.reject(new Error(\"No ad loaded\"));\n      }\n\n      console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n      try {\n        if (!adVideoElement) {\n          adVideoElement = createAdVideoElement();\n          adContainerEl?.appendChild(adVideoElement);\n          setupAdEventListeners();\n        }\n\n        resetQuartileTracking(true);\n\n        const contentVolume = contentVideo.volume;\n        originalVolume = Math.max(\n          0,\n          Math.min(1, contentVolume || originalVolume)\n        );\n\n        if (!options?.continueLiveStreamDuringAds) {\n          contentVideo.pause();\n          console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n        } else {\n          console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n        }\n\n        console.log(\"[HlsAdPlayer] FORCE MUTING main video\");\n        contentVideo.muted = true;\n        adPlaying = true;\n        setAdPlayingFlag(true);\n\n        if (adVideoElement) {\n          adVideoElement.volume = Math.max(0, Math.min(1, originalVolume));\n          adVideoElement.muted = originalMutedState;\n          console.log(\n            `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n          );\n        }\n\n        if (adContainerEl) {\n          adContainerEl.style.display = \"flex\";\n          adContainerEl.style.pointerEvents = \"auto\";\n        }\n\n        emit(\"content_pause\");\n\n        loadCurrentAdMedia();\n\n        return Promise.resolve();\n      } catch (error) {\n        console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n        handleAdError();\n        return Promise.reject(error);\n      }\n    },\n    pause() {\n      if (!adPlaying || !adVideoElement) {\n        return;\n      }\n\n      try {\n        if (adVideoElement && !adVideoElement.paused) {\n          adVideoElement.pause();\n        }\n      } catch (error) {\n        console.warn(\"[HlsAdPlayer] Error pausing ad:\", error);\n      }\n    },\n    resume() {\n      if (!adPlaying || !adVideoElement) {\n        return;\n      }\n\n      try {\n        if (adVideoElement && adVideoElement.paused) {\n          adVideoElement.play().catch(() => {});\n        }\n      } catch (error) {\n        console.warn(\"[HlsAdPlayer] Error resuming ad:\", error);\n      }\n    },\n    async stop() {\n      console.log(\"[HlsAdPlayer] Stopping ad\");\n      clearStallWatchdog();\n      adPlaying = false;\n      setAdPlayingFlag(false);\n\n      const previousMutedState = contentVideo.muted;\n      contentVideo.muted = originalMutedState;\n      contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n      console.log(\n        `[HlsAdPlayer] Restored mute state on stop: ${previousMutedState} -> ${originalMutedState}, volume: ${contentVideo.volume}`\n      );\n\n      releaseAdDecoder();\n\n      contentVideo.style.visibility = \"visible\";\n      contentVideo.style.opacity = \"1\";\n\n      if (options?.continueLiveStreamDuringAds) {\n        if (contentVideo.paused) {\n          console.log(\"[HlsAdPlayer] Content video paused in live mode, resuming playback on stop\");\n          contentVideo.play().catch((error) => {\n            console.error(\"[HlsAdPlayer] Error resuming content playback in live mode on stop:\", error);\n          });\n        }\n      }\n\n      currentAd = undefined;\n      podAds = [];\n      podIndex = 0;\n    },\n\n    destroy() {\n      console.log(\"[HlsAdPlayer] Destroying\");\n      destroyed = true;\n      clearStallWatchdog();\n\n      for (const timeoutId of pendingTimeouts) {\n        clearTimeout(timeoutId);\n      }\n      pendingTimeouts = [];\n      \n      adPlaying = false;\n      setAdPlayingFlag(false);\n      contentVideo.muted = originalMutedState;\n      contentVideo.volume = Math.max(0, Math.min(1, originalVolume));\n\n      releaseAdDecoder();\n\n      if (adContainerEl?.parentElement) {\n        adContainerEl.parentElement.removeChild(adContainerEl);\n      }\n\n      adContainerEl = undefined;\n      currentAd = undefined;\n      podAds = [];\n      podIndex = 0;\n      listeners.clear();\n      preloadedAds.clear();\n      preloadingAds.clear();\n    },\n\n    isAdPlaying() {\n      return adPlaying;\n    },\n\n    resize(width: number, height: number) {\n      console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n      if (adContainerEl) {\n        adContainerEl.style.width = `${width}px`;\n        adContainerEl.style.height = `${height}px`;\n      }\n\n      if (adVideoElement) {\n        adVideoElement.style.width = `${width}px`;\n        adVideoElement.style.height = `${height}px`;\n      }\n    },\n\n    on(event: string, listener: (payload?: any) => void) {\n      if (!listeners.has(event)) listeners.set(event, new Set());\n      listeners.get(event)!.add(listener);\n    },\n\n    off(event: string, listener: (payload?: any) => void) {\n      listeners.get(event)?.delete(listener);\n    },\n\n    updateOriginalMutedState(muted: boolean, volume?: number) {\n      const nextVolume =\n        typeof volume === \"number\" && !Number.isNaN(volume)\n          ? Math.max(0, Math.min(1, volume))\n          : originalVolume;\n      console.log(\n        `[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`\n      );\n      originalMutedState = muted;\n      originalVolume = nextVolume;\n    },\n\n    getOriginalMutedState() {\n      return originalMutedState;\n    },\n    getOriginalVolume() {\n      return originalVolume;\n    },\n\n    setAdVolume(volume: number) {\n      if (adVideoElement && adPlaying) {\n        const clamped = Math.max(0, Math.min(1, volume));\n        adVideoElement.volume = clamped;\n        adVideoElement.muted = clamped === 0;\n      }\n    },\n\n    getAdVolume(): number {\n      if (adVideoElement && adPlaying) {\n        return adVideoElement.volume;\n      }\n      return 1;\n    },\n    showPlaceholder() {\n      contentVideo.style.opacity = \"0\";\n      contentVideo.style.visibility = \"hidden\";\n      \n      if (!adContainerEl) {\n        const container = document.createElement(\"div\");\n        container.style.position = \"absolute\";\n        container.style.left = \"0\";\n        container.style.top = \"0\";\n        container.style.right = \"0\";\n        container.style.bottom = \"0\";\n        container.style.display = \"none\";\n        container.style.alignItems = \"center\";\n        container.style.justifyContent = \"center\";\n        container.style.pointerEvents = \"none\";\n        container.style.zIndex = \"10\";\n        container.style.backgroundColor = \"#000\";\n\n        contentVideo.parentElement?.appendChild(container);\n        adContainerEl = container;\n      }\n\n      if (adContainerEl) {\n        adContainerEl.style.display = \"flex\";\n        adContainerEl.style.pointerEvents = \"auto\";\n      }\n    },\n    hidePlaceholder() {\n      if (adContainerEl) {\n        adContainerEl.style.display = \"none\";\n        adContainerEl.style.pointerEvents = \"none\";\n      }\n      \n      if (!adPlaying) {\n        contentVideo.style.visibility = \"visible\";\n        contentVideo.style.opacity = \"1\";\n      }\n    },\n    getLoadedAdDuration() {\n      return currentAd?.duration;\n    },\n    getLoadedAdId() {\n      return currentAd?.id;\n    },\n    getPodAdCount() {\n      return podAds.length;\n    },\n    getPodTotalDurationMs() {\n      return podAds.reduce(\n        (total, ad) => total + (ad.duration > 0 ? ad.duration * 1000 : 0),\n        0\n      );\n    },\n  };\n}\n","const PRIVATE_HOST_PATTERNS: RegExp[] = [\n  /^localhost$/i,\n  /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n  /^0\\.0\\.0\\.0$/,\n  /^::1$/,\n  /^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n  /^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/,\n  /^172\\.(1[6-9]|2\\d|3[0-1])\\.\\d{1,3}\\.\\d{1,3}$/,\n];\n\nexport function isLocalDevHost(hostname: string): boolean {\n  const host = hostname.replace(/^\\[/, \"\").replace(/\\]$/, \"\").toLowerCase();\n  if (!host) return false;\n  if (host.endsWith(\".local\") || host.endsWith(\".localhost\")) return true;\n  return PRIVATE_HOST_PATTERNS.some((pattern) => pattern.test(host));\n}\n\nexport function toDevSafeUrl(rawUrl: string | undefined): string {\n  if (!rawUrl) return rawUrl ?? \"\";\n\n  let url: URL;\n  try {\n    url = new URL(rawUrl);\n  } catch {\n    return rawUrl;\n  }\n\n  if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n    return rawUrl;\n  }\n\n  if (!isLocalDevHost(url.hostname)) {\n    return rawUrl;\n  }\n\n  const cleanPath = url.pathname.replace(/\\/{2,}/g, \"/\") || \"/index.html\";\n  return `file://${cleanPath}`;\n}\n","import { toDevSafeUrl } from \"../utils/devUrl\";\n\ndeclare global {\n  interface Window {\n    goog?: any;\n  }\n}\n\nconst PAL_SDK_URL =\n  \"https://imasdk.googleapis.com/pal/sdkloader/pal.js\";\n\nlet _nonceLoader: any | undefined;\nlet _palLoadPromise: Promise<void> | undefined;\n\nfunction loadPalSdk(): Promise<void> {\n  if (typeof window !== \"undefined\" && window.goog?.pal) {\n    return Promise.resolve();\n  }\n\n  if (_palLoadPromise) return _palLoadPromise;\n\n  _palLoadPromise = new Promise<void>((resolve, reject) => {\n    const existing = document.querySelector(\n      'script[data-pal=\"true\"]'\n    ) as HTMLScriptElement | null;\n\n    if (existing) {\n      if (window.goog?.pal) {\n        resolve();\n        return;\n      }\n      const timeout = setTimeout(\n        () => reject(new Error(\"PAL SDK load timeout\")),\n        10000\n      );\n      existing.addEventListener(\"load\", () => {\n        clearTimeout(timeout);\n        resolve();\n      });\n      existing.addEventListener(\"error\", () => {\n        clearTimeout(timeout);\n        reject(new Error(\"PAL SDK load failed\"));\n      });\n      return;\n    }\n\n    const script = document.createElement(\"script\");\n    script.src = PAL_SDK_URL;\n    script.async = true;\n    script.setAttribute(\"data-pal\", \"true\");\n    script.onload = () => resolve();\n    script.onerror = () => reject(new Error(\"PAL SDK load failed\"));\n    document.head.appendChild(script);\n  });\n\n  return _palLoadPromise;\n}\n\nfunction getOrCreateNonceLoader(): any {\n  if (_nonceLoader) return _nonceLoader;\n  const goog = window.goog;\n  const consentSettings = new goog.pal.ConsentSettings();\n  consentSettings.allowStorage = true;\n  _nonceLoader = new goog.pal.NonceLoader(consentSettings);\n  return _nonceLoader;\n}\n\nexport interface PalNonceOptions {\n  videoWidth?: number;\n  videoHeight?: number;\n  descriptionUrl?: string;\n  ppid?: string;\n  sessionId?: string;\n  adWillAutoPlay?: boolean;\n  adWillPlayMuted?: boolean;\n  playerVolume?: number;\n  continuousPlayback?: boolean;\n}\n\nexport interface PalNonceManager {\n  generateNonce(options?: PalNonceOptions): Promise<string>;\n\n  getCurrentNonce(): string;\n\n  injectNonce(vastTagUrl: string): string;\n\n  sendPlaybackStart(): void;\n\n  sendPlaybackEnd(): void;\n\n  sendAdClick(): void;\n\n  sendAdTouch(event: MouseEvent | TouchEvent): void;\n\n  reset(): void;\n}\n\nexport function createPalNonceManager(): PalNonceManager {\n  let currentNonce = \"\";\n  let currentNonceManager: any | undefined;\n\n  return {\n    async generateNonce(options: PalNonceOptions = {}): Promise<string> {\n      try {\n        await loadPalSdk();\n\n        const loader = getOrCreateNonceLoader();\n        const goog = window.goog;\n\n        const request = new goog.pal.NonceRequest();\n        request.adWillAutoPlay = options.adWillAutoPlay ?? true;\n        request.adWillPlayMuted = options.adWillPlayMuted ?? false;\n        request.playerVolume =\n          options.playerVolume ?? (request.adWillPlayMuted ? 0 : 1);\n        request.continuousPlayback = options.continuousPlayback ?? true;\n        request.descriptionUrl = toDevSafeUrl(\n          options.descriptionUrl ||\n            (typeof window !== \"undefined\" ? window.location.href : \"\")\n        );\n        request.iconsSupported = true;\n        request.playerType = \"StormcloudVideoPlayer\";\n        request.playerVersion = \"1.0\";\n        request.supportedApiFrameworks = \"2,7,9\";\n        request.url = toDevSafeUrl(\n          options.descriptionUrl ||\n            (typeof window !== \"undefined\" ? window.location.href : \"\")\n        );\n        request.videoWidth = options.videoWidth || 640;\n        request.videoHeight = options.videoHeight || 480;\n\n        if (options.ppid) request.ppid = options.ppid;\n        if (options.sessionId) request.sessionId = options.sessionId;\n\n        console.log(\n          \"[PAL] NonceRequest before generateNonce:\",\n          JSON.stringify({\n            adWillAutoPlay: request.adWillAutoPlay,\n            adWillPlayMuted: request.adWillPlayMuted,\n            playerVolume: request.playerVolume,\n            continuousPlayback: request.continuousPlayback,\n            descriptionUrl: request.descriptionUrl,\n            iconsSupported: request.iconsSupported,\n            playerType: request.playerType,\n            playerVersion: request.playerVersion,\n            supportedApiFrameworks: request.supportedApiFrameworks,\n            url: request.url,\n            videoWidth: request.videoWidth,\n            videoHeight: request.videoHeight,\n            ppid: request.ppid,\n            sessionId: request.sessionId,\n          }, null, 2)\n        );\n\n        const manager = await loader.loadNonceManager(request);\n        currentNonceManager = manager;\n        currentNonce = manager.getNonce() as string;\n\n        console.log(\"[PAL] Nonce generated successfully\");\n        return currentNonce;\n      } catch (error) {\n        console.warn(\"[PAL] Failed to generate nonce:\", error);\n        currentNonce = \"\";\n        currentNonceManager = undefined;\n        return \"\";\n      }\n    },\n\n    getCurrentNonce(): string {\n      return currentNonce;\n    },\n\n    injectNonce(vastTagUrl: string): string {\n      if (!currentNonce || !vastTagUrl) return vastTagUrl;\n\n      try {\n        const url = new URL(vastTagUrl);\n        url.searchParams.delete(\"paln\");\n        url.searchParams.set(\"givn\", currentNonce);\n        return url.toString();\n      } catch {\n        let base = vastTagUrl\n          .replace(/([?&])paln=[^&]*/g, \"\")\n          .replace(/[?&]$/, \"\");\n        const sep = base.includes(\"?\") ? \"&\" : \"?\";\n        return `${base}${sep}givn=${encodeURIComponent(currentNonce)}`;\n      }\n    },\n\n    sendPlaybackStart(): void {\n      try {\n        currentNonceManager?.sendPlaybackStart();\n      } catch {}\n    },\n\n    sendPlaybackEnd(): void {\n      try {\n        currentNonceManager?.sendPlaybackEnd();\n      } catch {}\n    },\n\n    sendAdClick(): void {\n      try {\n        currentNonceManager?.sendAdClick();\n      } catch {}\n    },\n\n    sendAdTouch(event: MouseEvent | TouchEvent): void {\n      try {\n        currentNonceManager?.sendAdTouch(event);\n      } catch {}\n    },\n\n    reset(): void {\n      currentNonce = \"\";\n      currentNonceManager = undefined;\n    },\n  };\n}\n","import mqtt from \"mqtt\";\nimport type { MqttClient } from \"mqtt\";\nimport {\n  applyMQTTConfig,\n  buildMQTTBrokerUrl,\n  isMQTTEnabled,\n  mqttConfig,\n} from \"./mqttConfig\";\nimport type { MQTTConfig } from \"./mqttConfig\";\n\nconst LOG = \"[StormcloudVideoPlayer][MQTT]\";\n\nconst KEEPALIVE_SECONDS = 30;\nconst CONNECT_TIMEOUT_MS = 10_000;\n\nconst RECONNECT_BASE_MS = 5_000;\nconst RECONNECT_MAX_MS = 60_000;\nconst MAX_RECONNECT_ATTEMPTS = 8;\nconst COOLDOWN_MS = 10 * 60_000;\n\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\nlet reconnectAttempts = 0;\nlet reconnectTimer: ReturnType<typeof setTimeout> | null = null;\nlet stopped = false;\n\nexport function getMQTTStatus(): MQTTStatus {\n  return status;\n}\n\nexport function isMQTTConnected(): boolean {\n  return status === \"connected\" && client !== null && client.connected;\n}\n\nexport function isMQTTConfigured(): boolean {\n  return isMQTTEnabled();\n}\n\nexport function configureMQTT(overrides: Partial<MQTTConfig>): void {\n  applyMQTTConfig(overrides);\n  disconnectMQTT();\n}\n\nfunction clearReconnectTimer(): void {\n  if (reconnectTimer) {\n    clearTimeout(reconnectTimer);\n    reconnectTimer = null;\n  }\n}\n\nfunction teardownClient(): void {\n  if (client) {\n    try {\n      client.removeAllListeners();\n      client.end(true);\n    } catch {\n      // ignore teardown errors\n    }\n    client = null;\n  }\n}\n\nfunction scheduleReconnect(): void {\n  if (stopped || !isMQTTEnabled() || reconnectTimer) return;\n\n  if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n    console.warn(\n      `${LOG} giving up after ${reconnectAttempts} attempts; cooling down for ${\n        COOLDOWN_MS / 60_000\n      }m`\n    );\n    teardownClient();\n    status = \"disconnected\";\n    reconnectTimer = setTimeout(() => {\n      reconnectTimer = null;\n      reconnectAttempts = 0;\n      openConnection();\n    }, COOLDOWN_MS);\n    return;\n  }\n\n  const delay = Math.min(\n    RECONNECT_MAX_MS,\n    RECONNECT_BASE_MS * 2 ** reconnectAttempts\n  );\n  const jitter = Math.floor(Math.random() * 1_000);\n  reconnectAttempts += 1;\n\n  reconnectTimer = setTimeout(() => {\n    reconnectTimer = null;\n    openConnection();\n  }, delay + jitter);\n}\n\nfunction openConnection(): void {\n  if (stopped || !isMQTTEnabled()) return;\n\n  teardownClient();\n\n  const url = buildMQTTBrokerUrl();\n  status = \"connecting\";\n\n  const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n\n  try {\n    client = mqtt.connect(url, {\n      clientId,\n      username: mqttConfig.username,\n      password: mqttConfig.password,\n      keepalive: KEEPALIVE_SECONDS,\n      clean: true,\n      // Disable MQTT.js internal reconnect; we manage reconnection ourselves.\n      reconnectPeriod: 0,\n      connectTimeout: CONNECT_TIMEOUT_MS,\n      queueQoSZero: false,\n      reschedulePings: true,\n      // Root-cause fix for the Tizen 4.0 \"Keepalive timeout\" loop: MQTT.js's\n      // default timerVariant \"auto\" runs the keepalive interval inside a\n      // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old\n      // WebKit) served from a file:// origin that worker can't tick reliably,\n      // so the keepalive counter trips onKeepaliveTimeout almost immediately\n      // after connect. Force the native setInterval timer instead; the main\n      // thread is free because video is decoded by the native AVPlay pipeline.\n      timerVariant: \"native\",\n    });\n  } catch (err) {\n    status = \"error\";\n    console.warn(`${LOG} connect() threw:`, err);\n    scheduleReconnect();\n    return;\n  }\n\n  client.on(\"connect\", () => {\n    status = \"connected\";\n    reconnectAttempts = 0;\n    clearReconnectTimer();\n    console.info(`${LOG} connected to ${url}`);\n  });\n\n  client.on(\"offline\", () => {\n    if (status === \"connected\") status = \"disconnected\";\n    console.warn(`${LOG} offline`);\n    scheduleReconnect();\n  });\n\n  client.on(\"error\", (err) => {\n    status = \"error\";\n    console.warn(`${LOG} error:`, err.message);\n    scheduleReconnect();\n  });\n\n  client.on(\"close\", () => {\n    if (status === \"connected\") status = \"disconnected\";\n    scheduleReconnect();\n  });\n}\n\nexport function initMQTTClient(): void {\n  if (client || !isMQTTEnabled()) return;\n  stopped = false;\n  reconnectAttempts = 0;\n  openConnection();\n}\n\nexport function ensureMQTTClient(): void {\n  if (isMQTTEnabled() && !client && !reconnectTimer) {\n    initMQTTClient();\n  }\n}\n\nexport function publishMQTT(\n  topic: string,\n  payload: Record<string, unknown>\n): boolean {\n  if (!isMQTTEnabled()) {\n    return false;\n  }\n\n  ensureMQTTClient();\n\n  if (!client || !client.connected) {\n    return false;\n  }\n\n  try {\n    client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n    return true;\n  } catch (err) {\n    console.warn(`${LOG} publish failed on ${topic}:`, err);\n    return false;\n  }\n}\n\nexport function disconnectMQTT(): void {\n  stopped = true;\n  clearReconnectTimer();\n  teardownClient();\n  reconnectAttempts = 0;\n  status = \"disconnected\";\n}\n","export const MQTT_CA_CERT_FILE = \"src/certs/emqxsl-ca.crt\";\n\nexport type MQTTConfig = {\n  enabled: boolean;\n  brokerAddress: string;\n  brokerPort: number;\n  wsPort: number;\n  username: string;\n  password: string;\n  topicPrefix: string;\n  qos: 0 | 1 | 2;\n  brokerUrl?: string;\n};\n\nexport const DEFAULT_MQTT_CONFIG: MQTTConfig = {\n  enabled: true,\n  brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n  brokerPort: 8883,\n  wsPort: 8084,\n  username: \"for-sonifi\",\n  password: \"sonifi-mqtt\",\n  topicPrefix: \"adstorm/players\",\n  qos: 1,\n};\n\nexport const mqttConfig: MQTTConfig = { ...DEFAULT_MQTT_CONFIG };\n\nexport function applyMQTTConfig(overrides: Partial<MQTTConfig>): void {\n  Object.assign(mqttConfig, overrides);\n}\n\nexport function isMQTTEnabled(): boolean {\n  return mqttConfig.enabled;\n}\n\nexport function buildMQTTBrokerUrl(): string {\n  if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n  return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\nexport function buildPlayerTopic(\n  licenseKey: string,\n  channel: \"metrics\" | \"impressions\" | \"heartbeat\"\n): string {\n  return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n","export interface VastEnvironmentSignals {\n  isCtv: boolean;\n  contentUrl?: string;\n  appId?: string;\n  appName?: string;\n  sessionId?: string;\n  deviceId?: string;\n  deviceIdType?: string;\n  limitAdTracking?: boolean;\n  deviceTypeHint?: number;\n}\n\nconst AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nconst AIRY_WEBOS_APP_ID    = \"com.freeairytv.webos\";\nconst AIRY_TIZEN_APP_ID    = \"com.freeairytv.samsung\";\nconst AIRY_ROKU_APP_ID     = \"com.freeairytv.roku\";\nconst AIRY_APP_NAME = \"AiryTV Movies & TV\";\nconst AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nconst CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\nexport const PLAYER_ID_STORAGE_KEY = \"stormcloud.player.id\";\n\nconst LG_TEST_APP_ID      = \"com.hulu.plus\";\nconst LG_TEST_APP_NAME    = \"Hulu\";\nconst LG_TEST_CONTENT_URL = \"https://www.hulu.com/live-tv\";\n\nlet _lgTestDeviceId: string | undefined;\nfunction getLgTestDeviceId(): string {\n  if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();\n  return _lgTestDeviceId;\n}\n\nfunction isLgWebOS(): boolean {\n  if (typeof navigator === \"undefined\") return false;\n  return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);\n}\n\nfunction getDefaultAppId(): string {\n  if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n  const ua = navigator.userAgent;\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n  if (/Tizen|Samsung/i.test(ua))                       return AIRY_TIZEN_APP_ID;\n  if (/Roku/i.test(ua))                                return AIRY_ROKU_APP_ID;\n  return AIRY_ANDROID_APP_ID;\n}\n\nconst DEVICE_ID_STORAGE_KEYS = [\n  \"rdid\",\n  \"ifa\",\n  \"advertisingId\",\n  \"advertising_id\",\n  \"deviceAdvertisingId\",\n  \"aaid\",\n  \"adid\",\n  \"rida\",\n  \"tifa\",\n  \"lgudid\",\n];\n\nconst ANDROID_ID_TYPES = new Set([\"aaid\", \"adid\"]);\n\nexport function resolveVastEnvironmentSignals(isCtv: boolean): VastEnvironmentSignals {\n  const bridgeSignals  = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const lg = isCtv && isLgWebOS();\n\n  const deviceId =\n    bridgeSignals.deviceId  ||\n    readStoredDeviceId()    ||\n    platformDevice.deviceId ||\n    (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : undefined);\n  const deviceIdType =\n    bridgeSignals.deviceIdType  ||\n    readStoredString(\"deviceIdType\") ||\n    readStoredString(\"idtype\") ||\n    platformDevice.deviceIdType ||\n    inferDeviceIdType() ||\n    (lg ? \"lgudid\" : undefined);\n  const platformLat = bridgeSignals.deviceId\n    ? bridgeSignals.limitAdTracking\n    : platformDevice.limitAdTracking;\n  const limitAdTracking =\n    deviceId != null\n      ? platformLat ?? readStoredLimitAdTracking() ?? false\n      : undefined;\n\n  if (isCtv) {\n    return {\n      isCtv: true,\n      contentUrl:\n        bridgeSignals.contentUrl ||\n        readStoredString(\"contentUrl\") ||\n        (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),\n      appId:\n        bridgeSignals.appId ||\n        readStoredString(\"appId\") ||\n        readStoredString(\"msid\") ||\n        (lg ? LG_TEST_APP_ID : getDefaultAppId()),\n      appName:\n        bridgeSignals.appName ||\n        readStoredString(\"appName\") ||\n        readStoredString(\"an\") ||\n        (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),\n      sessionId: getOrCreateCtvSessionId(),\n      ...(deviceId ? { deviceId } : {}),\n      ...(deviceIdType ? { deviceIdType } : {}),\n      ...(limitAdTracking != null ? { limitAdTracking } : {}),\n      deviceTypeHint: 5,\n    };\n  }\n\n  return {\n    isCtv: false,\n    ...(deviceId ? { deviceId } : {}),\n    ...(deviceIdType ? { deviceIdType } : {}),\n    ...(limitAdTracking != null ? { limitAdTracking } : {}),\n  };\n}\n\nexport function inferDeviceIdType(): string | undefined {\n  if (typeof navigator === \"undefined\") {\n    return undefined;\n  }\n\n  const ua = navigator.userAgent;\n  if (/Roku/i.test(ua)) return \"rida\";\n  if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n  if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n  if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n  if (/Android|Google TV/i.test(ua)) return \"aaid\";\n  if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n  return undefined;\n}\n\nexport function isEquivalentDeviceIdType(\n  tagType: string | undefined,\n  runtimeType: string | undefined\n): boolean {\n  if (!tagType || !runtimeType) return false;\n  const tag = tagType.toLowerCase();\n  const runtime = runtimeType.toLowerCase();\n  if (tag === runtime) return true;\n  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\n\nexport function resolveNativeDeviceId(): string | undefined {\n  const bridgeSignals = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const deviceId =\n    bridgeSignals.deviceId ||\n    readStoredDeviceId() ||\n    platformDevice.deviceId;\n\n  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {\n    return undefined;\n  }\n\n  return deviceId;\n}\n\nexport function getOrCreateStoredUuid(storageKey: string): string | undefined {\n  if (typeof window === \"undefined\") {\n    return undefined;\n  }\n\n  const existing = readPersistentId(storageKey);\n  if (existing) {\n    writePersistentId(storageKey, existing);\n    return existing;\n  }\n\n  const id = createUuid();\n  writePersistentId(storageKey, id);\n  return id;\n}\n\nfunction getOrCreateCtvSessionId(): string {\n  const existing = readPersistentId(CTV_SESSION_STORAGE_KEY);\n  if (existing) {\n    writePersistentId(CTV_SESSION_STORAGE_KEY, existing);\n    return existing;\n  }\n\n  const sessionId = createUuid();\n  writePersistentId(CTV_SESSION_STORAGE_KEY, sessionId);\n  return sessionId;\n}\n\nfunction readPersistentId(storageKey: string): string | undefined {\n  return readStoredString(storageKey) || readCookie(storageKey);\n}\n\nfunction writePersistentId(storageKey: string, value: string): void {\n  try {\n    window.localStorage?.setItem(storageKey, value);\n  } catch {}\n  writeCookie(storageKey, value);\n}\n\nconst PERSISTENT_ID_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5; // ~5 years\n\nfunction readCookie(name: string): string | undefined {\n  if (typeof document === \"undefined\") {\n    return undefined;\n  }\n\n  try {\n    const prefix = encodeURIComponent(name) + \"=\";\n    const parts = document.cookie ? document.cookie.split(\";\") : [];\n    for (const part of parts) {\n      const entry = part.trim();\n      if (entry.startsWith(prefix)) {\n        return decodeURIComponent(entry.slice(prefix.length)) || undefined;\n      }\n    }\n  } catch {}\n\n  return undefined;\n}\n\nfunction writeCookie(name: string, value: string): void {\n  if (typeof document === \"undefined\") {\n    return;\n  }\n\n  try {\n    document.cookie =\n      encodeURIComponent(name) +\n      \"=\" +\n      encodeURIComponent(value) +\n      \";path=/;max-age=\" +\n      PERSISTENT_ID_COOKIE_MAX_AGE +\n      \";SameSite=Lax\";\n  } catch {}\n}\n\nfunction createUuid(): string {\n  if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n\n  const bytes = new Uint8Array(16);\n  if (typeof crypto !== \"undefined\" && typeof crypto.getRandomValues === \"function\") {\n    crypto.getRandomValues(bytes);\n  } else {\n    let seed = Date.now() ^ Math.floor(performanceNow() * 1e3);\n    for (let i = 0; i < 16; i++) {\n      seed = (seed * 1103515245 + 12345) & 0x7fffffff;\n      bytes[i] = (seed ^ Math.floor(Math.random() * 256)) & 0xff;\n    }\n  }\n\n  bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;\n  bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;\n\n  let hex = \"\";\n  for (let i = 0; i < 16; i++) {\n    hex += (bytes[i] ?? 0).toString(16).padStart(2, \"0\");\n  }\n\n  return (\n    hex.slice(0, 8) +\n    \"-\" +\n    hex.slice(8, 12) +\n    \"-\" +\n    hex.slice(12, 16) +\n    \"-\" +\n    hex.slice(16, 20) +\n    \"-\" +\n    hex.slice(20, 32)\n  );\n}\n\nfunction performanceNow(): number {\n  try {\n    if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n      return performance.now();\n    }\n  } catch {}\n  return 0;\n}\n\nfunction readPlatformNativeDeviceId(): {\n  deviceId?: string;\n  deviceIdType?: string;\n  limitAdTracking?: boolean;\n} {\n  if (typeof window === \"undefined\") return {};\n\n  try {\n    const adinfo = (window as any).webapis?.adinfo;\n    if (adinfo) {\n      const tifa: unknown =\n        typeof adinfo.getTIFA === \"function\" ? adinfo.getTIFA() : adinfo.tifa;\n      if (typeof tifa === \"string\" && tifa && !isMacroPlaceholder(tifa)) {\n        const lat: unknown =\n          typeof adinfo.isLATEnabled === \"function\"\n            ? adinfo.isLATEnabled()\n            : undefined;\n        return {\n          deviceId: tifa,\n          deviceIdType: \"tifa\",\n          ...(typeof lat === \"boolean\" ? { limitAdTracking: lat } : {}),\n        };\n      }\n    }\n  } catch {}\n\n  try {\n    const webOSDev = (window as any).webOSDev;\n    if (webOSDev) {\n      const lgudid: unknown =\n        typeof webOSDev.LGUDID === \"function\"\n          ? webOSDev.LGUDID()\n          : webOSDev.lgudid ?? webOSDev.LGUDID;\n      if (typeof lgudid === \"string\" && lgudid) {\n        if (isZeroedAdId(lgudid)) {\n          return { deviceIdType: \"lgudid\", limitAdTracking: true };\n        }\n        if (!isMacroPlaceholder(lgudid)) {\n          return { deviceId: lgudid, deviceIdType: \"lgudid\", limitAdTracking: false };\n        }\n      }\n    }\n  } catch {}\n\n  try {\n    const roku = (window as any).Roku;\n    if (roku) {\n      const rida: unknown =\n        typeof roku.getPublisherUniqueId === \"function\"\n          ? roku.getPublisherUniqueId()\n          : roku.rida;\n      if (typeof rida === \"string\" && rida && !isMacroPlaceholder(rida)) {\n        return { deviceId: rida, deviceIdType: \"rida\", limitAdTracking: false };\n      }\n    }\n  } catch {}\n\n  return {};\n}\n\nconst ZEROED_AD_ID_PATTERNS: ReadonlySet<string> = new Set([\n  \"38400000-8cf0-11bd-b23e-10b96e40000d\",\n  \"00000000-0000-0000-0000-000000000000\",\n]);\n\nfunction isMacroPlaceholder(value: string): boolean {\n  const t = value.trim();\n  return !t ||\n    /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/.test(t) ||\n    /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(t) ||\n    ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());\n}\n\nfunction isZeroedAdId(value: string): boolean {\n  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());\n}\n\nfunction readNativeBridgeSignals(): {\n  contentUrl?: string;\n  appId?: string;\n  appName?: string;\n  deviceId?: string;\n  deviceIdType?: string;\n  limitAdTracking?: boolean;\n} {\n  if (typeof window === \"undefined\") {\n    return {};\n  }\n\n  const candidates = [\n    (window as any).__STORMCLOUD_CTV_AD_INFO__,\n    (window as any).__STORMCLOUD_CTV__,\n    (window as any).stormcloudCtv,\n    (window as any).AiryTV,\n    (window as any).Android,\n    (window as any).webOS,\n    (window as any).tizen,\n    (window as any).amazon,\n  ].filter(Boolean);\n\n  for (const source of candidates) {\n    const contentUrl =\n      readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) ||\n      undefined;\n    const appId =\n      readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) ||\n      undefined;\n    const appName =\n      readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || undefined;\n    const deviceId =\n      readBridgeValue(source, [\n        \"rdid\",\n        \"ifa\",\n        \"advertisingId\",\n        \"adId\",\n        \"deviceId\",\n        \"lgudid\",\n        \"LGUDID\",\n        \"tifa\",\n        \"rida\",\n        \"afai\",\n        \"aaid\",\n      ]) || undefined;\n\n    if (!contentUrl && !deviceId && !appId && !appName) continue;\n\n    const deviceIdType =\n      readBridgeValue(source, [\n        \"idtype\",\n        \"deviceIdType\",\n        \"advertisingIdType\",\n        \"idType\",\n      ]) || inferDeviceIdType();\n    const limitAdTracking = readBridgeBoolean(source, [\n      \"is_lat\",\n      \"limitAdTracking\",\n      \"limitedAdTracking\",\n      \"lat\",\n    ]);\n\n    return {\n      ...(contentUrl ? { contentUrl } : {}),\n      ...(appId ? { appId } : {}),\n      ...(appName ? { appName } : {}),\n      ...(deviceId ? { deviceId } : {}),\n      ...(deviceId && deviceIdType ? { deviceIdType } : {}),\n      ...(deviceId && limitAdTracking != null ? { limitAdTracking } : {}),\n    };\n  }\n\n  return {};\n}\n\nfunction readBridgeValue(source: any, keys: string[]): string | undefined {\n  for (const key of keys) {\n    const value = source?.[key];\n    if (typeof value === \"string\" && value) {\n      return value;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = value.call(source);\n        if (typeof result === \"string\" && result) {\n          return result;\n        }\n      } catch {}\n    }\n  }\n  return undefined;\n}\n\nfunction readBridgeBoolean(source: any, keys: string[]): boolean | undefined {\n  for (const key of keys) {\n    const value = source?.[key];\n    const normalized = normalizeBoolean(value);\n    if (normalized != null) {\n      return normalized;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = normalizeBoolean(value.call(source));\n        if (result != null) {\n          return result;\n        }\n      } catch {}\n    }\n  }\n  return undefined;\n}\n\nfunction readStoredDeviceId(): string | undefined {\n  for (const key of DEVICE_ID_STORAGE_KEYS) {\n    const value = readStoredString(key);\n    if (value) {\n      return value;\n    }\n  }\n  return undefined;\n}\n\nfunction readStoredString(key: string): string | undefined {\n  if (typeof window === \"undefined\") {\n    return undefined;\n  }\n\n  try {\n    const value = window.localStorage?.getItem(key);\n    return value || undefined;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction readStoredLimitAdTracking(): boolean | undefined {\n  return normalizeBoolean(\n    readStoredString(\"limitAdTracking\") ||\n      readStoredString(\"limitedAdTracking\") ||\n      readStoredString(\"is_lat\")\n  );\n}\n\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n  if (typeof value === \"boolean\") {\n    return value;\n  }\n  if (typeof value === \"number\") {\n    return value === 1;\n  }\n  if (typeof value === \"string\") {\n    const normalized = value.toLowerCase();\n    if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n      return true;\n    }\n    if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n      return false;\n    }\n  }\n  return undefined;\n}\n","import type {\n  ClientInfo,\n  AdDetectInfo,\n  AdLoadedInfo,\n  AdImpressionInfo,\n  PlayerAnalyticsContext,\n  StormcloudVideoPlayerConfig,\n} from \"../types\";\n\nimport { buildPlayerTopic, isMQTTEnabled } from \"./mqttConfig\";\nimport { ensureMQTTClient, publishMQTT } from \"./mqttClient\";\nimport {\n  getOrCreateStoredUuid,\n  PLAYER_ID_STORAGE_KEY,\n  resolveNativeDeviceId,\n} from \"./vastEnvironmentSignals\";\n\nlet cachedBrowserId: string | null = null;\n\nexport function buildAnalyticsContext(\n  config: Pick<StormcloudVideoPlayerConfig, \"debugAdTiming\" | \"isLiveStream\">\n): PlayerAnalyticsContext {\n  const context: PlayerAnalyticsContext = {};\n  if (config.debugAdTiming) {\n    context.debugAdTiming = true;\n  }\n  if (config.isLiveStream !== undefined) {\n    context.inputStreamType = config.isLiveStream ? \"live\" : \"vod\";\n  }\n  return context;\n}\n\nexport function getClientInfo(): ClientInfo {\n  const ua = navigator.userAgent;\n  const platform = navigator.platform;\n  const vendor = navigator.vendor || \"\";\n  const maxTouchPoints = navigator.maxTouchPoints || 0;\n  const memory = (navigator as any).deviceMemory || null;\n  const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n\n  const screenInfo = {\n    width: screen?.width,\n    height: screen?.height,\n    availWidth: screen?.availWidth,\n    availHeight: screen?.availHeight,\n    orientation: (screen?.orientation as any)?.type || \"\",\n    pixelDepth: screen?.pixelDepth,\n  };\n\n  let deviceType: \"tv\" | \"mobile\" | \"tablet\" | \"desktop\" = \"desktop\";\n  let brand = \"Unknown\";\n  let os = \"Unknown\";\n  let model = \"\";\n  let isSmartTV = false;\n  let isAndroid = false;\n  let isWebView = false;\n  let isWebApp = false;\n\n  if (ua.includes(\"Web0S\")) {\n    brand = \"LG\";\n    os = \"webOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n    model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n  } else if (ua.includes(\"Tizen\")) {\n    brand = \"Samsung\";\n    os = \"Tizen\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n    const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n    model = tizenMatch\n      ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()\n      : \"Tizen TV\";\n  } else if (ua.includes(\"Philips\")) {\n    brand = \"Philips\";\n    os = \"Saphi\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n    brand = \"Sharp\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (\n    ua.includes(\"Android\") &&\n    (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))\n  ) {\n    brand = \"Sony\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (\n    ua.includes(\"Android\") &&\n    (ua.includes(\"NetCast\") || ua.includes(\"LG\"))\n  ) {\n    brand = \"LG\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n    brand = \"Roku\";\n    os = \"Roku OS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"AppleTV\")) {\n    brand = \"Apple\";\n    os = \"tvOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  }\n\n  if (ua.includes(\"Android\")) {\n    isAndroid = true;\n    os = \"Android\";\n    deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n\n    if (\n      ua.includes(\"Android\") &&\n      (maxTouchPoints === 0 ||\n        ua.includes(\"Google TV\") ||\n        ua.includes(\"XiaoMi\"))\n    ) {\n      deviceType = \"tv\";\n      isSmartTV = true;\n      brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n    }\n\n    const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n    if (androidModelMatch && androidModelMatch[1]) {\n      model = androidModelMatch[1];\n    }\n  }\n\n  if (/iPad|iPhone|iPod/.test(ua)) {\n    os = \"iOS\";\n    deviceType = \"mobile\";\n    brand = \"Apple\";\n    if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n      deviceType = \"tablet\";\n    }\n  }\n\n  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n    if (ua.includes(\"Windows\")) {\n      os = \"Windows\";\n      deviceType = \"desktop\";\n    } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n      os = \"macOS\";\n      deviceType = \"desktop\";\n      if (maxTouchPoints > 1) deviceType = \"tablet\";\n    } else if (ua.includes(\"Linux\")) {\n      os = \"Linux\";\n      deviceType = \"desktop\";\n    }\n  }\n\n  if (brand === \"Unknown\") {\n    if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n    if (vendor.includes(\"Apple\")) brand = \"Apple\";\n    if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n  }\n\n  isWebView = /wv|WebView|Linux; U;/.test(ua);\n\n  if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n    isWebView = true;\n  }\n\n  isWebApp =\n    window.matchMedia(\"(display-mode: standalone)\").matches ||\n    (window.navigator as any).standalone === true ||\n    window.screen?.orientation?.angle !== undefined;\n\n  return {\n    brand,\n    os,\n    model: model || ua.substring(0, 50) + \"...\",\n    deviceType,\n    isSmartTV,\n    isAndroid,\n    isWebView,\n    isWebApp,\n    domain: window.location.hostname,\n    origin: window.location.origin,\n    path: window.location.pathname,\n    userAgent: ua,\n    vendor,\n    platform,\n    screen: screenInfo,\n    hardwareConcurrency,\n    deviceMemory: memory,\n    maxTouchPoints,\n    language: navigator.language,\n    languages: navigator.languages?.join(\",\") || \"\",\n    cookieEnabled: navigator.cookieEnabled,\n    doNotTrack: navigator.doNotTrack || \"\",\n    referrer: document.referrer,\n    visibilityState: document.visibilityState,\n  };\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n  if (typeof crypto !== \"undefined\" && crypto.subtle?.digest) {\n    try {\n      await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n\n      let encodedData: BufferSource;\n      if (typeof TextEncoder !== \"undefined\") {\n        encodedData = new TextEncoder().encode(input);\n      } else {\n        const utf8 = unescape(encodeURIComponent(input));\n        const buffer = new Uint8Array(utf8.length);\n        for (let i = 0; i < utf8.length; i++) {\n          buffer[i] = utf8.charCodeAt(i);\n        }\n        encodedData = buffer;\n      }\n\n      const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n      return Array.from(new Uint8Array(hashBuffer))\n        .map((b) => b.toString(16).padStart(2, \"0\"))\n        .join(\"\");\n    } catch {\n      console.warn(\n        \"[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash\"\n      );\n    }\n  }\n\n  let hash = 0;\n  for (let i = 0; i < input.length; i++) {\n    const char = input.charCodeAt(i);\n    hash = (hash << 5) - hash + char;\n    hash = hash & hash;\n  }\n\n  const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n  const timestamp = Date.now().toString(16).padStart(12, \"0\");\n  const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n\n  return (fallbackHash + timestamp + random).padEnd(64, \"0\");\n}\n\nfunction resolvePlayerIdentitySeed(clientInfo: ClientInfo): string {\n  const nativeDeviceId = resolveNativeDeviceId();\n  if (nativeDeviceId) {\n    return `device:${nativeDeviceId}`;\n  }\n\n  const persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);\n  if (persistedId) {\n    return `persisted:${persistedId}`;\n  }\n\n  return `fingerprint:${JSON.stringify(clientInfo)}`;\n}\n\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n  if (cachedBrowserId) {\n    return cachedBrowserId;\n  }\n\n  cachedBrowserId = await sha256Hex(resolvePlayerIdentitySeed(clientInfo));\n  return cachedBrowserId;\n}\n\ntype PlayerMetricFlags = {\n  adLoaded?: boolean;\n  adDetect?: boolean;\n  captureAt?: string;\n};\n\nfunction canPublish(licenseKey: string | undefined): licenseKey is string {\n  return Boolean(isMQTTEnabled() && licenseKey);\n}\n\nasync function buildPlayerMetricEvent(\n  context: PlayerAnalyticsContext = {},\n  flags: PlayerMetricFlags = {}\n): Promise<Record<string, unknown>> {\n  const clientInfo = getClientInfo();\n\n  const debugAdTiming = !!context.debugAdTiming;\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] clientInfo: \", JSON.stringify(clientInfo, null, 2));\n  }\n\n  const playerId = await getBrowserID(clientInfo);\n\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] playerId: \", playerId);\n  }\n\n  const captureAt = flags.captureAt ?? new Date().toISOString();\n\n  return {\n    player_id: playerId,\n    device_type: clientInfo.deviceType,\n    os: clientInfo.os.toLowerCase(),\n    ad_loaded: flags.adLoaded ?? false,\n    ad_detect: flags.adDetect ?? false,\n    capture_at: captureAt,\n    ...(context.inputStreamType\n      ? { input_stream_type: context.inputStreamType }\n      : {}),\n  };\n}\n\nfunction publishTracking(\n  licenseKey: string,\n  channel: \"metrics\" | \"impressions\" | \"heartbeat\",\n  body: Record<string, unknown>\n): void {\n  ensureMQTTClient();\n  publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\n\nexport async function sendInitialTracking(\n  licenseKey?: string,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  if (!canPublish(licenseKey)) return;\n\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      adLoaded: false,\n      adDetect: false,\n    });\n\n    publishTracking(licenseKey, \"metrics\", {\n      events: [metricEvent],\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n      error\n    );\n  }\n}\n\nexport async function sendAdDetectTracking(\n  licenseKey: string | undefined,\n  adDetectInfo: AdDetectInfo,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  try {\n    await sendHeartbeat(licenseKey, context, {\n      adDetect: true,\n      captureAt: adDetectInfo.timestamp,\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n      error\n    );\n  }\n}\n\nexport async function sendAdLoadedTracking(\n  licenseKey: string | undefined,\n  adLoadedInfo: AdLoadedInfo,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  try {\n    await sendHeartbeat(licenseKey, context, {\n      adLoaded: true,\n      captureAt: adLoadedInfo.timestamp,\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n      error\n    );\n  }\n}\n\nexport async function sendAdImpressionTracking(\n  licenseKey: string | undefined,\n  adImpressionInfo: AdImpressionInfo,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  if (!canPublish(licenseKey)) return;\n\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      captureAt: adImpressionInfo.timestamp,\n    });\n\n    publishTracking(licenseKey, \"heartbeat\", metricEvent);\n    publishTracking(licenseKey, \"impressions\", {\n      events: [\n        {\n          player_id: metricEvent.player_id,\n          ad_played_count: 1,\n          ad_url: adImpressionInfo.adUrl,\n          capture_at: adImpressionInfo.timestamp,\n        },\n      ],\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n      error\n    );\n  }\n}\n\nexport async function sendHeartbeat(\n  licenseKey?: string,\n  context: PlayerAnalyticsContext = {},\n  flags: PlayerMetricFlags = {}\n): Promise<void> {\n  if (!canPublish(licenseKey)) return;\n\n  try {\n    const heartbeatData = await buildPlayerMetricEvent(context, flags);\n    publishTracking(licenseKey, \"heartbeat\", heartbeatData);\n  } catch (error) {\n    console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n  }\n}\n","export function polyfillURLSearchParams(): void {\n  if (typeof URLSearchParams !== 'undefined') {\n    return;\n  }\n\n  class URLSearchParamsPolyfill {\n    private params: Map<string, string[]>;\n\n    constructor(init?: string | URLSearchParamsPolyfill) {\n      this.params = new Map();\n\n      if (typeof init === 'string') {\n        this.parseQueryString(init);\n      } else if (init instanceof URLSearchParamsPolyfill) {\n        init.forEach((value, key) => {\n          this.append(key, value);\n        });\n      }\n    }\n\n    private parseQueryString(query: string): void {\n      const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n      if (!cleanQuery) return;\n\n      cleanQuery.split('&').forEach((param) => {\n        const [key, value] = param.split('=');\n        if (key) {\n          const decodedKey = this.safeDecodeURIComponent(key);\n          const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n          this.append(decodedKey, decodedValue);\n        }\n      });\n    }\n\n    private safeDecodeURIComponent(str: string): string {\n      try {\n        return decodeURIComponent(str.replace(/\\+/g, ' '));\n      } catch (e) {\n        return str;\n      }\n    }\n\n    append(name: string, value: string): void {\n      const values = this.params.get(name) || [];\n      values.push(String(value));\n      this.params.set(name, values);\n    }\n\n    delete(name: string): void {\n      this.params.delete(name);\n    }\n\n    get(name: string): string | null {\n      const values = this.params.get(name);\n      return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n    }\n\n    getAll(name: string): string[] {\n      return this.params.get(name) || [];\n    }\n\n    has(name: string): boolean {\n      return this.params.has(name);\n    }\n\n    set(name: string, value: string): void {\n      this.params.set(name, [String(value)]);\n    }\n\n    forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n      this.params.forEach((values, key) => {\n        values.forEach((value) => {\n          callback(value, key, this);\n        });\n      });\n    }\n\n    toString(): string {\n      const parts: string[] = [];\n      this.params.forEach((values, key) => {\n        values.forEach((value) => {\n          parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n        });\n      });\n      return parts.join('&');\n    }\n  }\n\n  // @ts-ignore\n  window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n  if (typeof TextEncoder !== 'undefined') {\n    return;\n  }\n\n  class TextEncoderPolyfill {\n    encoding = 'utf-8';\n\n    encode(str: string): Uint8Array {\n      const utf8: number[] = [];\n      for (let i = 0; i < str.length; i++) {\n        let charcode = str.charCodeAt(i);\n        if (charcode < 0x80) {\n          utf8.push(charcode);\n        } else if (charcode < 0x800) {\n          utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n        } else if (charcode < 0xd800 || charcode >= 0xe000) {\n          utf8.push(\n            0xe0 | (charcode >> 12),\n            0x80 | ((charcode >> 6) & 0x3f),\n            0x80 | (charcode & 0x3f)\n          );\n        } else {\n          i++;\n          charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n          utf8.push(\n            0xf0 | (charcode >> 18),\n            0x80 | ((charcode >> 12) & 0x3f),\n            0x80 | ((charcode >> 6) & 0x3f),\n            0x80 | (charcode & 0x3f)\n          );\n        }\n      }\n      return new Uint8Array(utf8);\n    }\n  }\n\n  // @ts-ignore\n  window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n  if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n    Promise.prototype.finally = function (callback: () => void) {\n      const constructor = this.constructor as PromiseConstructor;\n      return this.then(\n        (value) => constructor.resolve(callback()).then(() => value),\n        (reason) =>\n          constructor.resolve(callback()).then(() => {\n            throw reason;\n          })\n      );\n    };\n  }\n}\n\nexport function polyfillObjectAssign(): void {\n  if (typeof Object.assign !== 'function') {\n    Object.assign = function (target: any, ...sources: any[]) {\n      if (target == null) {\n        throw new TypeError('Cannot convert undefined or null to object');\n      }\n\n      const to = Object(target);\n\n      for (let i = 0; i < sources.length; i++) {\n        const nextSource = sources[i];\n\n        if (nextSource != null) {\n          for (const nextKey in nextSource) {\n            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n              to[nextKey] = nextSource[nextKey];\n            }\n          }\n        }\n      }\n\n      return to;\n    };\n  }\n}\n\nexport function polyfillArrayFrom(): void {\n  if (!Array.from) {\n    Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n      const items = Object(arrayLike);\n      if (arrayLike == null) {\n        throw new TypeError('Array.from requires an array-like object');\n      }\n\n      const len = items.length >>> 0;\n      const result = new Array(len);\n\n      for (let i = 0; i < len; i++) {\n        if (mapFn) {\n          result[i] = mapFn.call(thisArg, items[i], i);\n        } else {\n          result[i] = items[i];\n        }\n      }\n\n      return result;\n    };\n  }\n}\n\nexport function polyfillStringStartsWith(): void {\n  if (!String.prototype.startsWith) {\n    String.prototype.startsWith = function (search: string, pos?: number) {\n      pos = !pos || pos < 0 ? 0 : +pos;\n      return this.substring(pos, pos + search.length) === search;\n    };\n  }\n}\n\nexport function polyfillStringEndsWith(): void {\n  if (!String.prototype.endsWith) {\n    String.prototype.endsWith = function (search: string, length?: number) {\n      if (length === undefined || length > this.length) {\n        length = this.length;\n      }\n      return this.substring(length - search.length, length) === search;\n    };\n  }\n}\n\nexport function polyfillStringIncludes(): void {\n  if (!String.prototype.includes) {\n    String.prototype.includes = function (search: string, start?: number) {\n      if (typeof start !== 'number') {\n        start = 0;\n      }\n      if (start + search.length > this.length) {\n        return false;\n      }\n      return this.indexOf(search, start) !== -1;\n    };\n  }\n}\n\nexport function initializePolyfills(): void {\n  polyfillObjectAssign();\n  polyfillArrayFrom();\n  polyfillStringStartsWith();\n  polyfillStringEndsWith();\n  polyfillStringIncludes();\n  polyfillURLSearchParams();\n  polyfillTextEncoder();\n  polyfillPromiseFinally();\n}\n\n","import {\n  inferDeviceIdType,\n  isEquivalentDeviceIdType,\n} from \"./vastEnvironmentSignals\";\n\nexport interface VastConsentSignals {\n  gdpr?: string | undefined;\n  gdprConsent?: string | undefined;\n  usPrivacy?: string | undefined;\n}\n\nexport interface VastMacroContext {\n  correlator: string;\n  streamCorrelator: string;\n  pod?: number | undefined;\n  podMaxAds?: number | undefined;\n  podMinDurationMs?: number | undefined;\n  podMaxDurationMs?: number | undefined;\n  isCtv?: boolean | undefined;\n  contentUrl?: string | undefined;\n  pageUrl?: string | undefined;\n  adWillPlayMuted?: boolean | undefined;\n  adWillAutoPlay?: boolean | undefined;\n  appId?: string | undefined;\n  appName?: string | undefined;\n  sessionId?: string | undefined;\n  deviceId?: string | undefined;\n  deviceIdType?: string | undefined;\n  limitAdTracking?: boolean | undefined;\n  deviceTypeHint?: number | undefined;\n  adTest?: boolean | undefined;\n  consent?: VastConsentSignals | undefined;\n}\n\nconst UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nconst INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nconst EXAMPLE_COM_URL = /example\\.com/i;\nconst CTV_UNSUPPORTED_PARAMS = [\n  \"description_url\",\n  \"tfcd\",\n  \"npa\",\n  \"min_ad_duration\",\n  \"max_ad_duration\",\n  \"unviewed_position_start\",\n  \"impl\",\n  \"vad_type\",\n  \"gdpr\",\n  \"gdpr_consent\",\n  \"us_privacy\",\n];\n\nconst INLINE_DEVICE_MACRO_REPLACEMENTS: Array<{\n  pattern: RegExp;\n  getValue: (ctx: VastMacroContext) => string | undefined;\n}> = [\n  { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) =>\n      ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n  { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) =>\n      ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n  { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n  { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n  { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n  { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator },\n];\n\nexport function isMacroPlaceholder(value: string | null | undefined): boolean {\n  if (value == null) return true;\n  const trimmed = value.trim();\n  if (!trimmed) return true;\n  if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n  return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\n\nexport function generateCorrelator(): string {\n  if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n    try {\n      const buf = new Uint32Array(2);\n      crypto.getRandomValues(buf);\n      const value = (buf[0] ?? 0) * 0x200000 + ((buf[1] ?? 0) & 0x1fffff);\n      if (value > 0) {\n        return String(value);\n      }\n    } catch {\n    }\n  }\n  return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\n\nfunction expandInlineMacroPlaceholders(baseUrl: string, ctx: VastMacroContext): string {\n  let url = baseUrl;\n  for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n    const value = getValue(ctx);\n    if (value != null && value !== \"\") {\n      url = url.replace(pattern, encodeURIComponent(value));\n    }\n  }\n  return url;\n}\n\nfunction applyDeviceIdentityParams(\n  params: URLSearchParams,\n  ctx: VastMacroContext\n): void {\n  const runtimeId = ctx.deviceId?.trim();\n  const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n  const tagRdid = params.get(\"rdid\");\n  const tagType = params.get(\"idtype\");\n  const tagLat = params.get(\"is_lat\");\n  const latValue =\n    ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined;\n\n  if (runtimeId) {\n    params.set(\"rdid\", runtimeId);\n    params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n    params.set(\"is_lat\", latValue ?? (isMacroPlaceholder(tagLat) ? \"0\" : tagLat!));\n    return;\n  }\n\n  const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));\n  const tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));\n\n  if (\n    tagRdidValid &&\n    tagTypeValid &&\n    runtimeType &&\n    !isEquivalentDeviceIdType(tagType!, runtimeType)\n  ) {\n    params.delete(\"rdid\");\n    params.delete(\"idtype\");\n    params.delete(\"is_lat\");\n    return;\n  }\n\n  if (tagRdidValid) {\n    if (isMacroPlaceholder(tagType) && runtimeType) {\n      params.set(\"idtype\", runtimeType);\n    }\n    if (isMacroPlaceholder(tagLat)) {\n      params.set(\"is_lat\", latValue ?? \"0\");\n    }\n    return;\n  }\n\n  params.delete(\"rdid\");\n  params.delete(\"idtype\");\n  params.delete(\"is_lat\");\n}\n\nfunction removeBrokenAppNameOrphans(\n  params: URLSearchParams,\n  appName?: string\n): void {\n  const toDelete: string[] = [];\n\n  params.forEach((_value, key) => {\n    if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n      toDelete.push(key);\n    }\n  });\n\n  if (appName && appName.includes(\"&\")) {\n    for (const suffix of appName.split(\"&\").slice(1)) {\n      const trimmed = suffix.replace(/^\\s+/, \"\");\n      if (!trimmed) continue;\n      toDelete.push(suffix, ` ${trimmed}`, trimmed);\n    }\n  }\n\n  for (const key of new Set(toDelete)) {\n    if (key) params.delete(key);\n  }\n}\n\nexport function normalizeVastTagUrl(raw: string): string {\n  if (!raw) return raw;\n\n  try {\n    const url = new URL(raw);\n\n    const anValue = url.searchParams.get(\"an\");\n    if (anValue !== null) {\n      const orphanFragments: string[] = [];\n      url.searchParams.forEach((_value, key) => {\n        if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n          orphanFragments.push(key.trim());\n        }\n      });\n      if (orphanFragments.length > 0) {\n        const reconstructed = [anValue.replace(/\\s+$/, \"\"), ...orphanFragments]\n          .filter(Boolean)\n          .join(\" & \");\n\n        url.searchParams.forEach((_value, key) => {\n          if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n            url.searchParams.delete(key);\n          }\n        });\n        url.searchParams.set(\"an\", reconstructed);\n\n        return url.toString().replace(\n          /([?&]an=)([^&]*)/,\n          (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n        );\n      }\n    }\n\n    removeBrokenAppNameOrphans(url.searchParams);\n    return url.toString();\n  } catch {\n    return raw;\n  }\n}\n\nexport function applyVastMacros(\n  baseUrl: string,\n  ctx: VastMacroContext\n): string {\n  const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n  let url: URL;\n  try {\n    url = new URL(normalizeVastTagUrl(expandedUrl));\n  } catch {\n    return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n  }\n\n  const params = url.searchParams;\n\n  removeBrokenAppNameOrphans(params, ctx.appName);\n\n  params.set(\"correlator\", ctx.correlator);\n  params.set(\"scor\", ctx.streamCorrelator);\n  if (ctx.isCtv) {\n    for (const key of CTV_UNSUPPORTED_PARAMS) {\n      params.delete(key);\n    }\n  }\n\n  if (ctx.pod != null) {\n    params.set(\"pod\", String(ctx.pod));\n  }\n\n  params.delete(\"ppos\");\n  params.delete(\"lip\");\n  if (ctx.podMinDurationMs != null) {\n    params.set(\"pmnd\", String(Math.max(0, Math.round(ctx.podMinDurationMs))));\n  }\n  if (ctx.podMaxDurationMs != null) {\n    params.set(\"pmxd\", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));\n  }\n  if (ctx.podMaxAds != null) {\n    params.set(\"pmad\", String(Math.max(1, Math.round(ctx.podMaxAds))));\n  }\n\n  const requestUrl = ctx.contentUrl || ctx.pageUrl;\n  if (requestUrl) {\n    params.set(\"url\", requestUrl);\n    if (!ctx.isCtv) {\n      params.set(\"description_url\", requestUrl);\n    }\n  } else {\n    const existingUrl = params.get(\"url\") || \"\";\n    if (EXAMPLE_COM_URL.test(existingUrl)) {\n      params.delete(\"url\");\n      params.delete(\"description_url\");\n    }\n  }\n\n  if (ctx.adWillPlayMuted != null) {\n    params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n  }\n  if (ctx.adWillAutoPlay != null) {\n    params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n  }\n\n  if (ctx.appId) {\n    params.set(\"msid\", ctx.appId);\n  }\n  if (ctx.appName) {\n    removeBrokenAppNameOrphans(params, ctx.appName);\n    params.set(\"an\", ctx.appName);\n  }\n  if (ctx.sessionId) {\n    params.set(\"sid\", ctx.sessionId);\n  }\n  if (ctx.deviceTypeHint != null) {\n    params.set(\"dth\", String(ctx.deviceTypeHint));\n  } else if (ctx.isCtv) {\n    params.set(\"dth\", \"5\");\n  }\n\n  applyDeviceIdentityParams(params, ctx);\n\n  if (!ctx.isCtv) {\n    const consent = ctx.consent;\n    if (consent?.gdpr != null) {\n      params.set(\"gdpr\", consent.gdpr);\n    }\n    if (consent?.gdprConsent != null) {\n      params.set(\"gdpr_consent\", consent.gdprConsent);\n    }\n    if (consent?.usPrivacy != null) {\n      params.set(\"us_privacy\", consent.usPrivacy);\n    }\n  }\n\n  if (ctx.adTest) {\n    params.set(\"adtest\", \"on\");\n  }\n\n  const staleKeys: string[] = [];\n  params.forEach((value, key) => {\n    if (isMacroPlaceholder(value)) {\n      staleKeys.push(key);\n    }\n  });\n  for (const key of staleKeys) {\n    params.delete(key);\n  }\n\n  removeBrokenAppNameOrphans(params, ctx.appName);\n\n  return url.toString();\n}\n\nfunction replaceCorrelatorFallback(baseUrl: string, correlator: string): string {\n  const correlatorRegex = /([?&])correlator=([^&]*)/;\n  if (correlatorRegex.test(baseUrl)) {\n    return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n  }\n  const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n  return `${baseUrl}${sep}correlator=${correlator}`;\n}\n\nexport function fetchConsentSignals(\n  timeoutMs: number = 1500\n): Promise<VastConsentSignals> {\n  const signals: VastConsentSignals = {};\n  if (typeof window === \"undefined\") {\n    return Promise.resolve(signals);\n  }\n\n  const tasks: Promise<void>[] = [];\n\n  const tcfApi = (window as any).__tcfapi;\n  if (typeof tcfApi === \"function\") {\n    tasks.push(\n      new Promise<void>((resolve) => {\n        let settled = false;\n        try {\n          tcfApi(\"addEventListener\", 2, (tcData: any, success: boolean) => {\n            if (settled) return;\n            if (\n              success &&\n              tcData &&\n              (tcData.eventStatus === \"tcloaded\" ||\n                tcData.eventStatus === \"useractioncomplete\")\n            ) {\n              settled = true;\n              signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n              if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n                signals.gdprConsent = tcData.tcString;\n              }\n              try {\n                tcfApi(\"removeEventListener\", 2, () => {}, tcData.listenerId);\n              } catch {}\n              resolve();\n            }\n          });\n        } catch {\n          resolve();\n        }\n        setTimeout(() => {\n          if (!settled) {\n            settled = true;\n            resolve();\n          }\n        }, timeoutMs);\n      })\n    );\n  }\n\n  const uspApi = (window as any).__uspapi;\n  if (typeof uspApi === \"function\") {\n    tasks.push(\n      new Promise<void>((resolve) => {\n        try {\n          uspApi(\"getUSPData\", 1, (data: any, success: boolean) => {\n            if (success && typeof data?.uspString === \"string\" && data.uspString) {\n              signals.usPrivacy = data.uspString;\n            }\n            resolve();\n          });\n        } catch {\n          resolve();\n        }\n        setTimeout(resolve, timeoutMs);\n      })\n    );\n  }\n\n  if (tasks.length === 0) {\n    return Promise.resolve(signals);\n  }\n\n  return Promise.all(tasks).then(() => signals);\n}\n","interface NavigatorUAData {\n  platform?: string;\n  brands?: Array<{ brand: string; version: string }>;\n  mobile?: boolean;\n}\n\ndeclare global {\n  interface Navigator {\n    userAgentData?: NavigatorUAData;\n  }\n}\n\nexport interface BrowserInfo {\n  name: string;\n  version: string;\n  majorVersion: number;\n  isSmartTV: boolean;\n  isLegacyTV: boolean;\n  platform: string;\n  supportsModernJS: boolean;\n  webOSVersion?: number | undefined;\n  tizenVersion?: number | undefined;\n  chromeVersion?: number | undefined;\n}\n\nfunction getChromeVersion(ua: string): number {\n  const match = ua.match(/Chrome\\/(\\d+)/);\n  return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n  const match = ua.match(/AppleWebKit\\/(\\d+)/);\n  return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n  if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n    return navigator.userAgentData.platform;\n  }\n\n  const ua = navigator.userAgent;\n  if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n    return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n  }\n  if (/Win/i.test(ua)) {\n    return 'Win32';\n  }\n  if (/Linux/i.test(ua)) {\n    return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n  }\n  if (/CrOS/i.test(ua)) {\n    return 'CrOS';\n  }\n\n  // eslint-disable-next-line deprecation/deprecation\n  return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n  const ua = navigator.userAgent;\n  const platform = getPlatform();\n\n  let name = 'Unknown';\n  let version = '0';\n  let majorVersion = 0;\n  let isSmartTV = false;\n  let isLegacyTV = false;\n  let supportsModernJS = true;\n  let webOSVersion: number | undefined;\n  let tizenVersion: number | undefined;\n  let chromeVersionNum: number | undefined;\n\n  const chromeVersion = getChromeVersion(ua);\n  const webkitVersion = getWebKitVersion(ua);\n  chromeVersionNum = chromeVersion > 0 ? chromeVersion : undefined;\n\n  if (/Web0S|webOS|LG Browser|LGSTB/i.test(ua)) {\n    name = 'LG WebOS';\n    isSmartTV = true;\n\n    let match = ua.match(/Web0S[/\\s]*([\\d.]+)/i) || ua.match(/webOS[/\\s]*([\\d.]+)/i);\n\n    if (!match || !match[1]) {\n      match = ua.match(/webOSTV[/\\s-]*([\\d.]+)/i) || ua.match(/webOS\\.TV[/\\s-]*([\\d.]+)/i);\n    }\n\n    if (match && match[1]) {\n      version = match[1];\n      const parts = version.split('.');\n      majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n      webOSVersion = majorVersion;\n    } else if (chromeVersion > 0) {\n      if (chromeVersion >= 79) {\n        webOSVersion = 6;\n        version = '6.0';\n        majorVersion = 6;\n      } else if (chromeVersion >= 68) {\n        webOSVersion = 5;\n        version = '5.0';\n        majorVersion = 5;\n      } else if (chromeVersion >= 53) {\n        webOSVersion = 4;\n        version = '4.0';\n        majorVersion = 4;\n      } else if (chromeVersion >= 38) {\n        webOSVersion = 3;\n        version = '3.0';\n        majorVersion = 3;\n      } else {\n        webOSVersion = 2;\n        version = '2.0';\n        majorVersion = 2;\n      }\n    } else {\n      version = 'Unknown';\n      webOSVersion = undefined;\n    }\n\n    isLegacyTV = webOSVersion !== undefined && webOSVersion < 3;\n  } else if (/Tizen/i.test(ua)) {\n    name = 'Samsung Tizen';\n    isSmartTV = true;\n    const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n    version = match && match[1] ? match[1] : 'Unknown';\n    if (version !== 'Unknown') {\n      const parts = version.split('.');\n      majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n      tizenVersion = majorVersion;\n    }\n\n    isLegacyTV = tizenVersion !== undefined && tizenVersion < 3;\n  } else if (/SMART-TV|SmartTV/i.test(ua)) {\n    name = 'Smart TV';\n    isSmartTV = true;\n    isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n  } else if (/NetCast/i.test(ua)) {\n    name = 'LG NetCast';\n    isSmartTV = true;\n    isLegacyTV = true;\n  } else if (/BRAVIA/i.test(ua)) {\n    name = 'Sony BRAVIA';\n    isSmartTV = true;\n    isLegacyTV = chromeVersion > 0 && chromeVersion < 53;\n  } else {\n    if (chromeVersion > 0) {\n      name = 'Chrome';\n      version = chromeVersion.toString();\n      majorVersion = chromeVersion;\n\n      if (chromeVersion < 50) {\n        supportsModernJS = false;\n      }\n    }\n\n    if (webkitVersion > 0 && webkitVersion < 600) {\n      supportsModernJS = false;\n    }\n  }\n\n  if (typeof Promise === 'undefined' ||\n      typeof Map === 'undefined' ||\n      typeof Set === 'undefined') {\n    supportsModernJS = false;\n  }\n\n  if (typeof URLSearchParams === 'undefined') {\n    supportsModernJS = false;\n  }\n\n  return {\n    name,\n    version,\n    majorVersion,\n    isSmartTV,\n    isLegacyTV,\n    platform,\n    supportsModernJS,\n    webOSVersion,\n    tizenVersion,\n    chromeVersion: chromeVersionNum,\n  };\n}\n\nexport function getBrowserConfigOverrides(): {\n  allowNativeHls?: boolean;\n  pauseContentDuringAds?: boolean;\n} {\n  const browser = detectBrowser();\n  const overrides: {\n    allowNativeHls?: boolean;\n    pauseContentDuringAds?: boolean;\n  } = {};\n\n  if (browser.isSmartTV) {\n    overrides.allowNativeHls = true;\n    overrides.pauseContentDuringAds = true;\n  }\n\n  return overrides;\n}\n\nexport function supportsModernJS(): boolean {\n  try {\n    return (\n      typeof Promise !== 'undefined' &&\n      typeof Map !== 'undefined' &&\n      typeof Set !== 'undefined' &&\n      typeof Array.from !== 'undefined' &&\n      typeof Object.assign !== 'undefined' &&\n      typeof Array.prototype.forEach !== 'undefined' &&\n      typeof String.prototype.includes !== 'undefined'\n    );\n  } catch (e) {\n    return false;\n  }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n  if (!debug) return;\n\n  const browser = detectBrowser();\n\n  console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n    browser: `${browser.name} ${browser.version}`,\n    platform: browser.platform,\n    isSmartTV: browser.isSmartTV,\n    isLegacyTV: browser.isLegacyTV,\n    supportsModernJS: browser.supportsModernJS,\n    ...(browser.webOSVersion !== undefined ? { webOSVersion: browser.webOSVersion } : {}),\n    ...(browser.tizenVersion !== undefined ? { tizenVersion: browser.tizenVersion } : {}),\n    ...(browser.chromeVersion !== undefined ? { chromeVersion: browser.chromeVersion } : {}),\n    userAgent: navigator.userAgent,\n  });\n}\n\nexport function supportsFeature(feature: string): boolean {\n  switch (feature) {\n    case 'urlsearchparams':\n      return typeof URLSearchParams !== 'undefined';\n    case 'textencoder':\n      return typeof TextEncoder !== 'undefined';\n    case 'promises':\n      return typeof Promise !== 'undefined';\n    case 'fetch':\n      return typeof fetch !== 'undefined';\n    case 'crypto':\n      return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n    default:\n      return false;\n  }\n}\n","import type { Scte35Marker, Id3TagInfo } from \"../types\";\n\nexport function parseCueOutDuration(value: string): number | undefined {\n  const num = parseFloat(value.trim());\n  if (!Number.isNaN(num)) return num;\n  const match =\n    value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n    value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n  if (match && match[1] != null) {\n    const dStr = match[1];\n    const d = parseFloat(dStr);\n    return Number.isNaN(d) ? undefined : d;\n  }\n  return undefined;\n}\n\nexport function parseCueOutCont(\n  value: string\n): { elapsed?: number; duration?: number } | undefined {\n  const res: { elapsed?: number; duration?: number } = {};\n\n  const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n  const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n  if (elapsedMatch && elapsedMatch[1] != null) {\n    const e = parseFloat(elapsedMatch[1]);\n    if (!Number.isNaN(e)) res.elapsed = e;\n  }\n  if (durationMatch && durationMatch[1] != null) {\n    const d = parseFloat(durationMatch[1]);\n    if (!Number.isNaN(d)) res.duration = d;\n  }\n\n  if (!(\"elapsed\" in res) || !(\"duration\" in res)) {\n    const slashMatch = value.match(/([0-9.]+)\\s*\\/\\s*([0-9.]+)/);\n    if (slashMatch && slashMatch[1] && slashMatch[2]) {\n      const elapsed = parseFloat(slashMatch[1]);\n      const duration = parseFloat(slashMatch[2]);\n      if (!Number.isNaN(elapsed) && !(\"elapsed\" in res)) res.elapsed = elapsed;\n      if (!Number.isNaN(duration) && !(\"duration\" in res)) res.duration = duration;\n    }\n  }\n\n  if (\"elapsed\" in res || \"duration\" in res) return res;\n  return undefined;\n}\n\nexport function parseAttributeList(value: string): Record<string, string> {\n  const attrs: Record<string, string> = {};\n  const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n  let match: RegExpExecArray | null;\n  while ((match = regex.exec(value)) !== null) {\n    const key: string = (match[1] ?? \"\") as string;\n    let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n    if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n      rawVal = rawVal.slice(1, -1);\n    }\n    if (key) {\n      attrs[key] = rawVal;\n    }\n  }\n  return attrs;\n}\n\nexport function toNumber(val: unknown): number | undefined {\n  if (val == null) return undefined;\n  const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n  return Number.isNaN(n) ? undefined : n;\n}\n\nexport function isManifestBasedMarker(marker: Scte35Marker): boolean {\n  const raw = marker.raw as any;\n  if (!raw) return false;\n\n  if (raw.tag) {\n    const tag = String(raw.tag);\n    return (\n      tag.includes(\"EXT-X-CUE-OUT\") ||\n      tag.includes(\"EXT-X-CUE-IN\") ||\n      tag.includes(\"EXT-X-DATERANGE\")\n    );\n  }\n\n  if (raw.id3) return false;\n\n  if (raw.splice_command_type) return false;\n\n  return false;\n}\n\nexport function decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n  try {\n    if (typeof value === \"string\") return value;\n    const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n    const text = decoder.decode(value);\n    if (text && /[\\x20-\\x7E]/.test(text)) return text;\n    let out = \"\";\n    for (let i = 0; i < value.length; i++)\n      out += String.fromCharCode(value[i]!);\n    return out;\n  } catch {\n    return undefined;\n  }\n}\n\nexport function getFragmentStartSeconds(frag: any): number | undefined {\n  const candidates = [frag?.start, frag?.startPTS];\n  for (const candidate of candidates) {\n    if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n      return candidate;\n    }\n  }\n  return undefined;\n}\n\nexport function parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n  const text = decodeId3ValueToText(tag.value);\n  if (!text) return undefined;\n\n  const cueOutMatch =\n    text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n    text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n  if (cueOutMatch) {\n    const arg = (cueOutMatch[1] ?? \"\").trim();\n    const dur = parseCueOutDuration(arg);\n    const marker: Scte35Marker = {\n      type: \"start\",\n      ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n      ...(dur !== undefined ? { durationSeconds: dur } : {}),\n      raw: { id3: text },\n    } as Scte35Marker;\n    return marker;\n  }\n\n  const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n  if (cueOutContMatch) {\n    const arg = (cueOutContMatch[1] ?? \"\").trim();\n    const cont = parseCueOutCont(arg);\n    const marker: Scte35Marker = {\n      type: \"progress\",\n      ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n      ...(cont?.duration !== undefined\n        ? { durationSeconds: cont.duration }\n        : {}),\n      raw: { id3: text },\n    } as Scte35Marker;\n    return marker;\n  }\n\n  const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n  if (cueInMatch) {\n    const marker: Scte35Marker = {\n      type: \"end\",\n      ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n      raw: { id3: text },\n    } as Scte35Marker;\n    return marker;\n  }\n\n  const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\\r\\n]*)/i);\n  if (daterangeMatch) {\n    const attrs = parseAttributeList(daterangeMatch[1] ?? \"\");\n    const hasScteOut =\n      \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n    const hasScteIn =\n      \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n    const klass = String(attrs[\"CLASS\"] ?? \"\");\n    const duration = toNumber(attrs[\"DURATION\"]);\n    if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n      const marker: Scte35Marker = {\n        type: \"start\",\n        ...(tag.ptsSeconds !== undefined\n          ? { ptsSeconds: tag.ptsSeconds }\n          : {}),\n        ...(duration !== undefined ? { durationSeconds: duration } : {}),\n        raw: { id3: text, attrs },\n      } as Scte35Marker;\n      return marker;\n    }\n    if (hasScteIn) {\n      const marker: Scte35Marker = {\n        type: \"end\",\n        ...(tag.ptsSeconds !== undefined\n          ? { ptsSeconds: tag.ptsSeconds }\n          : {}),\n        raw: { id3: text, attrs },\n      } as Scte35Marker;\n      return marker;\n    }\n  }\n\n  if (/SCTE35-OUT/i.test(text)) {\n    const marker: Scte35Marker = {\n      type: \"start\",\n      ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n      raw: { id3: text },\n    } as Scte35Marker;\n    return marker;\n  }\n  if (/SCTE35-IN/i.test(text)) {\n    const marker: Scte35Marker = {\n      type: \"end\",\n      ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n      raw: { id3: text },\n    } as Scte35Marker;\n    return marker;\n  }\n\n  if (tag.value instanceof Uint8Array) {\n    const bin = parseScte35Binary(tag.value);\n    if (bin) return bin;\n  }\n\n  return undefined;\n}\n\nexport function normalizeFragmentPayload(payload: unknown): Uint8Array | undefined {\n  if (payload instanceof Uint8Array) {\n    return payload;\n  }\n  if (payload instanceof ArrayBuffer) {\n    return new Uint8Array(payload);\n  }\n  if (ArrayBuffer.isView(payload)) {\n    const view = payload as ArrayBufferView;\n    return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);\n  }\n  return undefined;\n}\n\n// --- Transport Stream SCTE-35 parsing ---\n\nexport function detectTsPacketFormat(\n  data: Uint8Array\n): { offset: number; packetSize: number; tsPayloadOffset: number } | undefined {\n  const packetSizes = [188, 192, 204];\n  for (const packetSize of packetSizes) {\n    const tsPayloadOffset = packetSize === 192 ? 4 : 0;\n    for (let offset = 0; offset < packetSize; offset++) {\n      let matchedPackets = 0;\n      for (\n        let packetStart = offset;\n        packetStart + tsPayloadOffset < data.length &&\n        matchedPackets < 5;\n        packetStart += packetSize\n      ) {\n        if (data[packetStart + tsPayloadOffset] !== 0x47) {\n          break;\n        }\n        matchedPackets++;\n      }\n      if (matchedPackets >= 2) {\n        return { offset, packetSize, tsPayloadOffset };\n      }\n    }\n  }\n  return undefined;\n}\n\nfunction getPsiSectionStart(\n  payload: Uint8Array,\n  payloadUnitStart: boolean\n): number | undefined {\n  if (!payloadUnitStart) {\n    return undefined;\n  }\n  const pointerField = payload[0];\n  if (pointerField == null) {\n    return undefined;\n  }\n  const sectionStart = 1 + pointerField;\n  return sectionStart < payload.length ? sectionStart : undefined;\n}\n\nfunction getPsiSectionLength(data: Uint8Array, offset: number): number {\n  return (((data[offset + 1] ?? 0) & 0x0f) << 8) | (data[offset + 2] ?? 0);\n}\n\nfunction parsePatSection(\n  payload: Uint8Array,\n  payloadUnitStart: boolean,\n  pmtPids: Set<number>\n): void {\n  const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n  if (sectionStart == null || sectionStart + 8 >= payload.length) {\n    return;\n  }\n  if (payload[sectionStart] !== 0x00) {\n    return;\n  }\n\n  const sectionLength = getPsiSectionLength(payload, sectionStart);\n  const sectionEnd = Math.min(\n    payload.length,\n    sectionStart + 3 + sectionLength\n  );\n\n  for (let offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4) {\n    const programNumber =\n      ((payload[offset] ?? 0) << 8) | (payload[offset + 1] ?? 0);\n    const pid =\n      (((payload[offset + 2] ?? 0) & 0x1f) << 8) |\n      (payload[offset + 3] ?? 0);\n    if (programNumber !== 0) {\n      pmtPids.add(pid);\n    }\n  }\n}\n\nfunction descriptorsIdentifyScte35(\n  data: Uint8Array,\n  start: number,\n  end: number\n): boolean {\n  let offset = start;\n  while (offset + 2 <= end) {\n    const tag = data[offset] ?? 0;\n    const length = data[offset + 1] ?? 0;\n    const descriptorStart = offset + 2;\n    const descriptorEnd = descriptorStart + length;\n    if (descriptorEnd > end) {\n      return false;\n    }\n\n    const registration =\n      length >= 4\n        ? String.fromCharCode(\n            data[descriptorStart] ?? 0,\n            data[descriptorStart + 1] ?? 0,\n            data[descriptorStart + 2] ?? 0,\n            data[descriptorStart + 3] ?? 0\n          )\n        : \"\";\n    if (tag === 0x8a || registration === \"CUEI\" || registration === \"SCTE\") {\n      return true;\n    }\n\n    offset = descriptorEnd;\n  }\n  return false;\n}\n\nfunction parsePmtSection(\n  payload: Uint8Array,\n  payloadUnitStart: boolean,\n  tsScte35Pids: Set<number>\n): void {\n  const sectionStart = getPsiSectionStart(payload, payloadUnitStart);\n  if (sectionStart == null || sectionStart + 12 >= payload.length) {\n    return;\n  }\n  if (payload[sectionStart] !== 0x02) {\n    return;\n  }\n\n  const sectionLength = getPsiSectionLength(payload, sectionStart);\n  const sectionEnd = Math.min(\n    payload.length,\n    sectionStart + 3 + sectionLength\n  );\n  const programInfoLength =\n    (((payload[sectionStart + 10] ?? 0) & 0x0f) << 8) |\n    (payload[sectionStart + 11] ?? 0);\n\n  let offset = sectionStart + 12 + programInfoLength;\n  while (offset + 5 <= sectionEnd - 4) {\n    const streamType = payload[offset] ?? 0;\n    const elementaryPid =\n      (((payload[offset + 1] ?? 0) & 0x1f) << 8) |\n      (payload[offset + 2] ?? 0);\n    const esInfoLength =\n      (((payload[offset + 3] ?? 0) & 0x0f) << 8) |\n      (payload[offset + 4] ?? 0);\n    const descriptorStart = offset + 5;\n    const descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);\n\n    if (\n      streamType === 0x86 ||\n      (streamType === 0x06 &&\n        descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd))\n    ) {\n      tsScte35Pids.add(elementaryPid);\n    }\n\n    offset = descriptorStart + esInfoLength;\n  }\n}\n\nfunction hasProcessedTsScte35Section(\n  section: Uint8Array,\n  processedSections: Set<string>\n): boolean {\n  let checksum = 0;\n  for (let i = 0; i < section.length; i++) {\n    checksum = (checksum * 31 + (section[i] ?? 0)) >>> 0;\n  }\n\n  const key = `${section.length}:${checksum}`;\n  if (processedSections.has(key)) {\n    return true;\n  }\n\n  processedSections.add(key);\n  if (processedSections.size > 200) {\n    const firstKey = processedSections.values().next().value;\n    if (firstKey) {\n      processedSections.delete(firstKey);\n    }\n  }\n  return false;\n}\n\nfunction addScte35SectionMarker(\n  section: Uint8Array,\n  markers: Scte35Marker[],\n  processedSections: Set<string>\n): void {\n  if (section[0] !== 0xfc || hasProcessedTsScte35Section(section, processedSections)) {\n    return;\n  }\n\n  const marker = parseScte35Binary(section);\n  if (!marker) {\n    return;\n  }\n\n  marker.raw = {\n    ...(typeof marker.raw === \"object\" && marker.raw ? marker.raw : {}),\n    source: \"ts-packet\",\n  };\n  markers.push(marker);\n}\n\nfunction appendScte35Bytes(\n  pid: number,\n  bytes: Uint8Array,\n  assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n  markers: Scte35Marker[],\n  processedSections: Set<string>\n): void {\n  const assembler = assemblers.get(pid);\n  if (!assembler) {\n    return;\n  }\n\n  for (let i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++) {\n    assembler.bytes.push(bytes[i] ?? 0);\n  }\n\n  if (assembler.bytes.length >= assembler.expectedLength) {\n    assemblers.delete(pid);\n    addScte35SectionMarker(new Uint8Array(assembler.bytes), markers, processedSections);\n  }\n}\n\nfunction collectScte35SectionsFromPayload(\n  pid: number,\n  payload: Uint8Array,\n  payloadUnitStart: boolean,\n  assemblers: Map<number, { bytes: number[]; expectedLength: number }>,\n  markers: Scte35Marker[],\n  processedSections: Set<string>\n): void {\n  if (payload.length === 0) {\n    return;\n  }\n\n  let offset = 0;\n  if (payloadUnitStart) {\n    const pointerField = payload[0] ?? 0;\n    const previousAssembler = assemblers.get(pid);\n    if (previousAssembler && pointerField > 0) {\n      appendScte35Bytes(\n        pid,\n        payload.subarray(1, Math.min(1 + pointerField, payload.length)),\n        assemblers,\n        markers,\n        processedSections\n      );\n    }\n    assemblers.delete(pid);\n    offset = 1 + pointerField;\n  } else {\n    appendScte35Bytes(pid, payload, assemblers, markers, processedSections);\n    return;\n  }\n\n  while (offset + 3 <= payload.length) {\n    const tableId = payload[offset];\n    if (tableId == null || tableId === 0xff) {\n      return;\n    }\n\n    const sectionLength = getPsiSectionLength(payload, offset);\n    const totalLength = 3 + sectionLength;\n    if (sectionLength <= 0 || totalLength <= 3) {\n      return;\n    }\n\n    if (offset + totalLength <= payload.length) {\n      addScte35SectionMarker(\n        payload.subarray(offset, offset + totalLength),\n        markers,\n        processedSections\n      );\n      offset += totalLength;\n    } else {\n      assemblers.set(pid, {\n        bytes: Array.from(payload.subarray(offset)),\n        expectedLength: totalLength,\n      });\n      return;\n    }\n  }\n}\n\nexport function parseScte35FromTsPackets(\n  data: Uint8Array,\n  tsScte35Pids: Set<number>,\n  pmtPids: Set<number>,\n  processedSections: Set<string>\n): Scte35Marker[] {\n  const packetInfo = detectTsPacketFormat(data);\n  if (!packetInfo) {\n    return [];\n  }\n\n  const markers: Scte35Marker[] = [];\n  const sectionAssemblers = new Map<\n    number,\n    { bytes: number[]; expectedLength: number }\n  >();\n\n  for (\n    let packetStart = packetInfo.offset;\n    packetStart + packetInfo.packetSize <= data.length;\n    packetStart += packetInfo.packetSize\n  ) {\n    const tsStart = packetStart + packetInfo.tsPayloadOffset;\n    if (data[tsStart] !== 0x47) {\n      continue;\n    }\n\n    const secondByte = data[tsStart + 1];\n    const thirdByte = data[tsStart + 2];\n    const fourthByte = data[tsStart + 3];\n    if (\n      secondByte == null ||\n      thirdByte == null ||\n      fourthByte == null ||\n      (secondByte & 0x80) !== 0\n    ) {\n      continue;\n    }\n\n    const payloadUnitStart = (secondByte & 0x40) !== 0;\n    const pid = ((secondByte & 0x1f) << 8) | thirdByte;\n    const adaptationFieldControl = (fourthByte >> 4) & 0x03;\n    const hasPayload =\n      adaptationFieldControl === 1 || adaptationFieldControl === 3;\n    if (!hasPayload) {\n      continue;\n    }\n\n    let payloadStart = tsStart + 4;\n    if (adaptationFieldControl === 3) {\n      const adaptationLength = data[payloadStart];\n      if (adaptationLength == null) {\n        continue;\n      }\n      payloadStart += 1 + adaptationLength;\n    }\n\n    const payloadEnd = Math.min(tsStart + 188, data.length);\n    if (payloadStart >= payloadEnd || payloadStart >= data.length) {\n      continue;\n    }\n\n    const payload = data.subarray(payloadStart, payloadEnd);\n    if (pid === 0) {\n      parsePatSection(payload, payloadUnitStart, pmtPids);\n    } else if (pmtPids.has(pid)) {\n      parsePmtSection(payload, payloadUnitStart, tsScte35Pids);\n    } else if (tsScte35Pids.has(pid)) {\n      collectScte35SectionsFromPayload(\n        pid,\n        payload,\n        payloadUnitStart,\n        sectionAssemblers,\n        markers,\n        processedSections\n      );\n    }\n  }\n\n  return markers;\n}\n\n// --- Binary SCTE-35 parsing ---\n\nclass BitReader {\n  private bytePos = 0;\n  private bitPos = 0;\n  constructor(private readonly buf: Uint8Array) {}\n  readBits(numBits: number): number {\n    let result = 0;\n    while (numBits > 0) {\n      if (this.bytePos >= this.buf.length) return result;\n      const remainingInByte = 8 - this.bitPos;\n      const toRead = Math.min(numBits, remainingInByte);\n      const currentByte = this.buf[this.bytePos]!;\n      const shift = remainingInByte - toRead;\n      const mask = ((1 << toRead) - 1) & 0xff;\n      const bits = (currentByte >> shift) & mask;\n      result = (result << toRead) | bits;\n      this.bitPos += toRead;\n      if (this.bitPos >= 8) {\n        this.bitPos = 0;\n        this.bytePos += 1;\n      }\n      numBits -= toRead;\n    }\n    return result >>> 0;\n  }\n  skipBits(n: number): void {\n    this.readBits(n);\n  }\n  get bytePosition(): number {\n    return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;\n  }\n}\n\nfunction readSpliceTime(\n  r: BitReader,\n  ptsAdjustmentTicks: number\n): number | undefined {\n  const timeSpecifiedFlag = r.readBits(1) === 1;\n  if (!timeSpecifiedFlag) {\n    r.readBits(7);\n    return undefined;\n  }\n  r.readBits(6);\n  const high = r.readBits(1);\n  const low = r.readBits(32);\n  const ptsTicks =\n    (high * 0x100000000 + low + ptsAdjustmentTicks) % 0x200000000;\n  return ptsTicks / 90000;\n}\n\nfunction markerTypeFromSegmentationTypeId(\n  segmentationTypeId: number\n): Scte35Marker[\"type\"] | undefined {\n  switch (segmentationTypeId) {\n    case 0x10:\n    case 0x22:\n    case 0x30:\n    case 0x32:\n    case 0x34:\n    case 0x36:\n      return \"start\";\n    case 0x11:\n    case 0x23:\n    case 0x31:\n    case 0x33:\n    case 0x35:\n    case 0x37:\n      return \"end\";\n    default:\n      return undefined;\n  }\n}\n\nfunction parseScte35SegmentationDescriptor(\n  descriptor: Uint8Array\n):\n  | {\n      type: Scte35Marker[\"type\"];\n      durationSeconds?: number;\n      segmentationEventId?: number;\n    }\n  | undefined {\n  if (descriptor.length < 11) {\n    return undefined;\n  }\n\n  const identifier = String.fromCharCode(\n    descriptor[0] ?? 0,\n    descriptor[1] ?? 0,\n    descriptor[2] ?? 0,\n    descriptor[3] ?? 0\n  );\n  if (identifier !== \"CUEI\") {\n    return undefined;\n  }\n\n  const segmentationEventId =\n    ((descriptor[4] ?? 0) * 0x1000000) +\n    ((descriptor[5] ?? 0) << 16) +\n    ((descriptor[6] ?? 0) << 8) +\n    (descriptor[7] ?? 0);\n  const cancelIndicator = ((descriptor[8] ?? 0) & 0x80) !== 0;\n  if (cancelIndicator) {\n    return undefined;\n  }\n\n  const flags = descriptor[9] ?? 0;\n  const programSegmentationFlag = (flags & 0x80) !== 0;\n  const segmentationDurationFlag = (flags & 0x40) !== 0;\n  let offset = 10;\n\n  if (!programSegmentationFlag) {\n    const componentCount = descriptor[offset] ?? 0;\n    offset += 1 + componentCount * 6;\n    if (offset > descriptor.length) {\n      return undefined;\n    }\n  }\n\n  let durationSeconds: number | undefined = undefined;\n  if (segmentationDurationFlag) {\n    if (offset + 5 > descriptor.length) {\n      return undefined;\n    }\n    const durationTicks =\n      ((descriptor[offset] ?? 0) * 0x100000000) +\n      ((descriptor[offset + 1] ?? 0) * 0x1000000) +\n      ((descriptor[offset + 2] ?? 0) << 16) +\n      ((descriptor[offset + 3] ?? 0) << 8) +\n      (descriptor[offset + 4] ?? 0);\n    durationSeconds = durationTicks / 90000;\n    offset += 5;\n  }\n\n  if (offset + 2 > descriptor.length) {\n    return undefined;\n  }\n  offset += 1;\n  const segmentationUpidLength = descriptor[offset] ?? 0;\n  offset += 1 + segmentationUpidLength;\n  if (offset >= descriptor.length) {\n    return undefined;\n  }\n\n  const segmentationTypeId = descriptor[offset] ?? 0;\n  const markerType = markerTypeFromSegmentationTypeId(segmentationTypeId);\n  if (!markerType) {\n    return undefined;\n  }\n\n  return {\n    type: markerType,\n    ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n    segmentationEventId,\n  };\n}\n\nfunction parseScte35SegmentationDescriptors(\n  data: Uint8Array,\n  offset: number\n):\n  | {\n      type: Scte35Marker[\"type\"];\n      durationSeconds?: number;\n      segmentationEventId?: number;\n    }\n  | undefined {\n  if (offset + 2 > data.length) {\n    return undefined;\n  }\n\n  const descriptorLoopLength =\n    ((data[offset] ?? 0) << 8) | (data[offset + 1] ?? 0);\n  let descriptorOffset = offset + 2;\n  const descriptorEnd = Math.min(\n    data.length,\n    descriptorOffset + descriptorLoopLength\n  );\n\n  while (descriptorOffset + 2 <= descriptorEnd) {\n    const descriptorTag = data[descriptorOffset] ?? 0;\n    const descriptorLength = data[descriptorOffset + 1] ?? 0;\n    const descriptorDataStart = descriptorOffset + 2;\n    const descriptorDataEnd = descriptorDataStart + descriptorLength;\n    if (descriptorDataEnd > descriptorEnd) {\n      return undefined;\n    }\n\n    if (descriptorTag === 0x02) {\n      const descriptorMarker = parseScte35SegmentationDescriptor(\n        data.subarray(descriptorDataStart, descriptorDataEnd)\n      );\n      if (descriptorMarker) {\n        return descriptorMarker;\n      }\n    }\n\n    descriptorOffset = descriptorDataEnd;\n  }\n\n  return undefined;\n}\n\nexport function parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n  const r = new BitReader(data);\n  const tableId = r.readBits(8);\n  if (tableId !== 0xfc) return undefined;\n  r.readBits(1);\n  r.readBits(1);\n  r.readBits(2);\n  const sectionLength = r.readBits(12);\n  if (sectionLength <= 0 || data.length < 3 + sectionLength) {\n    return undefined;\n  }\n  r.readBits(8);\n  r.readBits(1);\n  r.readBits(6);\n  const ptsAdjHigh = r.readBits(1);\n  const ptsAdjLow = r.readBits(32);\n  const ptsAdjustmentTicks = ptsAdjHigh * 0x100000000 + ptsAdjLow;\n  r.readBits(8);\n  r.readBits(12);\n  const spliceCommandLength = r.readBits(12);\n  const spliceCommandType = r.readBits(8);\n\n  let markerType: Scte35Marker[\"type\"] | undefined;\n  let durationSeconds: number | undefined = undefined;\n  let ptsSeconds: number | undefined = undefined;\n  let spliceEventId: number | undefined = undefined;\n  const commandBodyStart = r.bytePosition;\n\n  if (spliceCommandType === 5) {\n    spliceEventId = r.readBits(32);\n    const cancel = r.readBits(1) === 1;\n    r.readBits(7);\n    if (cancel) return undefined;\n    const outOfNetwork = r.readBits(1) === 1;\n    const programSpliceFlag = r.readBits(1) === 1;\n    const durationFlag = r.readBits(1) === 1;\n    const spliceImmediateFlag = r.readBits(1) === 1;\n    r.readBits(4);\n    markerType = outOfNetwork ? \"start\" : \"end\";\n\n    if (programSpliceFlag && !spliceImmediateFlag) {\n      ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n    } else if (!programSpliceFlag) {\n      const componentCount = r.readBits(8);\n      for (let i = 0; i < componentCount; i++) {\n        r.readBits(8);\n        if (!spliceImmediateFlag) {\n          const componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n          if (ptsSeconds === undefined) {\n            ptsSeconds = componentPtsSeconds;\n          }\n        }\n      }\n    }\n\n    if (durationFlag) {\n      r.readBits(6);\n      r.readBits(1);\n      const high = r.readBits(1);\n      const low = r.readBits(32);\n      const durationTicks = high * 0x100000000 + low;\n      durationSeconds = durationTicks / 90000;\n    }\n    r.readBits(16);\n    r.readBits(8);\n    r.readBits(8);\n  } else if (spliceCommandType === 6) {\n    ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);\n  } else {\n    return undefined;\n  }\n\n  const expectedDescriptorOffset =\n    spliceCommandLength === 0x0fff\n      ? r.bytePosition\n      : commandBodyStart + spliceCommandLength;\n  const descriptorMarker = parseScte35SegmentationDescriptors(\n    data,\n    expectedDescriptorOffset\n  );\n\n  if (descriptorMarker) {\n    markerType = descriptorMarker.type;\n    if (durationSeconds === undefined) {\n      durationSeconds = descriptorMarker.durationSeconds;\n    }\n  }\n\n  if (!markerType) {\n    return undefined;\n  }\n\n  const marker: Scte35Marker = {\n    type: markerType,\n    ...(ptsSeconds !== undefined ? { ptsSeconds } : {}),\n    ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n    raw: {\n      splice_command_type: spliceCommandType,\n      ...(spliceEventId !== undefined ? { splice_event_id: spliceEventId } : {}),\n      ...(descriptorMarker?.segmentationEventId !== undefined\n        ? { segmentation_event_id: descriptorMarker.segmentationEventId }\n        : {}),\n    },\n  } as Scte35Marker;\n  return marker;\n}\n","import type { Scte35Marker } from \"../types\";\nimport type {\n  NormalizedScte35Cue,\n  Scte35CueContext,\n  Scte35CueSource,\n  Scte35CueReadiness,\n} from \"./playerTypes\";\nimport { getFragmentStartSeconds } from \"./Scte35Parser\";\n\nexport interface Scte35CueManagerCallbacks {\n  onEarlyStartCue(marker: Scte35Marker, fragmentSn: number | undefined, cueKey: string): void;\n  onPlaybackCue(marker: Scte35Marker, cueKey?: string): void;\n  isInAdBreak(): boolean;\n}\n\nexport class Scte35CueManager {\n  private readonly pendingScte35Cues: Map<string, NormalizedScte35Cue> = new Map();\n  private readonly recentScte35CueKeys: Map<string, number> = new Map();\n  private readonly recentScte35CueLimit: number = 200;\n  private pendingScte35CueKeyValue: string | undefined;\n  private activeScte35BreakKeyValue: string | undefined;\n  private scheduledScte35BreakKeyValue: string | undefined;\n\n  readonly tsScte35Pids: Set<number> = new Set();\n  readonly pmtPids: Set<number> = new Set();\n  readonly processedTsScte35Sections: Set<string> = new Set();\n\n  private debug: boolean;\n  private callbacks: Scte35CueManagerCallbacks;\n\n  constructor(debug: boolean, callbacks: Scte35CueManagerCallbacks) {\n    this.debug = debug;\n    this.callbacks = callbacks;\n  }\n\n  get pendingScte35CueKey(): string | undefined {\n    return this.pendingScte35CueKeyValue;\n  }\n  set pendingScte35CueKey(value: string | undefined) {\n    this.pendingScte35CueKeyValue = value;\n  }\n\n  get activeScte35BreakKey(): string | undefined {\n    return this.activeScte35BreakKeyValue;\n  }\n  set activeScte35BreakKey(value: string | undefined) {\n    this.activeScte35BreakKeyValue = value;\n  }\n\n  get scheduledScte35BreakKey(): string | undefined {\n    return this.scheduledScte35BreakKeyValue;\n  }\n  set scheduledScte35BreakKey(value: string | undefined) {\n    this.scheduledScte35BreakKeyValue = value;\n  }\n\n  createScte35CueContext(\n    source: Scte35CueSource,\n    readiness: Scte35CueReadiness,\n    frag?: any\n  ): Scte35CueContext {\n    const context: Scte35CueContext = { source, readiness };\n    if (typeof frag?.sn === \"number\") {\n      context.fragmentSn = frag.sn;\n    }\n    const fragmentStartSec = getFragmentStartSeconds(frag);\n    if (fragmentStartSec !== undefined) {\n      context.fragmentStartSeconds = fragmentStartSec;\n    }\n    return context;\n  }\n\n  onScte35Cue(marker: Scte35Marker, context: Scte35CueContext): void {\n    const cue = this.createScte35Cue(marker, context);\n    const pendingKey = this.getPendingScte35CueKey(cue);\n\n    if (context.readiness === \"early\") {\n      this.pendingScte35Cues.set(pendingKey, cue);\n      this.trimRecentScte35CueMaps();\n\n      if (marker.type === \"start\") {\n        this.callbacks.onEarlyStartCue(marker, context.fragmentSn, cue.key);\n      }\n      return;\n    }\n\n    if (marker.type === \"end\" && !this.shouldAcceptScte35EndCue(cue)) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Ignoring SCTE-35 end cue\", {\n          key: cue.key,\n          activeScte35BreakKey: this.activeScte35BreakKeyValue,\n          inAdBreak: this.callbacks.isInAdBreak(),\n          source: cue.source,\n        });\n      }\n      return;\n    }\n\n    if (marker.type === \"start\" && this.hasRecentlyHandledScte35Cue(cue)) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue\", {\n          key: cue.key,\n          source: cue.source,\n        });\n      }\n      return;\n    }\n\n    this.pendingScte35Cues.delete(pendingKey);\n    this.markScte35CueHandled(cue);\n    this.callbacks.onPlaybackCue(marker, cue.key);\n  }\n\n  activatePendingScte35CuesForFragment(frag: any): void {\n    const fragmentSn = typeof frag?.sn === \"number\" ? frag.sn : undefined;\n    if (fragmentSn === undefined) {\n      return;\n    }\n\n    const matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(\n      ([, cue]) => cue.fragmentSn === fragmentSn\n    );\n\n    matchingCues.forEach(([pendingKey, cue]) => {\n      this.pendingScte35Cues.delete(pendingKey);\n      const context: Scte35CueContext = {\n        source: cue.source,\n        readiness: \"playback\",\n      };\n      context.fragmentSn = fragmentSn;\n      const fragmentStartSec =\n        cue.fragmentStartSeconds ?? getFragmentStartSeconds(frag);\n      if (fragmentStartSec !== undefined) {\n        context.fragmentStartSeconds = fragmentStartSec;\n      }\n      this.onScte35Cue(cue.marker, context);\n    });\n  }\n\n  private createScte35Cue(\n    marker: Scte35Marker,\n    context: Scte35CueContext\n  ): NormalizedScte35Cue {\n    const cue: NormalizedScte35Cue = {\n      marker,\n      source: context.source,\n      readiness: context.readiness,\n      key: this.getScte35CueKey(marker, context),\n    };\n    if (context.fragmentSn !== undefined) {\n      cue.fragmentSn = context.fragmentSn;\n    }\n    if (context.fragmentStartSeconds !== undefined) {\n      cue.fragmentStartSeconds = context.fragmentStartSeconds;\n    }\n    return cue;\n  }\n\n  private getScte35CueKey(\n    marker: Scte35Marker,\n    context: Scte35CueContext\n  ): string {\n    const raw = this.getScte35MarkerRaw(marker);\n    const spliceEventId = this.toIdentityString(raw?.splice_event_id);\n    if (spliceEventId) {\n      return `splice:${spliceEventId}`;\n    }\n\n    const segmentationEventId = this.toIdentityString(raw?.segmentation_event_id);\n    if (segmentationEventId) {\n      return `segmentation:${segmentationEventId}`;\n    }\n\n    const daterangeId = this.toIdentityString(raw?.attrs?.ID);\n    if (daterangeId) {\n      return `daterange:${daterangeId}`;\n    }\n\n    const scteValue =\n      this.toIdentityString(raw?.attrs?.[\"SCTE35-OUT\"]) ||\n      this.toIdentityString(raw?.attrs?.[\"SCTE35-IN\"]);\n    if (scteValue) {\n      return `daterange-scte:${scteValue}`;\n    }\n\n    if (typeof marker.ptsSeconds === \"number\" && Number.isFinite(marker.ptsSeconds)) {\n      return `pts:${Math.round(marker.ptsSeconds * 2) / 2}`;\n    }\n\n    if (context.fragmentSn !== undefined) {\n      return `fragment:${context.fragmentSn}`;\n    }\n\n    return `${context.source}:wallclock:${Math.floor(Date.now() / 1000)}`;\n  }\n\n  private getPendingScte35CueKey(cue: NormalizedScte35Cue): string {\n    return `${cue.marker.type}:${cue.key}:${\n      cue.fragmentSn !== undefined ? cue.fragmentSn : \"unknown\"\n    }`;\n  }\n\n  private getScte35MarkerRaw(marker: Scte35Marker): any {\n    return typeof marker.raw === \"object\" && marker.raw !== null\n      ? (marker.raw as any)\n      : {};\n  }\n\n  private toIdentityString(value: unknown): string | undefined {\n    if (typeof value === \"number\" && Number.isFinite(value)) {\n      return String(value);\n    }\n    if (typeof value === \"string\" && value.trim().length > 0) {\n      return value.trim();\n    }\n    return undefined;\n  }\n\n  isStrongScte35CueKey(key: string | undefined): boolean {\n    return !!(\n      key &&\n      (key.startsWith(\"splice:\") ||\n        key.startsWith(\"segmentation:\") ||\n        key.startsWith(\"daterange:\") ||\n        key.startsWith(\"daterange-scte:\"))\n    );\n  }\n\n  private hasRecentlyHandledScte35Cue(cue: NormalizedScte35Cue): boolean {\n    if (\n      this.activeScte35BreakKeyValue === cue.key ||\n      this.scheduledScte35BreakKeyValue === cue.key\n    ) {\n      return true;\n    }\n\n    const recentKey = `${cue.marker.type}:${cue.key}`;\n    return this.recentScte35CueKeys.has(recentKey);\n  }\n\n  private markScte35CueHandled(cue: NormalizedScte35Cue): void {\n    this.recentScte35CueKeys.set(`${cue.marker.type}:${cue.key}`, Date.now());\n    this.trimRecentScte35CueMaps();\n  }\n\n  private trimRecentScte35CueMaps(): void {\n    while (this.recentScte35CueKeys.size > this.recentScte35CueLimit) {\n      const firstKey = this.recentScte35CueKeys.keys().next().value;\n      if (!firstKey) {\n        break;\n      }\n      this.recentScte35CueKeys.delete(firstKey);\n    }\n\n    while (this.pendingScte35Cues.size > this.recentScte35CueLimit) {\n      const firstKey = this.pendingScte35Cues.keys().next().value;\n      if (!firstKey) {\n        break;\n      }\n      this.pendingScte35Cues.delete(firstKey);\n    }\n  }\n\n  private shouldAcceptScte35EndCue(cue: NormalizedScte35Cue): boolean {\n    if (!this.callbacks.isInAdBreak()) {\n      return false;\n    }\n\n    if (\n      this.isStrongScte35CueKey(this.activeScte35BreakKeyValue) &&\n      this.isStrongScte35CueKey(cue.key) &&\n      this.activeScte35BreakKeyValue !== cue.key\n    ) {\n      return false;\n    }\n\n    return true;\n  }\n}\n","import type {\n  StormcloudVideoPlayerConfig,\n  AdBreak,\n  StormcloudApiResponse,\n  AdController,\n} from \"../types\";\nimport type { PalNonceManager } from \"../sdk/pal\";\nimport { applyVastMacros, generateCorrelator, normalizeVastTagUrl } from \"../utils/vastMacros\";\nimport type { VastConsentSignals } from \"../utils/vastMacros\";\nimport { resolveVastEnvironmentSignals } from \"../utils/vastEnvironmentSignals\";\nimport { toDevSafeUrl } from \"../utils/devUrl\";\nimport {\n  buildAnalyticsContext,\n  sendHeartbeat,\n  sendInitialTracking,\n} from \"../utils/tracking\";\nimport { applyMQTTConfig } from \"../utils/mqttConfig\";\n\nexport class AdConfigManager {\n  vmapBreaks: AdBreak[] = [];\n  consumedVmapBreakIds: Set<string> = new Set();\n  apiVastTagUrl: string | undefined;\n  apiNumberAds: number | undefined;\n  readonly streamCorrelator: string = generateCorrelator();\n  readonly viewCorrelator: string = generateCorrelator();\n  consentSignals: VastConsentSignals = {};\n  podCounter: number = 0;\n  podAssignedByPrefetch: boolean = false;\n\n  private lastHeartbeatTime: number = 0;\n  private heartbeatInterval: number | undefined;\n\n  private config: StormcloudVideoPlayerConfig;\n  private video: HTMLVideoElement;\n\n  constructor(config: StormcloudVideoPlayerConfig, video: HTMLVideoElement) {\n    this.config = config;\n    this.video = video;\n  }\n\n  get debug(): boolean {\n    return !!this.config.debugAdTiming;\n  }\n\n  isVmapEnabled(): boolean {\n    return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n  }\n\n  async fetchAdConfiguration(): Promise<void> {\n    if (this.isVmapEnabled()) {\n      await this.fetchAndParseVmap(this.config.vmapUrl!);\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n      }\n      return;\n    }\n\n    const vastMode = this.config.vastMode || \"default\";\n\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n    }\n\n    if (vastMode === \"adstorm\") {\n      if (!this.config.licenseKey) {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n          );\n        }\n        return;\n      }\n\n      const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n      this.apiVastTagUrl = vastEndpoint;\n\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n          vastEndpoint\n        );\n      }\n      return;\n    }\n\n    if (this.config.vastTagUrl) {\n      this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n      return;\n    }\n\n    const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n\n    if (this.debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n        apiUrl\n      );\n    }\n\n    const headers: Record<string, string> = {};\n    if (this.config.licenseKey) {\n      headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n    }\n\n    const response = await fetch(apiUrl, { headers });\n    if (!response.ok) {\n      if (this.debug) {\n        console.warn(\n          `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n        );\n      }\n      return;\n    }\n\n    const data: StormcloudApiResponse = await response.json();\n\n    this.applyMqttConfigFromResponse(data);\n\n    const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n    if (imaPayload) {\n      let decodedPayload = imaPayload;\n      try {\n        decodedPayload = decodeURIComponent(imaPayload);\n      } catch {\n        console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n      }\n      console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n      this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n    } else {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n        );\n      }\n    }\n\n    const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n    if (numberAds != null && numberAds > 0) {\n      this.apiNumberAds = numberAds;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n          this.apiNumberAds\n        );\n      }\n    }\n  }\n\n  private applyMqttConfigFromResponse(data: StormcloudApiResponse): void {\n    const mqttConfig = data.response?.mqtt_config;\n    if (!mqttConfig || typeof mqttConfig !== \"object\") {\n      return;\n    }\n\n    applyMQTTConfig(mqttConfig);\n\n    if (this.debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Applied MQTT config from /ads/web:\",\n        mqttConfig\n      );\n    }\n  }\n\n  private async fetchAndParseVmap(vmapUrl: string): Promise<void> {\n    if (!vmapUrl.trim()) {\n      return;\n    }\n\n    try {\n      const response = await fetch(vmapUrl);\n      if (!response.ok) {\n        throw new Error(`Failed to fetch VMAP (${response.status})`);\n      }\n\n      const vmapXml = await response.text();\n      this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n      this.consumedVmapBreakIds.clear();\n\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n          vmapUrl\n        );\n      }\n    } catch (error) {\n      this.vmapBreaks = [];\n      this.consumedVmapBreakIds.clear();\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n      }\n    }\n  }\n\n  private parseVmapToBreaks(vmapXml: string): AdBreak[] {\n    if (typeof DOMParser === \"undefined\") {\n      return [];\n    }\n\n    const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n    if (doc.querySelector(\"parsererror\")) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n      }\n      return [];\n    }\n\n    const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n    let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(\n        doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n      );\n    }\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n        (el) => el.localName === \"AdBreak\"\n      );\n    }\n    const parsed: AdBreak[] = [];\n\n    adBreakNodes.forEach((node, index) => {\n      const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n      const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n      if (startTimeMs == null) {\n        return;\n      }\n\n      let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n      if (!adTagNode) {\n        adTagNode =\n          (node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") as Element | null) ??\n          undefined;\n      }\n      const adTagUrl = (adTagNode?.textContent || \"\").trim();\n      if (!adTagUrl) {\n        return;\n      }\n\n      const breakId =\n        node.getAttribute(\"breakId\") ||\n        `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n      parsed.push({\n        id: breakId,\n        startTimeMs,\n        vastTagUrl: adTagUrl,\n      });\n    });\n\n    parsed.sort((a, b) => {\n      const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n      const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n      return aStart - bStart;\n    });\n\n    return parsed;\n  }\n\n  private parseVmapTimeOffsetToMs(timeOffset: string): number | undefined {\n    if (!timeOffset) {\n      return undefined;\n    }\n\n    const normalized = timeOffset.trim().toLowerCase();\n    if (normalized === \"start\") {\n      return 0;\n    }\n\n    if (normalized === \"end\") {\n      return -1;\n    }\n\n    const hms = timeOffset.match(\n      /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n    );\n    if (hms) {\n      const [, hh, mm, ss, ms = \"0\"] = hms;\n      const hours = Number(hh);\n      const minutes = Number(mm);\n      const seconds = Number(ss);\n      const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n      return ((hours * 3600 + minutes * 60 + seconds) * 1000) + millis;\n    }\n\n    const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n    if (percent) {\n      const ratio = Number(percent[1]) / 100;\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1000 * ratio);\n      }\n      return undefined;\n    }\n\n    return undefined;\n  }\n\n  getAdBreakKey(adBreak: AdBreak): string {\n    if (adBreak.id) {\n      return adBreak.id;\n    }\n    return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n  }\n\n  resolveBreakStartMs(adBreak: AdBreak): number | undefined {\n    if (adBreak.startTimeMs >= 0) {\n      return adBreak.startTimeMs;\n    }\n\n    if (adBreak.startTimeMs === -1) {\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1000);\n      }\n    }\n\n    return undefined;\n  }\n\n  findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n    const schedule: AdBreak[] = this.vmapBreaks;\n    let candidate: AdBreak | undefined;\n    const tol = this.config.driftToleranceMs ?? 1000;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n      if (\n        breakStartMs <= nowMs + tol &&\n        (candidate == null ||\n          breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))\n      ) {\n        candidate = b;\n      }\n    }\n    return candidate;\n  }\n\n  findBreakForTime(nowMs: number): AdBreak | undefined {\n    const schedule: AdBreak[] = this.vmapBreaks;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n\n      if (b.durationMs) {\n        const end = breakStartMs + b.durationMs;\n        if (nowMs >= breakStartMs && nowMs < end) {\n          return b;\n        }\n        continue;\n      }\n\n      if (nowMs >= breakStartMs) {\n        return b;\n      }\n    }\n    return undefined;\n  }\n\n  selectVastTagsForBreak(b?: AdBreak): string[] | undefined {\n    if (!b || !b.vastTagUrl) return undefined;\n    if (b.vastTagUrl.includes(\",\")) {\n      return b.vastTagUrl\n        .split(\",\")\n        .map((s) => s.trim())\n        .filter((s) => s.length > 0);\n    }\n    return [b.vastTagUrl];\n  }\n\n  beginNewAdPod(): void {\n    this.podCounter++;\n  }\n\n  private readonly defaultPodMaxAds: number = 6;\n  private readonly defaultPodMaxDurationMs: number = 120000;\n\n  resolvePodParams(breakDurationMs?: number): {\n    maxAds: number;\n    minDurationMs: number;\n    maxDurationMs: number;\n  } {\n    const maxDurationMs =\n      breakDurationMs != null && breakDurationMs > 0\n        ? breakDurationMs\n        : this.config.podMaxDurationMs != null && this.config.podMaxDurationMs > 0\n          ? this.config.podMaxDurationMs\n          : this.defaultPodMaxDurationMs;\n\n    const maxAds =\n      this.config.podMaxAds && this.config.podMaxAds > 0\n        ? this.config.podMaxAds\n        : this.apiNumberAds && this.apiNumberAds > 0\n          ? this.apiNumberAds\n          : this.defaultPodMaxAds;\n\n    const minDurationMs =\n      this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;\n\n    return { maxAds, minDurationMs, maxDurationMs };\n  }\n\n  generatePodVastUrl(\n    baseUrl: string,\n    podParams: { maxAds: number; minDurationMs: number; maxDurationMs: number },\n    adPlayer: AdController,\n    palNonce: PalNonceManager,\n    inAdBreak: boolean\n  ): string {\n    const adWillPlayMuted = inAdBreak\n      ? adPlayer.getOriginalMutedState()\n      : this.video.muted;\n    const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n\n    const urlWithMacros = applyVastMacros(baseUrl, {\n      correlator: this.viewCorrelator,\n      streamCorrelator: this.streamCorrelator,\n      pod: this.podCounter > 0 ? this.podCounter : undefined,\n      podMaxAds: podParams.maxAds,\n      podMinDurationMs: podParams.minDurationMs,\n      podMaxDurationMs: podParams.maxDurationMs,\n      isCtv: envSignals.isCtv,\n      contentUrl: envSignals.contentUrl,\n      pageUrl:\n        !envSignals.isCtv && typeof window !== \"undefined\"\n          ? toDevSafeUrl(window.location.href)\n          : undefined,\n      adWillPlayMuted,\n      adWillAutoPlay: !!this.config.autoplay,\n      appId: envSignals.appId,\n      appName: envSignals.appName,\n      sessionId: envSignals.sessionId,\n      deviceId: envSignals.deviceId,\n      deviceIdType: envSignals.deviceIdType,\n      limitAdTracking: envSignals.limitAdTracking,\n      deviceTypeHint: envSignals.deviceTypeHint,\n      adTest: this.config.adTest,\n      consent: this.consentSignals,\n    });\n\n    const finalUrl = palNonce.injectNonce(urlWithMacros);\n    console.log(\n      `[StormcloudVideoPlayer] Resolved optimized-pod request URL (pod=${this.podCounter}, pmad=${podParams.maxAds}, pmnd=${podParams.minDurationMs}, pmxd=${podParams.maxDurationMs ?? \"?\"}):`,\n      finalUrl\n    );\n    return finalUrl;\n  }\n\n  // --- Tracking ---\n\n  initializeTracking(): void {\n    sendInitialTracking(this.config.licenseKey, buildAnalyticsContext(this.config))\n      .then(() => {\n        this.heartbeatInterval = window.setInterval(() => {\n          this.sendHeartbeatIfNeeded();\n        }, 5000);\n      })\n      .catch((error) => {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n            error\n          );\n        }\n        this.heartbeatInterval = window.setInterval(() => {\n          this.sendHeartbeatIfNeeded();\n        }, 5000);\n      });\n  }\n\n  private sendHeartbeatIfNeeded(): void {\n    const now = Date.now();\n    if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n      this.lastHeartbeatTime = now;\n      sendHeartbeat(this.config.licenseKey, buildAnalyticsContext(this.config)).catch((error) => {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n            error\n          );\n        }\n      });\n    }\n  }\n\n  destroyTracking(): void {\n    if (this.heartbeatInterval) {\n      clearInterval(this.heartbeatInterval);\n      this.heartbeatInterval = undefined;\n    }\n  }\n}\n","import type { AdController, StormcloudVideoPlayerConfig, Scte35Marker } from \"../types\";\n\nexport interface AdTimingCallbacks {\n  onAdStopTimerFired(): void;\n  onAdStartTimerFired(marker: Scte35Marker, cueKey: string | undefined): void;\n  onWatchdogTimeout(): void;\n  onFailsafeTimeout(): void;\n}\n\nexport class AdTimingService {\n  private adStopTimerId: number | undefined;\n  private adStartTimerId: number | undefined;\n  private adFailsafeTimerId: number | undefined;\n  private adRequestWatchdogId: number | undefined;\n  private adRequestWatchdogToken: number | null = null;\n  private adFailsafeToken: number | null = null;\n\n  ptsDriftEmaMs = 0;\n  expectedAdBreakDurationMs: number | undefined;\n  currentAdBreakStartWallClockMs: number | undefined;\n  scteAdBreakEndWallClockMs: number | undefined;\n  adBreakPlayedDurationMs: number = 0;\n  adBreakEpoch: number = 0;\n\n  adRequestTokenCounter = 0;\n  activeAdRequestToken: number | null = null;\n  currentAdIndex: number = 0;\n  totalAdsInBreak: number = 0;\n  totalAdRequestsInBreak: number = 0;\n  readonly maxTotalAdRequestsPerBreak: number = 10;\n  lastAdRequestTime: number = 0;\n  consecutiveFailures: number = 0;\n  readonly maxConsecutiveFailures: number = 5;\n  readonly minAdRequestIntervalMs: number = 3000;\n  readonly backoffBaseMs: number = 1000;\n  readonly maxBackoffMs: number = 15000;\n  private readonly defaultMinRemainingMsToStartAd: number = 4000;\n\n  failedVastUrls: Set<string> = new Set();\n  temporaryFailureUrls: Map<string, number> = new Map();\n  private readonly temporaryFailureCooldownMs: number = 30000;\n\n  private globalConsecutiveNoFills: number = 0;\n  private readonly globalNoFillThreshold: number = 3;\n  private globalNoFillCooldownUntil: number = 0;\n  private readonly globalNoFillBackoffBaseMs: number = 5000;\n  private readonly globalNoFillBackoffMaxMs: number = 60000;\n  private globalLastGamRequestTime: number = 0;\n  private readonly globalMinGamIntervalMs: number = 3000;\n\n  private config: StormcloudVideoPlayerConfig;\n  private video: HTMLVideoElement;\n  private callbacks: AdTimingCallbacks;\n\n  constructor(\n    config: StormcloudVideoPlayerConfig,\n    video: HTMLVideoElement,\n    callbacks: AdTimingCallbacks\n  ) {\n    this.config = config;\n    this.video = video;\n    this.callbacks = callbacks;\n  }\n\n  get debug(): boolean {\n    return !!this.config.debugAdTiming;\n  }\n\n  // --- Ad stop timer ---\n\n  scheduleAdStopCountdown(remainingMs: number): void {\n    this.clearAdStopTimer();\n    const ms = Math.max(0, Math.floor(remainingMs));\n    if (ms === 0) {\n      this.ensureAdStoppedByTimer();\n      return;\n    }\n    this.adStopTimerId = window.setTimeout(() => {\n      this.ensureAdStoppedByTimer();\n    }, ms) as unknown as number;\n  }\n\n  clearAdStopTimer(): void {\n    if (this.adStopTimerId != null) {\n      clearTimeout(this.adStopTimerId);\n      this.adStopTimerId = undefined;\n    }\n  }\n\n  private ensureAdStoppedByTimer(): void {\n    this.adStopTimerId = undefined;\n    this.callbacks.onAdStopTimerFired();\n  }\n\n  // --- Ad start timer ---\n\n  scheduleAdStartIn(\n    delayMs: number,\n    marker: Scte35Marker = { type: \"start\" } as Scte35Marker,\n    cueKey?: string\n  ): void {\n    this.clearAdStartTimer();\n    const ms = Math.max(0, Math.floor(delayMs));\n    if (ms === 0) {\n      this.callbacks.onAdStartTimerFired(marker, cueKey);\n      return;\n    }\n    this.adStartTimerId = window.setTimeout(() => {\n      this.callbacks.onAdStartTimerFired(marker, cueKey);\n    }, ms) as unknown as number;\n  }\n\n  clearAdStartTimer(): void {\n    if (this.adStartTimerId != null) {\n      clearTimeout(this.adStartTimerId);\n      this.adStartTimerId = undefined;\n    }\n  }\n\n  // --- PTS drift ---\n\n  updatePtsDrift(ptsSecondsSample: number): void {\n    const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n    if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n    const alpha = 0.1;\n    this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n  }\n\n  resolveScteBreakStartWallClockMs(marker: Scte35Marker): number {\n    const nowWallClockMs = Date.now();\n    if (typeof marker.ptsSeconds !== \"number\") {\n      return nowWallClockMs;\n    }\n\n    const nowMs = this.video.currentTime * 1000;\n    const estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n    const deltaMs = marker.ptsSeconds * 1000 - estimatedCurrentPtsMs;\n    if (!Number.isFinite(deltaMs)) {\n      return nowWallClockMs;\n    }\n\n    return nowWallClockMs + Math.floor(deltaMs);\n  }\n\n  // --- Duration boundary ---\n\n  setAdBreakDurationBoundary(durationMs: number | undefined): void {\n    this.expectedAdBreakDurationMs = durationMs;\n    if (\n      durationMs != null &&\n      this.currentAdBreakStartWallClockMs != null\n    ) {\n      this.scteAdBreakEndWallClockMs =\n        this.currentAdBreakStartWallClockMs + durationMs;\n    } else {\n      this.scteAdBreakEndWallClockMs = undefined;\n    }\n  }\n\n  scheduleAdStopAtBreakBoundary(): void {\n    if (this.expectedAdBreakDurationMs == null) {\n      return;\n    }\n    this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());\n  }\n\n  // --- Duration budget ---\n\n  getWallClockRemainingAdMs(): number {\n    const endWallClockMs = this.getAdBreakEndWallClockMs();\n    if (endWallClockMs != null) {\n      return Math.max(0, endWallClockMs - Date.now());\n    }\n    return 0;\n  }\n\n  getAdBreakEndWallClockMs(): number | undefined {\n    if (this.scteAdBreakEndWallClockMs != null) {\n      return this.scteAdBreakEndWallClockMs;\n    }\n    if (\n      this.expectedAdBreakDurationMs == null ||\n      this.currentAdBreakStartWallClockMs == null\n    ) {\n      return undefined;\n    }\n    return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;\n  }\n\n  getDurationBudgetRemainingMs(): number {\n    if (this.expectedAdBreakDurationMs == null) {\n      return 0;\n    }\n    return Math.max(0, this.expectedAdBreakDurationMs - this.adBreakPlayedDurationMs);\n  }\n\n  getLoadedAdDurationMs(adController: AdController): number {\n    const durationSec = adController.getLoadedAdDuration?.();\n    if (durationSec == null || durationSec <= 0) {\n      return 0;\n    }\n    return Math.round(durationSec * 1000);\n  }\n\n  adFitsRemainingBudget(durationMs: number): boolean {\n    if (durationMs <= 0) {\n      return true;\n    }\n    return durationMs <= this.getDurationBudgetRemainingMs();\n  }\n\n  logAdDurationDecision(\n    accepted: boolean,\n    durationMs: number,\n    adController: AdController\n  ): void {\n    if (!this.debug) {\n      return;\n    }\n    const remainingBudget = this.getDurationBudgetRemainingMs();\n    const adId = adController.getLoadedAdId?.() ?? \"unknown\";\n    if (accepted) {\n      console.log(\n        `[AD-DURATION] Accepted ad id=${adId}, duration=${durationMs}ms, budget remaining after play=${Math.max(0, remainingBudget - durationMs)}ms`\n      );\n    } else {\n      console.log(\n        `[AD-DURATION] Rejected ad id=${adId}, duration=${durationMs}ms exceeds remaining budget=${remainingBudget}ms — requesting another ad`\n      );\n    }\n  }\n\n  recordPlayedAdDuration(adController: AdController): void {\n    const durationMs = this.getLoadedAdDurationMs(adController);\n    if (durationMs <= 0) {\n      return;\n    }\n    this.adBreakPlayedDurationMs += durationMs;\n    if (this.debug) {\n      console.log(\n        `[AD-DURATION] Played ${durationMs}ms — total played=${this.adBreakPlayedDurationMs}ms / ${this.expectedAdBreakDurationMs ?? \"?\"}ms`\n      );\n    }\n  }\n\n  ensureLoadedAdFitsBudget(adController: AdController): boolean {\n    const durationMs = this.getLoadedAdDurationMs(adController);\n    const fits = this.adFitsRemainingBudget(durationMs);\n    this.logAdDurationDecision(fits, durationMs, adController);\n    return fits;\n  }\n\n  rejectLoadedAdForDuration(adController: AdController): void {\n    try {\n      adController.destroy();\n    } catch {}\n  }\n\n  markAdStarted(): void {\n    this.currentAdIndex++;\n    this.totalAdsInBreak = this.currentAdIndex;\n    this.totalAdRequestsInBreak++;\n    this.lastAdRequestTime = Date.now();\n  }\n\n  notePodAdStarted(): void {\n    this.currentAdIndex++;\n    this.totalAdsInBreak = this.currentAdIndex;\n  }\n\n  getRemainingAdMs(): number {\n    const wallClockRemaining = this.getWallClockRemainingAdMs();\n    const budgetRemaining = this.getDurationBudgetRemainingMs();\n    if (this.expectedAdBreakDurationMs == null) {\n      return wallClockRemaining;\n    }\n    return Math.min(wallClockRemaining, budgetRemaining);\n  }\n\n  getMinRemainingMsToStartAd(): number {\n    const configured = this.config.minRemainingMsToStartAd;\n    if (typeof configured === \"number\" && configured >= 0) {\n      return configured;\n    }\n    return this.defaultMinRemainingMsToStartAd;\n  }\n\n  hasTimeToStartAnotherAd(): boolean {\n    const minRemaining = this.getMinRemainingMsToStartAd();\n    return (\n      this.getWallClockRemainingAdMs() > minRemaining &&\n      this.getDurationBudgetRemainingMs() > minRemaining\n    );\n  }\n\n  // --- Circuit breaker ---\n\n  isTemporaryAdError(error: Error): boolean {\n    const message = error?.message?.toLowerCase() || \"\";\n\n    if (message.includes(\"no ads available\") || message.includes(\"no fill\") || message.includes(\"nofill\")) {\n      return true;\n    }\n    if (message.includes(\"timeout\")) {\n      return true;\n    }\n    if (message.includes(\"rate limit\") || message.includes(\"too many requests\")) {\n      return true;\n    }\n    if (message.includes(\"ad playback error\")) {\n      return true;\n    }\n    return false;\n  }\n\n  isUrlInCooldown(vastTagUrl: string): boolean {\n    const failureTime = this.temporaryFailureUrls.get(vastTagUrl);\n    if (failureTime == null) {\n      return false;\n    }\n\n    const elapsed = Date.now() - failureTime;\n    if (elapsed >= this.temporaryFailureCooldownMs) {\n      this.temporaryFailureUrls.delete(vastTagUrl);\n      return false;\n    }\n\n    return true;\n  }\n\n  cleanupTemporaryFailures(): void {\n    const now = Date.now();\n    for (const [url, timestamp] of this.temporaryFailureUrls) {\n      if (now - timestamp >= this.temporaryFailureCooldownMs) {\n        this.temporaryFailureUrls.delete(url);\n      }\n    }\n  }\n\n  isGamInCooldown(): boolean {\n    return Date.now() < this.globalNoFillCooldownUntil;\n  }\n\n  recordGamNoFill(): void {\n    this.globalConsecutiveNoFills++;\n\n    if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {\n      const exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;\n      const backoff = Math.min(\n        this.globalNoFillBackoffBaseMs * Math.pow(2, exponent),\n        this.globalNoFillBackoffMaxMs\n      );\n      this.globalNoFillCooldownUntil = Date.now() + backoff;\n\n      if (this.debug) {\n        console.log(\n          `[CIRCUIT-BREAKER] GAM cooldown activated: ${backoff}ms (${this.globalConsecutiveNoFills} consecutive no-fills)`\n        );\n      }\n    }\n  }\n\n  resetGamNoFillCounter(): void {\n    if (this.globalConsecutiveNoFills > 0 && this.debug) {\n      console.log(\n        `[CIRCUIT-BREAKER] Resetting no-fill counter (was ${this.globalConsecutiveNoFills})`\n      );\n    }\n    this.globalConsecutiveNoFills = 0;\n    this.globalNoFillCooldownUntil = 0;\n  }\n\n  async enforceGlobalRateLimit(): Promise<void> {\n    const now = Date.now();\n    const elapsed = now - this.globalLastGamRequestTime;\n    if (elapsed < this.globalMinGamIntervalMs) {\n      const waitMs = this.globalMinGamIntervalMs - elapsed;\n      if (this.debug) {\n        console.log(`[RATE-LIMIT] Waiting ${waitMs}ms before next GAM request`);\n      }\n      await new Promise(resolve => setTimeout(resolve, waitMs));\n    }\n    this.globalLastGamRequestTime = Date.now();\n  }\n\n  // --- Watchdog ---\n\n  startAdRequestWatchdog(token: number): void {\n    this.clearAdRequestWatchdog();\n\n    const timeoutMs = this.config.adFailsafeTimeoutMs ?? 10000;\n    this.adRequestWatchdogToken = token;\n    this.adRequestWatchdogId = window.setTimeout(() => {\n      if (this.adRequestWatchdogToken !== token) {\n        return;\n      }\n\n      this.adRequestWatchdogId = undefined;\n      this.adRequestWatchdogToken = null;\n      if (this.activeAdRequestToken === token) {\n        this.activeAdRequestToken = null;\n      }\n\n      this.logAdState(\"ad_request_timeout\", { token, timeoutMs });\n      this.callbacks.onWatchdogTimeout();\n    }, timeoutMs) as unknown as number;\n\n    this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n  }\n\n  clearAdRequestWatchdog(): void {\n    if (this.adRequestWatchdogId != null) {\n      clearTimeout(this.adRequestWatchdogId);\n      this.adRequestWatchdogId = undefined;\n    }\n\n    if (this.adRequestWatchdogToken != null) {\n      this.logAdState(\"ad_request_watchdog_cleared\", {\n        token: this.adRequestWatchdogToken,\n      });\n      this.adRequestWatchdogToken = null;\n    }\n  }\n\n  // --- Failsafe ---\n\n  startAdFailsafeTimer(token: number): void {\n    this.clearAdFailsafeTimer();\n\n    const failsafeMs = this.config.adFailsafeTimeoutMs ?? 10000;\n    this.adFailsafeToken = token;\n\n    this.adFailsafeTimerId = window.setTimeout(() => {\n      if (this.adFailsafeToken !== token) {\n        return;\n      }\n\n      this.adFailsafeTimerId = undefined;\n      this.adFailsafeToken = null;\n\n      if (this.activeAdRequestToken === token) {\n        this.activeAdRequestToken = null;\n      }\n\n      this.logAdState(\"ad_failsafe_triggered\", {\n        token,\n        failsafeMs,\n        videoPaused: this.video.paused,\n      });\n\n      this.callbacks.onFailsafeTimeout();\n    }, failsafeMs) as unknown as number;\n\n    this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n  }\n\n  clearAdFailsafeTimer(): void {\n    if (this.adFailsafeTimerId != null) {\n      clearTimeout(this.adFailsafeTimerId);\n      this.logAdState(\"ad_failsafe_cleared\", { token: this.adFailsafeToken });\n      this.adFailsafeTimerId = undefined;\n    }\n\n    this.adFailsafeToken = null;\n  }\n\n  logAdState(event: string, extra: Record<string, unknown> = {}, adPlayer?: AdController, inAdBreak?: boolean, showAds?: boolean): void {\n    if (!this.debug) {\n      return;\n    }\n\n    console.log(\"[StormcloudVideoPlayer][AdState]\", {\n      event,\n      timestamp: new Date().toISOString(),\n      showAds: showAds ?? false,\n      adPlaying: adPlayer?.isAdPlaying() ?? false,\n      inAdBreak: inAdBreak ?? false,\n      activeAdRequestToken: this.activeAdRequestToken,\n      ...extra,\n    });\n  }\n\n  // --- Reset for ad break end ---\n\n  resetForBreakEnd(): void {\n    this.clearAdStopTimer();\n    this.clearAdStartTimer();\n    this.clearAdRequestWatchdog();\n    this.clearAdFailsafeTimer();\n    this.activeAdRequestToken = null;\n    this.expectedAdBreakDurationMs = undefined;\n    this.currentAdBreakStartWallClockMs = undefined;\n    this.scteAdBreakEndWallClockMs = undefined;\n    this.adBreakPlayedDurationMs = 0;\n    this.currentAdIndex = 0;\n    this.totalAdsInBreak = 0;\n    this.consecutiveFailures = 0;\n    this.globalConsecutiveNoFills = 0;\n    this.adBreakEpoch++;\n  }\n\n  destroy(): void {\n    this.clearAdStopTimer();\n    this.clearAdStartTimer();\n    this.clearAdFailsafeTimer();\n    this.clearAdRequestWatchdog();\n  }\n}\n","export class PlaceholderLayer {\n  private container: HTMLDivElement | undefined;\n  private debug: boolean;\n  private video: HTMLVideoElement;\n\n  constructor(video: HTMLVideoElement, debug: boolean) {\n    this.video = video;\n    this.debug = debug;\n  }\n\n  private ensureContainer(): void {\n    if (this.container) {\n      return;\n    }\n\n    const el = document.createElement(\"div\");\n    el.style.position = \"absolute\";\n    el.style.left = \"0\";\n    el.style.top = \"0\";\n    el.style.right = \"0\";\n    el.style.bottom = \"0\";\n    el.style.display = \"none\";\n    el.style.alignItems = \"center\";\n    el.style.justifyContent = \"center\";\n    el.style.pointerEvents = \"none\";\n    el.style.zIndex = \"5\";\n    el.style.backgroundColor = \"#000\";\n    el.style.transition = \"opacity 0.3s ease-in-out\";\n    el.style.opacity = \"0\";\n\n    if (!this.video.parentElement) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n      }\n      return;\n    }\n\n    this.video.parentElement.appendChild(el);\n    this.container = el;\n  }\n\n  show(): void {\n    this.ensureContainer();\n\n    if (!this.container) {\n      return;\n    }\n\n    if (!this.video.muted) {\n      this.video.muted = true;\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n      }\n    }\n\n    const wasHidden = this.container.style.display === \"none\" || this.container.style.opacity === \"0\";\n    if (wasHidden) {\n      this.container.style.transition = \"none\";\n    } else {\n      this.container.style.transition = \"opacity 0.3s ease-in-out\";\n    }\n\n    this.container.style.backgroundColor = \"#000\";\n    this.container.style.display = \"flex\";\n    this.container.offsetHeight;\n    this.container.style.opacity = \"1\";\n    this.container.style.pointerEvents = \"auto\";\n\n    if (wasHidden) {\n      requestAnimationFrame(() => {\n        if (this.container) {\n          this.container.style.transition = \"opacity 0.3s ease-in-out\";\n        }\n      });\n    }\n\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Showing placeholder layer (between content and ad layer)\");\n    }\n  }\n\n  hide(): void {\n    if (!this.container) {\n      return;\n    }\n\n    this.container.style.opacity = \"0\";\n    setTimeout(() => {\n      if (this.container) {\n        this.container.style.display = \"none\";\n        this.container.style.pointerEvents = \"none\";\n        this.container.style.backgroundColor = \"#000\";\n      }\n    }, 300);\n\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n    }\n  }\n\n  destroy(): void {\n    if (this.container) {\n      if (this.container.parentElement) {\n        this.container.parentElement.removeChild(this.container);\n      }\n      this.container = undefined;\n    }\n  }\n}\n","import Hls from \"hls.js\";\nimport type {\n  StormcloudVideoPlayerConfig,\n  Scte35Marker,\n  Id3TagInfo,\n} from \"../types\";\nimport type { Scte35CueContext } from \"./playerTypes\";\nimport {\n  parseScte35FromId3,\n  parseScte35FromTsPackets,\n  normalizeFragmentPayload,\n  getFragmentStartSeconds,\n  parseCueOutDuration,\n  parseCueOutCont,\n  parseAttributeList,\n  toNumber,\n} from \"./Scte35Parser\";\nimport type { Scte35CueManager } from \"./Scte35CueManager\";\nimport type { AdTimingService } from \"./AdTimingService\";\n\nexport interface HlsEngineCallbacks {\n  onManifestParsed(isLive: boolean): Promise<void>;\n  onScte35Cue(marker: Scte35Marker, context: Scte35CueContext): void;\n  activatePendingCuesForFragment(frag: any): void;\n  onFatalDestroy(): void;\n  isInAdBreak(): boolean;\n  hasPendingAdBreak(): boolean;\n}\n\nexport class HlsEngine {\n  hls: Hls | undefined;\n  isLiveStream: boolean = false;\n  nativeHlsMode: boolean = false;\n  videoSrcProtection: string | null = null;\n  reloadingLiveStream: boolean = false;\n\n  private bufferedSegmentsCount: number = 0;\n  private shouldAutoplayAfterBuffering: boolean = false;\n  private hasInitialBufferCompleted: boolean = false;\n\n  private readonly config: StormcloudVideoPlayerConfig;\n  private readonly video: HTMLVideoElement;\n  private readonly cueManager: Scte35CueManager;\n  private readonly timing: AdTimingService;\n  private readonly callbacks: HlsEngineCallbacks;\n\n  constructor(\n    config: StormcloudVideoPlayerConfig,\n    video: HTMLVideoElement,\n    cueManager: Scte35CueManager,\n    timing: AdTimingService,\n    callbacks: HlsEngineCallbacks\n  ) {\n    this.config = config;\n    this.video = video;\n    this.cueManager = cueManager;\n    this.timing = timing;\n    this.callbacks = callbacks;\n  }\n\n  private get debug(): boolean {\n    return !!this.config.debugAdTiming;\n  }\n\n  shouldUseNativeHls(getStreamType: () => \"hls\" | \"other\"): boolean {\n    const streamType = getStreamType();\n    if (streamType === \"other\") {\n      return true;\n    }\n    const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n    return !!(this.config.allowNativeHls && canNative);\n  }\n\n  async setupNativeHls(): Promise<void> {\n    this.nativeHlsMode = true;\n    this.videoSrcProtection = this.config.src;\n    this.video.src = this.config.src;\n\n    this.isLiveStream = this.config.isLiveStream ?? (this.config.lowLatencyMode ?? false);\n\n    if (this.debug) {\n      const adBehavior = this.isLiveStream\n        ? \"live (main video continues muted during ads)\"\n        : \"vod (main video pauses during ads)\";\n      console.log(\n        \"[StormcloudVideoPlayer] Using native HLS playback:\",\n        {\n          isLive: this.isLiveStream,\n          allowNativeHls: this.config.allowNativeHls,\n          adBehavior,\n        }\n      );\n    }\n\n    if (this.config.autoplay) {\n      await this.video.play()?.catch(() => {});\n    }\n  }\n\n  setupHls(): void {\n    this.hls = new Hls({\n      enableWorker: true,\n      backBufferLength: 30,\n      liveDurationInfinity: true,\n      lowLatencyMode: !!this.config.lowLatencyMode,\n      maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n      ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n      maxBufferLength: 30,\n      maxMaxBufferLength: 600,\n      maxBufferSize: 60 * 1000 * 1000,\n      maxBufferHole: 0.5,\n      highBufferWatchdogPeriod: 2,\n      nudgeOffset: 0.1,\n      nudgeMaxRetry: 3,\n      startPosition: -1,\n    });\n\n    this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n      this.hls?.loadSource(this.config.src);\n    });\n\n    this.hls.on(Hls.Events.MANIFEST_PARSED, async (_, _data: any) => {\n      this.isLiveStream =\n        this.config.isLiveStream ??\n        (this.hls?.levels?.some(\n          (level) =>\n            level?.details?.live === true || level?.details?.type === \"LIVE\"\n        ) ?? false);\n\n      await this.callbacks.onManifestParsed(this.isLiveStream);\n\n      this.bufferedSegmentsCount = 0;\n      this.hasInitialBufferCompleted = false;\n      this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n      const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Waiting for\",\n          minSegments,\n          \"segments to buffer before playback\"\n        );\n      }\n\n      if (minSegments === 0 || !this.config.autoplay) {\n        this.hasInitialBufferCompleted = true;\n        if (this.config.autoplay) {\n          await this.video.play()?.catch(() => {});\n        }\n      }\n\n      this.reloadingLiveStream = false;\n    });\n\n    this.hls.on(Hls.Events.LEVEL_LOADED, (_evt, data: any) => {\n      if (this.callbacks.isInAdBreak() || this.callbacks.hasPendingAdBreak()) {\n        return;\n      }\n\n      const details = data?.details;\n      if (!details || !details.fragments || details.fragments.length === 0) {\n        return;\n      }\n\n      const fragmentsToScan = Math.min(5, details.fragments.length);\n\n      for (let i = 0; i < fragmentsToScan; i++) {\n        const frag = details.fragments[i];\n        const tagList: any[] | undefined = frag?.tagList;\n\n        if (!Array.isArray(tagList)) continue;\n\n        for (const entry of tagList) {\n          let tag = \"\";\n          let value = \"\";\n\n          if (Array.isArray(entry)) {\n            tag = String(entry[0] ?? \"\");\n            value = String(entry[1] ?? \"\");\n          } else if (typeof entry === \"string\") {\n            const idx = entry.indexOf(\":\");\n            if (idx >= 0) {\n              tag = entry.substring(0, idx);\n              value = entry.substring(idx + 1);\n            } else {\n              tag = entry;\n            }\n          }\n\n          if (!tag) continue;\n\n          if (tag.includes(\"EXT-X-CUE-OUT\") || tag.includes(\"EXT-X-DATERANGE\")) {\n            const attrs = tag.includes(\"EXT-X-DATERANGE\")\n              ? parseAttributeList(value)\n              : {};\n            const hasScteOut = tag.includes(\"EXT-X-CUE-OUT\") ||\n              \"SCTE35-OUT\" in attrs ||\n              attrs[\"SCTE35-OUT\"] !== undefined;\n\n            if (hasScteOut) {\n              const durationSeconds = parseCueOutDuration(value);\n              const marker: Scte35Marker = {\n                type: \"start\",\n                ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n                raw: { tag, value, earlyDetection: true },\n              } as Scte35Marker;\n\n              if (this.debug) {\n                console.log(\"[StormcloudVideoPlayer] EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n              }\n\n              this.callbacks.onScte35Cue(marker, {\n                ...this.cueManager.createScte35CueContext(\"manifest\", \"early\", frag),\n              });\n              return;\n            }\n          }\n        }\n      }\n    });\n\n    this.hls.on(Hls.Events.FRAG_BUFFERED, async (_evt, _data: any) => {\n      if (this.hasInitialBufferCompleted) {\n        return;\n      }\n\n      this.bufferedSegmentsCount++;\n      const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n        );\n      }\n\n      if (this.bufferedSegmentsCount >= minSegments) {\n        this.hasInitialBufferCompleted = true;\n\n        if (this.shouldAutoplayAfterBuffering) {\n          if (this.debug) {\n            console.log(\n              `[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`\n            );\n          }\n          await this.video.play()?.catch((err) => {\n            if (this.debug) {\n              console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n            }\n          });\n        }\n      }\n    });\n\n    this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n      const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n        key: \"ID3\",\n        value: s?.data,\n        ptsSeconds: s?.pts,\n      }));\n      id3Tags.forEach((tag) => this.onId3Tag(tag));\n    });\n\n    this.hls.on(Hls.Events.FRAG_LOADED, (_evt, data: any) => {\n      this.processFragmentScte35Payload(\n        data?.payload,\n        typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n        getFragmentStartSeconds(data?.frag)\n      );\n    });\n\n    this.hls.on(Hls.Events.FRAG_DECRYPTED, (_evt, data: any) => {\n      this.processFragmentScte35Payload(\n        data?.payload,\n        typeof data?.frag?.sn === \"number\" ? data.frag.sn : undefined,\n        getFragmentStartSeconds(data?.frag)\n      );\n    });\n\n    this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n      const frag = data?.frag;\n      const tagList: any[] | undefined = frag?.tagList;\n      if (!Array.isArray(tagList)) {\n        this.callbacks.activatePendingCuesForFragment(frag);\n        return;\n      }\n\n      for (const entry of tagList) {\n        let tag = \"\";\n        let value = \"\";\n        if (Array.isArray(entry)) {\n          tag = String(entry[0] ?? \"\");\n          value = String(entry[1] ?? \"\");\n        } else if (typeof entry === \"string\") {\n          const idx = entry.indexOf(\":\");\n          if (idx >= 0) {\n            tag = entry.substring(0, idx);\n            value = entry.substring(idx + 1);\n          } else {\n            tag = entry;\n            value = \"\";\n          }\n        }\n\n        if (!tag) continue;\n        if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n          const prog = parseCueOutCont(value);\n          const marker: Scte35Marker = {\n            type: \"progress\",\n            ...(prog?.duration !== undefined\n              ? { durationSeconds: prog.duration }\n              : {}),\n            ...(prog?.elapsed !== undefined\n              ? { ptsSeconds: prog.elapsed }\n              : {}),\n            raw: { tag, value },\n          } as Scte35Marker;\n          this.callbacks.onScte35Cue(marker, {\n            ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n          });\n        } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n          const durationSeconds = parseCueOutDuration(value);\n          const marker: Scte35Marker = {\n            type: \"start\",\n            ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n            raw: { tag, value },\n          } as Scte35Marker;\n          this.callbacks.onScte35Cue(marker, {\n            ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n          });\n        } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n          this.callbacks.onScte35Cue(\n            { type: \"end\", raw: { tag, value } },\n            {\n              ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n            }\n          );\n        } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n          const attrs = parseAttributeList(value);\n          const hasScteOut =\n            \"SCTE35-OUT\" in attrs || attrs[\"SCTE35-OUT\"] !== undefined;\n          const hasScteIn =\n            \"SCTE35-IN\" in attrs || attrs[\"SCTE35-IN\"] !== undefined;\n          const klass = String(attrs[\"CLASS\"] ?? \"\");\n          const duration = toNumber(attrs[\"DURATION\"]);\n\n          if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n            const marker: Scte35Marker = {\n              type: \"start\",\n              ...(duration !== undefined ? { durationSeconds: duration } : {}),\n              raw: { tag, value, attrs },\n            } as Scte35Marker;\n            this.callbacks.onScte35Cue(marker, {\n              ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n            });\n          }\n          if (hasScteIn) {\n            this.callbacks.onScte35Cue(\n              { type: \"end\", raw: { tag, value, attrs } },\n              {\n                ...this.cueManager.createScte35CueContext(\"manifest\", \"playback\", frag),\n              }\n            );\n          }\n        }\n      }\n      this.callbacks.activatePendingCuesForFragment(frag);\n    });\n\n    this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n      if (data?.fatal) {\n        switch (data.type) {\n          case Hls.ErrorTypes.NETWORK_ERROR:\n            this.hls?.startLoad();\n            break;\n          case Hls.ErrorTypes.MEDIA_ERROR:\n            this.hls?.recoverMediaError();\n            break;\n          default:\n            this.callbacks.onFatalDestroy();\n            break;\n        }\n      }\n    });\n\n    this.hls.attachMedia(this.video);\n  }\n\n  private onId3Tag(tag: Id3TagInfo): void {\n    if (typeof tag.ptsSeconds === \"number\") {\n      this.timing.updatePtsDrift(tag.ptsSeconds);\n    }\n    const marker = parseScte35FromId3(tag);\n    if (marker) {\n      this.callbacks.onScte35Cue(marker, {\n        source: \"id3\",\n        readiness: \"playback\",\n      });\n    }\n  }\n\n  private processFragmentScte35Payload(\n    payloadData: unknown,\n    fragmentSn?: number,\n    fragmentStartSeconds?: number\n  ): void {\n    const payload = normalizeFragmentPayload(payloadData);\n    if (!payload) {\n      return;\n    }\n\n    const markers = parseScte35FromTsPackets(\n      payload,\n      this.cueManager.tsScte35Pids,\n      this.cueManager.pmtPids,\n      this.cueManager.processedTsScte35Sections\n    );\n    markers.forEach((marker) => {\n      const context: Scte35CueContext = {\n        source: \"ts\",\n        readiness: \"early\",\n      };\n      if (fragmentSn !== undefined) {\n        context.fragmentSn = fragmentSn;\n      }\n      if (fragmentStartSeconds !== undefined) {\n        context.fragmentStartSeconds = fragmentStartSeconds;\n      }\n      this.callbacks.onScte35Cue(marker, context);\n    });\n  }\n\n  getLiveSyncPosition(): number | undefined {\n    const pos = this.hls?.liveSyncPosition;\n    return typeof pos === \"number\" && Number.isFinite(pos) ? pos : undefined;\n  }\n\n  restartLoadAt(position: number): void {\n    if (!this.hls) {\n      return;\n    }\n    try {\n      this.hls.stopLoad();\n      this.hls.startLoad(position);\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to restart HLS load at live edge:\", error);\n      }\n    }\n  }\n\n  recoverMediaError(): void {\n    if (!this.hls) {\n      return;\n    }\n    try {\n      this.hls.recoverMediaError();\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] recoverMediaError() failed:\", error);\n      }\n    }\n  }\n\n  reloadLiveStream(): void {\n    const hls = this.hls;\n    if (!hls) {\n      return;\n    }\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Hard-reloading live stream (detach → reset video → re-attach)\");\n    }\n    try {\n      this.reloadingLiveStream = true;\n      hls.stopLoad();\n      hls.detachMedia();\n      try {\n        this.video.removeAttribute(\"src\");\n        this.video.load();\n      } catch (error) {\n        console.warn(\"[StormcloudVideoPlayer] video.load() threw after src removal:\", error);\n      }\n      hls.attachMedia(this.video);\n    } catch (error) {\n      this.reloadingLiveStream = false;\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to hard-reload live stream:\", error);\n      }\n    }\n  }\n\n  destroy(): void {\n    this.hls?.destroy();\n    this.hls = undefined;\n  }\n}\n","import type { AdController } from \"../types\";\n\nexport function getAdAudioVolume(adPlayer: AdController): number {\n  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();\n}\n\nexport function toggleMute(\n  video: HTMLVideoElement,\n  adPlayer: AdController,\n  debug: boolean\n): void {\n  if (adPlayer.isAdPlaying()) {\n    const newMutedState = !adPlayer.getOriginalMutedState();\n    const restoreVolume = adPlayer.getOriginalVolume() || 1;\n\n    adPlayer.updateOriginalMutedState(newMutedState, video.volume);\n    adPlayer.setAdVolume(newMutedState ? 0 : restoreVolume);\n\n    if (debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n        newMutedState\n      );\n    }\n  } else {\n    video.muted = !video.muted;\n    adPlayer.updateOriginalMutedState(video.muted, video.volume);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] Muted:\", video.muted);\n    }\n  }\n}\n\nexport function toggleFullscreen(\n  video: HTMLVideoElement,\n  debug: boolean\n): Promise<void> {\n  return new Promise((resolve, reject) => {\n    if (!document.fullscreenElement) {\n      const container = video.parentElement;\n      if (!container) {\n        reject(new Error(\"No parent container found for fullscreen\"));\n        return;\n      }\n      container\n        .requestFullscreen()\n        .then(() => {\n          if (debug) {\n            console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n          }\n          resolve();\n        })\n        .catch((err) => {\n          if (debug) {\n            console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n          }\n          reject(err);\n        });\n    } else {\n      document\n        .exitFullscreen()\n        .then(() => {\n          if (debug) {\n            console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n          }\n          resolve();\n        })\n        .catch((err) => {\n          if (debug) {\n            console.error(\n              \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n              err\n            );\n          }\n          reject(err);\n        });\n    }\n  });\n}\n\nexport function isMuted(\n  video: HTMLVideoElement,\n  adPlayer: AdController\n): boolean {\n  if (adPlayer.isAdPlaying()) {\n    return adPlayer.getOriginalMutedState();\n  }\n  return video.muted;\n}\n\nexport function setMuted(\n  video: HTMLVideoElement,\n  adPlayer: AdController,\n  muted: boolean,\n  debug: boolean\n): void {\n  const adPlaying = adPlayer.isAdPlaying();\n\n  if (adPlaying && muted === video.muted) {\n    if (debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n        { muted }\n      );\n    }\n    return;\n  }\n\n  video.muted = muted;\n\n  if (adPlaying) {\n    adPlayer.updateOriginalMutedState(muted, video.volume);\n    adPlayer.setAdVolume(muted ? 0 : 1);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n        muted,\n      });\n    }\n    return;\n  }\n\n  adPlayer.updateOriginalMutedState(muted, video.volume);\n  if (debug) {\n    console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n  }\n}\n\nexport function setVolume(\n  video: HTMLVideoElement,\n  adPlayer: AdController,\n  volume: number,\n  debug: boolean\n): void {\n  const clampedVolume = Math.max(0, Math.min(1, volume));\n  const adPlaying = adPlayer.isAdPlaying();\n\n  if (adPlaying) {\n    adPlayer.setAdVolume(clampedVolume);\n    adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n        volume: clampedVolume,\n      });\n    }\n  } else {\n    video.volume = clampedVolume;\n    video.muted = clampedVolume === 0;\n    adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n    if (debug) {\n      console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n    }\n  }\n}\n\nexport function getVolume(\n  video: HTMLVideoElement,\n  adPlayer: AdController\n): number {\n  const adPlaying = adPlayer.isAdPlaying();\n  if (adPlaying) {\n    return adPlayer.getAdVolume();\n  }\n  return video.volume;\n}\n\nexport function isFullscreen(): boolean {\n  return !!document.fullscreenElement;\n}\n\nexport function resizePlayer(\n  video: HTMLVideoElement,\n  adPlayer: AdController,\n  debug: boolean\n): void {\n  if (debug) {\n    console.log(\"[StormcloudVideoPlayer] Resizing player\");\n  }\n\n  if (adPlayer && adPlayer.isAdPlaying()) {\n    const width = video.clientWidth || 640;\n    const height = video.clientHeight || 480;\n\n    if (debug) {\n      console.log(\n        `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n      );\n    }\n\n    adPlayer.resize(width, height);\n  }\n}\n","import type {\n  StormcloudVideoPlayerConfig,\n  Scte35Marker,\n  AdController,\n} from \"../types\";\nimport {\n  buildAnalyticsContext,\n  sendAdLoadedTracking,\n  sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport type { AdTimingService } from \"./AdTimingService\";\nimport type { AdConfigManager } from \"./AdConfigManager\";\nimport type { Scte35CueManager } from \"./Scte35CueManager\";\nimport type { PlaceholderLayer } from \"./PlaceholderLayer\";\nimport { getAdAudioVolume } from \"./PlayerControls\";\n\nexport interface AdBreakOrchestratorHost {\n  readonly config: StormcloudVideoPlayerConfig;\n  readonly video: HTMLVideoElement;\n  getAdPlayer(): AdController;\n  setAdPlayer(player: AdController): void;\n  createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;\n  shouldContinueLiveStreamDuringAds(): boolean;\n  isLiveStream(): boolean;\n  getLiveSyncPosition(): number | undefined;\n  restartHlsLoad(position: number): void;\n  reloadLiveStream(): void;\n  recoverMediaError(): void;\n  generatePodVastUrl(baseUrl: string, breakDurationMs?: number): string;\n}\n\nexport class AdBreakOrchestrator {\n  inAdBreak = false;\n  showAds: boolean = false;\n  isShowingPlaceholder: boolean = false;\n  adDetectSentForCurrentBreak: boolean = false;\n\n  private continuousFetchingActive: boolean = false;\n  private continuousFetchLoopRunning = false;\n  adRequestQueue: string[] = [];\n  adPodQueue: string[] = [];\n  private readonly maxPlaceholderDurationMs: number = 5000;\n\n  pendingAdBreak: {\n    marker: Scte35Marker;\n    detectedAtFragmentSn?: number;\n    vastUrls: string[];\n    isFetching: boolean;\n    fetchStartTime?: number;\n  } | null = null;\n  prefetchTimerId: number | undefined;\n\n  private readonly host: AdBreakOrchestratorHost;\n  private readonly timing: AdTimingService;\n  private readonly adConfig: AdConfigManager;\n  private readonly cueManager: Scte35CueManager;\n  private readonly placeholder: PlaceholderLayer;\n\n  constructor(\n    host: AdBreakOrchestratorHost,\n    timing: AdTimingService,\n    adConfig: AdConfigManager,\n    cueManager: Scte35CueManager,\n    placeholder: PlaceholderLayer\n  ) {\n    this.host = host;\n    this.timing = timing;\n    this.adConfig = adConfig;\n    this.cueManager = cueManager;\n    this.placeholder = placeholder;\n  }\n\n  private get debug(): boolean {\n    return !!this.host.config.debugAdTiming;\n  }\n\n  private get analyticsContext() {\n    return buildAnalyticsContext(this.host.config);\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  IMA event listeners\n  // ───────────────────────────────────────────────────────────────\n\n  private nextAdRequestUrl(baseVastUrl: string): string {\n    const remaining = Math.min(\n      this.timing.getWallClockRemainingAdMs(),\n      this.timing.getDurationBudgetRemainingMs()\n    );\n    const breakDurationMs = remaining > 0 ? remaining : undefined;\n    return this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);\n  }\n\n  attachImaEventListeners(): void {\n    const adPlayer = this.host.getAdPlayer();\n    adPlayer.on(\"pod_ad_started\", (payload?: any) => {\n      this.timing.notePodAdStarted();\n      if (this.debug) {\n        console.log(\n          `[POD] Playing pod ad ${payload?.index != null ? payload.index + 1 : \"?\"}/${payload?.total ?? \"?\"}`\n        );\n      }\n    });\n    adPlayer.on(\"all_ads_completed\", () => {\n      sendAdImpressionTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: new Date().toISOString() },\n        this.analyticsContext\n      ).catch(() => {});\n\n      this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n      const remaining = this.timing.getRemainingAdMs();\n\n      this.timing.consecutiveFailures = 0;\n\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] all_ads_completed event received - remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n          this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n        );\n      }\n\n      if (this.inAdBreak) {\n        if (this.timing.hasTimeToStartAnotherAd()) {\n          this.tryNextAvailableAdWithRateLimit();\n        } else {\n          this.handleAdPodComplete();\n        }\n      }\n    });\n    adPlayer.on(\"ad_error\", (errorPayload?: any) => {\n      let errorMessage = \"Ad playback failed\";\n\n      if (errorPayload) {\n        const errorCode = errorPayload.code || errorPayload.errorCode || \"unknown\";\n        const vastErrorCode = errorPayload.vastErrorCode;\n        const message = errorPayload.message || errorPayload.errorMessage || \"Unknown error\";\n        const cause = errorPayload.cause || errorPayload.innerError || errorPayload.error;\n\n        errorMessage = `Ad error: AdError ${errorCode}: ${message}`;\n\n        if (vastErrorCode && vastErrorCode !== \"N/A\" && vastErrorCode !== errorCode) {\n          errorMessage += ` (VAST Error Code: ${vastErrorCode})`;\n        }\n\n        if (cause) {\n          const causeMessage = typeof cause === \"string\" ? cause : (cause.message || String(cause));\n          errorMessage += `. Caused by: ${causeMessage}`;\n        }\n      }\n\n      console.error(\"[AD-ERROR]\", errorMessage, errorPayload || \"\");\n      this.handleAdFailure();\n    });\n    adPlayer.on(\"content_pause\", () => {\n      this.timing.clearAdFailsafeTimer();\n      this.timing.clearAdRequestWatchdog();\n      this.timing.activeAdRequestToken = null;\n      this.showAds = true;\n      this.timing.resetGamNoFillCounter();\n\n      if (this.inAdBreak && this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n        this.timing.scheduleAdStopAtBreakBoundary();\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n        }\n      }\n\n      this.host.getAdPlayer().setAdVolume(getAdAudioVolume(this.host.getAdPlayer()));\n\n      if (this.isShowingPlaceholder) {\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n        }\n        this.host.getAdPlayer().hidePlaceholder();\n        this.isShowingPlaceholder = false;\n      }\n    });\n    adPlayer.on(\"content_resume\", () => {\n      sendAdImpressionTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", adIndex: this.timing.currentAdIndex, timestamp: new Date().toISOString() },\n        this.analyticsContext\n      ).catch(() => {});\n\n      if (!this.host.video.muted) {\n        this.host.video.muted = true;\n        if (this.debug) {\n          console.log(\"[StormcloudVideoPlayer] Muted video on content_resume (ad ended, gap between ads)\");\n        }\n      }\n\n      this.timing.clearAdFailsafeTimer();\n      this.timing.clearAdRequestWatchdog();\n      this.timing.activeAdRequestToken = null;\n      this.showAds = false;\n\n      if (!this.inAdBreak) {\n        return;\n      }\n\n      this.timing.consecutiveFailures = 0;\n\n      this.timing.recordPlayedAdDuration(this.host.getAdPlayer());\n      const remaining = this.timing.getRemainingAdMs();\n\n      if (this.debug) {\n        console.log(\n          `[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`,\n          this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n        );\n      }\n\n      if (this.timing.hasTimeToStartAnotherAd()) {\n        this.tryNextAvailableAdWithRateLimit();\n      } else {\n        this.handleAdPodComplete();\n      }\n    });\n  }\n\n  recreateAdController(): void {\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Recreating AdController for new ad\");\n    }\n\n    const shouldShowPlaceholder = this.inAdBreak && this.showAds;\n    const adPlayer = this.host.getAdPlayer();\n    if (shouldShowPlaceholder && adPlayer) {\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] Showing placeholder before destroying old AdController\");\n      }\n      this.placeholder.show();\n      adPlayer.showPlaceholder();\n      this.isShowingPlaceholder = true;\n    }\n\n    const preservedMutedState = adPlayer.getOriginalMutedState();\n    const preservedVolumeState = adPlayer.getOriginalVolume();\n\n    if (adPlayer) {\n      try {\n        adPlayer.destroy();\n        this.host.video.muted = true;\n      } catch (error) {\n        if (this.debug) {\n          console.warn(\"[StormcloudVideoPlayer] Error destroying old AdController:\", error);\n        }\n      }\n    }\n\n    const continueLiveStreamDuringAds = this.host.shouldContinueLiveStreamDuringAds();\n    const newAdPlayer = this.host.createAdPlayer(continueLiveStreamDuringAds);\n    this.host.setAdPlayer(newAdPlayer);\n\n    newAdPlayer.initialize();\n    newAdPlayer.updateOriginalMutedState(preservedMutedState, preservedVolumeState);\n    this.attachImaEventListeners();\n\n    if (shouldShowPlaceholder) {\n      this.placeholder.show();\n      newAdPlayer.showPlaceholder();\n      this.isShowingPlaceholder = true;\n    }\n  }\n\n  clearPendingAdBreak(): void {\n    if (this.prefetchTimerId != null) {\n      clearTimeout(this.prefetchTimerId);\n      this.prefetchTimerId = undefined;\n    }\n    this.pendingAdBreak = null;\n    this.cueManager.pendingScte35CueKey = undefined;\n    this.adConfig.podAssignedByPrefetch = false;\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Ad break start\n  // ───────────────────────────────────────────────────────────────\n\n  async handleAdStart(_marker: Scte35Marker): Promise<void> {\n    const scheduled = this.adConfig.findCurrentOrNextBreak(\n      this.host.video.currentTime * 1000\n    );\n    if (scheduled) {\n      this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));\n    }\n    const tags = this.adConfig.selectVastTagsForBreak(scheduled);\n\n    let baseVastUrl: string;\n\n    if (tags && tags.length > 0 && tags[0]) {\n      baseVastUrl = tags[0];\n    } else if (this.adConfig.apiVastTagUrl) {\n      baseVastUrl = this.adConfig.apiVastTagUrl;\n    } else {\n      this.clearPendingAdBreak();\n      return;\n    }\n\n    const adBreakDurationMs =\n      _marker.durationSeconds != null\n        ? _marker.durationSeconds * 1000\n        : scheduled?.durationMs;\n\n    if (this.debug) {\n      const mode = this.host.config.isLiveStream ? \"LIVE\" : \"VOD\";\n      console.log(\n        `[CONTINUOUS-FETCH] ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n      );\n    }\n\n    this.timing.failedVastUrls.clear();\n    this.timing.temporaryFailureUrls.clear();\n    this.timing.consecutiveFailures = 0;\n    this.continuousFetchingActive = true;\n    this.isShowingPlaceholder = false;\n    this.timing.totalAdRequestsInBreak = 0;\n\n    if (this.adConfig.podAssignedByPrefetch) {\n      this.adConfig.podAssignedByPrefetch = false;\n    } else {\n      this.adConfig.beginNewAdPod();\n    }\n\n    const currentMuted = this.host.video.muted;\n    const currentVolume = this.host.video.volume;\n    this.host.getAdPlayer().updateOriginalMutedState(currentMuted, currentVolume);\n\n    this.inAdBreak = true;\n    this.timing.adBreakPlayedDurationMs = 0;\n    this.timing.currentAdIndex = 0;\n    this.timing.totalAdsInBreak = 0;\n    this.adPodQueue = [];\n    this.showAds = false;\n\n    if (\n      this.timing.expectedAdBreakDurationMs == null &&\n      adBreakDurationMs != null\n    ) {\n      this.timing.expectedAdBreakDurationMs = adBreakDurationMs;\n    }\n\n    const podPlayed = await this.startOptimizedPod(\n      baseVastUrl,\n      adBreakDurationMs,\n      currentMuted,\n      currentVolume\n    );\n\n    if (!podPlayed) {\n      if (this.debug) {\n        console.log(\"[POD] Initial pod request did not fill; attempting top-up pod request\");\n      }\n      this.continuousFetchingActive = true;\n      this.startContinuousFetching(baseVastUrl);\n      await this.tryNextAvailableAdWithRateLimit();\n    }\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Optimized pod (single multi-ad request)\n  // ───────────────────────────────────────────────────────────────\n\n  private async startOptimizedPod(\n    baseVastUrl: string,\n    breakDurationMs: number | undefined,\n    currentMuted: boolean,\n    currentVolume: number\n  ): Promise<boolean> {\n    let podUrl: string | undefined;\n    if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n      podUrl = this.pendingAdBreak.vastUrls[0];\n      this.clearPendingAdBreak();\n    } else {\n      podUrl = this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);\n    }\n\n    if (!podUrl) {\n      return false;\n    }\n\n    this.continuousFetchingActive = false;\n\n    this.recreateAdController();\n\n    const adPlayer = this.host.getAdPlayer();\n    const requestToken = ++this.timing.adRequestTokenCounter;\n    this.timing.activeAdRequestToken = requestToken;\n    this.timing.startAdRequestWatchdog(requestToken);\n\n    try {\n      await this.timing.enforceGlobalRateLimit();\n      this.timing.lastAdRequestTime = Date.now();\n      await adPlayer.requestAds(podUrl);\n      this.timing.clearAdRequestWatchdog();\n\n      if (this.timing.activeAdRequestToken !== requestToken) {\n        return true;\n      }\n\n      const podCount = adPlayer.getPodAdCount?.() ?? 1;\n      if (podCount < 1) {\n        return false;\n      }\n\n      if (this.debug) {\n        console.log(\n          podCount === 1\n            ? \"[POD] Response contained a single ad; playing it and enabling pod top-up\"\n            : `[POD] Optimized pod returned ${podCount} ads; playing pod in one controller`\n        );\n      }\n\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: podUrl, timestamp: new Date().toISOString() },\n        this.analyticsContext\n      ).catch(() => {});\n\n      this.timing.startAdFailsafeTimer(requestToken);\n      await adPlayer.play();\n      this.timing.markAdStarted();\n\n      if (\n        this.timing.expectedAdBreakDurationMs != null &&\n        this.timing.getAdBreakEndWallClockMs() == null\n      ) {\n        this.timing.scheduleAdStopAtBreakBoundary();\n      }\n\n      adPlayer.setAdVolume(currentMuted ? 0 : currentVolume);\n      this.timing.consecutiveFailures = 0;\n\n      this.continuousFetchingActive = true;\n      this.startContinuousFetching(baseVastUrl);\n\n      return true;\n    } catch (error) {\n      this.timing.clearAdRequestWatchdog();\n      this.timing.clearAdFailsafeTimer();\n      if (this.timing.activeAdRequestToken === requestToken) {\n        this.timing.activeAdRequestToken = null;\n      }\n      if (this.debug) {\n        console.warn(\"[POD] Optimized pod request/play failed:\", error);\n      }\n\n      if (this.timing.isTemporaryAdError(error as Error)) {\n        this.timing.temporaryFailureUrls.set(podUrl, Date.now());\n      }\n\n      this.continuousFetchingActive = true;\n      this.recreateAdController();\n      return false;\n    }\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Continuous fetching\n  // ───────────────────────────────────────────────────────────────\n\n  private startContinuousFetching(baseVastUrl: string): void {\n    if (!this.continuousFetchingActive) {\n      return;\n    }\n\n    if (this.continuousFetchLoopRunning) {\n      if (this.debug) {\n        console.log(\"[CONTINUOUS-FETCH] Fetch loop already running, skipping duplicate start\");\n      }\n      return;\n    }\n\n    if (this.debug) {\n      console.log(\"[CONTINUOUS-FETCH] Starting continuous ad fetching loop\");\n    }\n\n    this.continuousFetchLoopRunning = true;\n    this.continuousFetchLoop(baseVastUrl);\n  }\n\n  private async continuousFetchLoop(baseVastUrl: string): Promise<void> {\n    const epoch = this.timing.adBreakEpoch;\n    while (\n      this.continuousFetchingActive &&\n      this.inAdBreak &&\n      epoch === this.timing.adBreakEpoch\n    ) {\n      const remaining = Math.min(\n        this.timing.getWallClockRemainingAdMs(),\n        this.timing.getDurationBudgetRemainingMs()\n      );\n\n      if (remaining <= this.timing.getMinRemainingMsToStartAd()) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] Not enough ad break time left (wall=${this.timing.getWallClockRemainingAdMs()}ms, budget=${this.timing.getDurationBudgetRemainingMs()}ms), stopping URL generation`);\n        }\n        break;\n      }\n\n      if (this.timing.isGamInCooldown()) {\n        if (this.debug) {\n          console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation\");\n        }\n        break;\n      }\n\n      if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), stopping URL generation`);\n        }\n        break;\n      }\n\n      if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] Maximum ad requests reached (${this.timing.maxTotalAdRequestsPerBreak}), stopping`);\n        }\n        break;\n      }\n\n      const maxQueueSize = 5;\n      if (this.adRequestQueue.length >= maxQueueSize) {\n        if (this.debug) {\n          console.log(`[CONTINUOUS-FETCH] URL queue full (${this.adRequestQueue.length}), waiting...`);\n        }\n        await new Promise(resolve => setTimeout(resolve, 1000));\n        continue;\n      }\n\n      const newAdUrl = this.nextAdRequestUrl(baseVastUrl);\n\n      if (!newAdUrl || this.timing.failedVastUrls.has(newAdUrl) || this.timing.isUrlInCooldown(newAdUrl)) {\n        await new Promise(resolve => setTimeout(resolve, 500));\n        continue;\n      }\n\n      if (this.debug) {\n        const queuedUrlsPreview = [...this.adRequestQueue, newAdUrl];\n        console.log(\n          `[CONTINUOUS-FETCH] Queued VAST URL (queue size: ${queuedUrlsPreview.length})`,\n          { queuedUrls: queuedUrlsPreview }\n        );\n      }\n\n      this.adRequestQueue.push(newAdUrl);\n\n      const generationDelay = this.timing.consecutiveFailures > 0\n        ? Math.min(1000 * Math.pow(2, this.timing.consecutiveFailures), 5000)\n        : 500;\n      await new Promise(resolve => setTimeout(resolve, generationDelay));\n    }\n\n    this.continuousFetchLoopRunning = false;\n\n    if (this.debug) {\n      console.log(\n        `[CONTINUOUS-FETCH] URL generation loop ended (queued: ${this.adRequestQueue.length})`,\n        this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n      );\n    }\n  }\n\n  stopContinuousFetching(): void {\n    this.continuousFetchingActive = false;\n    this.continuousFetchLoopRunning = false;\n\n    this.placeholder.hide();\n\n    if (this.debug) {\n      console.log(\"[CONTINUOUS-FETCH] Stopping continuous ad fetching\");\n    }\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Ad iteration\n  // ───────────────────────────────────────────────────────────────\n\n  async tryNextAvailableAdWithRateLimit(): Promise<void> {\n    if (!this.inAdBreak) {\n      return;\n    }\n\n    const epoch = this.timing.adBreakEpoch;\n\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n\n    const backoffMultiplier = Math.pow(2, this.timing.consecutiveFailures);\n    const backoffDelay = Math.min(this.timing.backoffBaseMs * backoffMultiplier, this.timing.maxBackoffMs);\n    const effectiveMinInterval = this.timing.minAdRequestIntervalMs + (this.timing.consecutiveFailures > 0 ? backoffDelay : 0);\n\n    const timeSinceLastRequest = Date.now() - this.timing.lastAdRequestTime;\n    if (timeSinceLastRequest < effectiveMinInterval) {\n      const waitTime = effectiveMinInterval - timeSinceLastRequest;\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.timing.consecutiveFailures} failures)`);\n      }\n      await new Promise(resolve => setTimeout(resolve, waitTime));\n    }\n\n    if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) {\n      return;\n    }\n\n    return this.tryNextAvailableAd(0);\n  }\n\n  private async tryNextAvailableAd(retryCount: number = 0): Promise<void> {\n    if (!this.inAdBreak) {\n      return;\n    }\n\n    const remaining = this.timing.getRemainingAdMs();\n\n    if (!this.timing.hasTimeToStartAnotherAd()) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Not enough time remaining (${remaining}ms) to start another ad, ending ad break`);\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (this.timing.isGamInCooldown()) {\n      if (this.debug) {\n        console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully\");\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Too many consecutive failures (${this.timing.consecutiveFailures}), ending ad break`);\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n\n    this.timing.cleanupTemporaryFailures();\n\n    while (this.adRequestQueue.length > 0) {\n      const nextAdUrl = this.adRequestQueue.shift();\n\n      if (!nextAdUrl) continue;\n\n      if (this.timing.failedVastUrls.has(nextAdUrl)) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping permanently-failed URL, trying next...\");\n        continue;\n      }\n\n      if (this.timing.isUrlInCooldown(nextAdUrl)) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping URL in cooldown (recent no-fill), trying next...\");\n        continue;\n      }\n\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Requesting next ad via HLS ad player (${this.timing.currentAdIndex + 1}, ${this.adRequestQueue.length} remaining in queue)`);\n      }\n\n      try {\n        await this.playSingleAd(nextAdUrl);\n        this.timing.consecutiveFailures = 0;\n      } catch (error) {\n        const errorMessage = (error as Error).message;\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad request failed:\", errorMessage);\n\n        if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n\n        if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n          this.timing.consecutiveFailures++;\n        }\n\n        await this.tryNextAvailableAdWithRateLimit();\n      }\n      return;\n    }\n\n    const maxRetries = 3;\n    if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2000) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Queue empty, waiting for URLs... (${retryCount + 1}/${maxRetries})`);\n      }\n      await new Promise(resolve => setTimeout(resolve, 500));\n      await this.tryNextAvailableAd(retryCount + 1);\n      return;\n    }\n\n    if (!this.isShowingPlaceholder && remaining > 1000) {\n      this.showPlaceholderAndWaitForAds();\n    } else {\n      if (this.debug) console.log(\"[CONTINUOUS-FETCH] No more ads available, ending ad break\");\n      this.handleAdPodComplete();\n    }\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Single ad playback\n  // ───────────────────────────────────────────────────────────────\n\n  async playSingleAd(vastTagUrl: string): Promise<void> {\n    const adPlayer = this.host.getAdPlayer();\n    if (adPlayer.isAdPlaying()) return;\n\n    if (this.timing.failedVastUrls.has(vastTagUrl)) {\n      if (this.debug) console.warn(\"[AD-ERROR] Skipping permanently-failed VAST URL:\", vastTagUrl);\n      throw new Error(\"VAST URL permanently failed\");\n    }\n\n    if (this.timing.isUrlInCooldown(vastTagUrl)) {\n      if (this.debug) console.warn(\"[AD-ERROR] Skipping URL in cooldown (recent no-fill):\", vastTagUrl);\n      throw new Error(\"VAST URL in cooldown after no-fill\");\n    }\n\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) console.warn(\"[AD-ERROR] Too many consecutive failures, not requesting more ads\");\n      throw new Error(\"Too many consecutive failures\");\n    }\n\n    if (this.timing.isGamInCooldown()) {\n      if (this.debug) console.warn(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request\");\n      throw new Error(\"GAM in cooldown\");\n    }\n\n    this.recreateAdController();\n\n    const requestToken = ++this.timing.adRequestTokenCounter;\n    this.timing.activeAdRequestToken = requestToken;\n    this.timing.startAdRequestWatchdog(requestToken);\n\n    try {\n      await this.timing.enforceGlobalRateLimit();\n      this.timing.lastAdRequestTime = Date.now();\n      const ap = this.host.getAdPlayer();\n      await ap.requestAds(vastTagUrl);\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: vastTagUrl, timestamp: new Date().toISOString() },\n        this.analyticsContext\n      ).catch(() => {});\n\n      this.timing.clearAdRequestWatchdog();\n\n      if (this.timing.activeAdRequestToken !== requestToken) return;\n\n      if (!this.timing.ensureLoadedAdFitsBudget(ap)) {\n        this.timing.rejectLoadedAdForDuration(ap);\n        this.recreateAdController();\n        throw new Error(\"ad_duration_exceeds_budget\");\n      }\n\n      try {\n        this.timing.startAdFailsafeTimer(requestToken);\n        await ap.play();\n        this.timing.markAdStarted();\n\n        if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n          this.timing.scheduleAdStopAtBreakBoundary();\n        }\n\n        ap.setAdVolume(getAdAudioVolume(ap));\n        this.timing.consecutiveFailures = 0;\n        this.timing.temporaryFailureUrls.delete(vastTagUrl);\n      } catch (playError) {\n        if (this.debug) console.error(\"[AD-ERROR] Failed to play ad:\", playError);\n\n        if (this.timing.isTemporaryAdError(playError as Error)) {\n          this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n          if (this.debug) console.log(\"[AD-ERROR] Temporary play error - URL can be retried after cooldown\");\n        } else {\n          this.timing.failedVastUrls.add(vastTagUrl);\n          if (this.debug) console.log(\"[AD-ERROR] Permanent play error - URL blacklisted\");\n        }\n\n        this.timing.clearAdFailsafeTimer();\n        if (this.timing.activeAdRequestToken === requestToken) {\n          this.timing.activeAdRequestToken = null;\n        }\n        throw playError;\n      }\n    } catch (error) {\n      const errorMessage = (error as Error)?.message || \"\";\n      if (this.debug) console.error(\"[AD-ERROR] Ad request failed:\", errorMessage);\n\n      if (this.timing.isTemporaryAdError(error as Error)) {\n        this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());\n        if (this.debug) console.log(\"[AD-ERROR] Temporary error (no-fill/timeout) - URL can be retried after cooldown\");\n      } else {\n        this.timing.failedVastUrls.add(vastTagUrl);\n        if (this.debug) console.log(\"[AD-ERROR] Permanent error - URL blacklisted:\", errorMessage);\n      }\n\n      this.timing.clearAdRequestWatchdog();\n      this.timing.clearAdFailsafeTimer();\n      if (this.timing.activeAdRequestToken === requestToken) {\n        this.timing.activeAdRequestToken = null;\n      }\n      throw error;\n    }\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Placeholder wait\n  // ───────────────────────────────────────────────────────────────\n\n  private async showPlaceholderAndWaitForAds(): Promise<void> {\n    const remaining = this.timing.getRemainingAdMs();\n    const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n    if (this.timing.isGamInCooldown()) {\n      if (this.debug) console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait\");\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) console.log(\"[CONTINUOUS-FETCH] Skipping placeholder - too many consecutive failures\");\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (waitTime < 1000) {\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (this.debug) {\n      console.log(`[CONTINUOUS-FETCH] Showing placeholder for ${waitTime}ms while waiting for ad URLs`);\n    }\n\n    this.isShowingPlaceholder = true;\n    this.host.getAdPlayer().showPlaceholder();\n\n    const checkInterval = 300;\n    const maxChecks = Math.floor(waitTime / checkInterval);\n\n    for (let i = 0; i < maxChecks; i++) {\n      await new Promise(resolve => setTimeout(resolve, checkInterval));\n\n      if (!this.inAdBreak) return;\n\n      if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Too many failures during placeholder wait\");\n        break;\n      }\n\n      if (!this.timing.hasTimeToStartAnotherAd()) {\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Not enough time remaining during placeholder wait, ending ad break\");\n        break;\n      }\n\n      while (this.adRequestQueue.length > 0) {\n        if (!this.timing.hasTimeToStartAnotherAd()) break;\n\n        const nextAdUrl = this.adRequestQueue.shift();\n        if (!nextAdUrl) continue;\n        if (this.timing.failedVastUrls.has(nextAdUrl)) continue;\n        if (this.timing.isUrlInCooldown(nextAdUrl)) continue;\n\n        if (this.debug) console.log(\"[CONTINUOUS-FETCH] Ad URL available, requesting via HLS ad player\");\n\n        this.isShowingPlaceholder = false;\n        this.host.getAdPlayer().hidePlaceholder();\n\n        try {\n          await this.playSingleAd(nextAdUrl);\n          this.timing.consecutiveFailures = 0;\n        } catch (error) {\n          const errorMessage = (error as Error).message;\n          if (errorMessage.includes(\"ad_duration_exceeds_budget\")) {\n            await this.tryNextAvailableAdWithRateLimit();\n            return;\n          }\n          if (!errorMessage.includes(\"permanently failed\") && !errorMessage.includes(\"in cooldown\")) {\n            this.timing.consecutiveFailures++;\n          }\n          await this.tryNextAvailableAdWithRateLimit();\n        }\n        return;\n      }\n    }\n\n    if (this.debug) console.log(\"[CONTINUOUS-FETCH] Placeholder timeout, ending ad break\");\n\n    this.isShowingPlaceholder = false;\n    this.host.getAdPlayer().hidePlaceholder();\n    this.handleAdPodComplete();\n  }\n\n  // ───────────────────────────────────────────────────────────────\n  //  Ad break completion\n  // ───────────────────────────────────────────────────────────────\n\n  handleAdPodComplete(): void {\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] Ad pod complete - cleaning up\");\n    }\n\n    this.timing.resetForBreakEnd();\n\n    this.stopContinuousFetching();\n    this.clearPendingAdBreak();\n\n    if (this.isShowingPlaceholder) {\n      this.host.getAdPlayer().hidePlaceholder();\n      this.isShowingPlaceholder = false;\n    }\n\n    this.adRequestQueue = [];\n\n    this.inAdBreak = false;\n    this.adDetectSentForCurrentBreak = false;\n    this.cueManager.activeScte35BreakKey = undefined;\n    this.cueManager.scheduledScte35BreakKey = undefined;\n    this.adPodQueue = [];\n    this.showAds = false;\n\n    this.host.getAdPlayer().stop().catch(() => {});\n\n    const restoredMuted = this.host.getAdPlayer().getOriginalMutedState();\n    const restoredVolume = this.host.getAdPlayer().getOriginalVolume();\n\n    if (this.host.video.muted !== restoredMuted) {\n      this.host.video.muted = restoredMuted;\n    }\n    if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {\n      this.host.video.volume = restoredVolume;\n    }\n\n    this.host.video.style.visibility = \"visible\";\n    this.host.video.style.opacity = \"1\";\n\n    if (this.host.isLiveStream()) {\n      const liveSyncPos = this.host.getLiveSyncPosition();\n      if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {\n        if (this.debug) {\n          console.log(\n            `[StormcloudVideoPlayer] Live break end — snapping to live edge: ${this.host.video.currentTime.toFixed(2)}s → ${liveSyncPos.toFixed(2)}s`\n          );\n        }\n        this.host.video.currentTime = liveSyncPos;\n        this.host.restartHlsLoad(liveSyncPos);\n      }\n      this.resumeContentPlayback();\n      this.monitorLiveResumeStall(this.host.video.currentTime);\n      return;\n    }\n\n    this.resumeContentPlayback();\n  }\n\n  private getBufferedAhead(): number {\n    const video = this.host.video;\n    const t = video.currentTime;\n    const ranges = video.buffered;\n    for (let i = 0; i < ranges.length; i++) {\n      if (t >= ranges.start(i) - 0.5 && t <= ranges.end(i)) {\n        return ranges.end(i) - t;\n      }\n    }\n    return 0;\n  }\n\n  private describeVideoState(): string {\n    const v = this.host.video;\n    const networkStates = [\"EMPTY\", \"IDLE\", \"LOADING\", \"NO_SOURCE\"];\n    const readyStates = [\n      \"HAVE_NOTHING\",\n      \"HAVE_METADATA\",\n      \"HAVE_CURRENT_DATA\",\n      \"HAVE_FUTURE_DATA\",\n      \"HAVE_ENOUGH_DATA\",\n    ];\n    const net = networkStates[v.networkState] ?? String(v.networkState);\n    const ready = readyStates[v.readyState] ?? String(v.readyState);\n    const err = v.error\n      ? `code=${v.error.code}${v.error.message ? ` (${v.error.message})` : \"\"}`\n      : \"none\";\n    const ranges: string[] = [];\n    for (let i = 0; i < v.buffered.length; i++) {\n      ranges.push(`[${v.buffered.start(i).toFixed(2)}–${v.buffered.end(i).toFixed(2)}]`);\n    }\n    return (\n      `t=${v.currentTime.toFixed(2)}s paused=${v.paused} ended=${v.ended} seeking=${v.seeking} ` +\n      `readyState=${ready} networkState=${net} error=${err} ` +\n      `buffered=${ranges.length ? ranges.join(\",\") : \"none\"}`\n    );\n  }\n\n  private monitorLiveResumeStall(resumeBaseline: number): void {\n    const pollIntervalMs = 1000;\n    const graceMs = 5000;\n    const recoveryCooldownMs = 5000;\n    const maxRecoveries = 3;\n    const maxMonitorMs = 45000;\n\n    const startTime = Date.now();\n    let baseline = resumeBaseline;\n    let recoveries = 0;\n    let lastRecoveryAt = 0;\n\n    const video = this.host.video;\n    let listenersAttached = false;\n    let onMediaEvent: ((e: Event) => void) | undefined;\n    const diagEvents = [\n      \"loadstart\",\n      \"loadedmetadata\",\n      \"loadeddata\",\n      \"canplay\",\n      \"canplaythrough\",\n      \"play\",\n      \"playing\",\n      \"pause\",\n      \"waiting\",\n      \"stalled\",\n      \"suspend\",\n      \"seeking\",\n      \"seeked\",\n      \"emptied\",\n      \"error\",\n      \"ended\",\n    ];\n    if (this.debug) {\n      onMediaEvent = (e: Event) => {\n        const dt = ((Date.now() - startTime) / 1000).toFixed(1);\n        console.log(\n          `[ResumeDiag] +${dt}s event=${e.type} — ${this.describeVideoState()}`\n        );\n      };\n      for (const name of diagEvents) {\n        video.addEventListener(name, onMediaEvent);\n      }\n      listenersAttached = true;\n      console.log(\n        `[ResumeDiag] +0.0s monitor start — ${this.describeVideoState()}`\n      );\n    }\n\n    const cleanup = (): void => {\n      if (listenersAttached && onMediaEvent) {\n        for (const name of diagEvents) {\n          video.removeEventListener(name, onMediaEvent);\n        }\n        listenersAttached = false;\n      }\n    };\n\n    const poll = (): void => {\n      if (this.inAdBreak) {\n        cleanup();\n        return;\n      }\n\n      const currentTime = video.currentTime;\n      const advanced = currentTime > baseline + 0.5;\n      const playing = !video.paused && video.readyState >= 3;\n\n      if (advanced && playing) {\n        if (this.debug) {\n          console.log(\n            `[StormcloudVideoPlayer] Live stream resumed successfully after ad break — ${this.describeVideoState()}`\n          );\n        }\n        cleanup();\n        return;\n      }\n\n      if (video.paused) {\n        video.play()?.catch(() => {});\n      }\n\n      const elapsed = Date.now() - startTime;\n      const bufferedAhead = this.getBufferedAhead();\n      const wedged = bufferedAhead < 0.5 && !advanced;\n\n      if (elapsed >= maxMonitorMs) {\n        if (this.debug && !advanced) {\n          console.warn(\n            `[StormcloudVideoPlayer] Live stream failed to resume after ${(maxMonitorMs / 1000).toFixed(0)}s — ${this.describeVideoState()}`\n          );\n        }\n        cleanup();\n        return;\n      }\n\n      const canRecover =\n        wedged &&\n        elapsed >= graceMs &&\n        Date.now() - lastRecoveryAt >= recoveryCooldownMs &&\n        recoveries < maxRecoveries;\n\n      if (canRecover) {\n        recoveries++;\n        lastRecoveryAt = Date.now();\n\n        if (recoveries === 1) {\n          if (this.debug) {\n            console.warn(\n              `[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ${recoveries}/${maxRecoveries}) — ${this.describeVideoState()}`\n            );\n          }\n          this.host.recoverMediaError();\n        } else if (recoveries === 2) {\n          const liveSyncPos = this.host.getLiveSyncPosition();\n          const reloadPos =\n            liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;\n\n          if (this.debug) {\n            console.warn(\n              `[StormcloudVideoPlayer] Content wedged after ad break — restarting HLS load at ${reloadPos.toFixed(2)}s (recovery ${recoveries}/${maxRecoveries}) — ${this.describeVideoState()}`\n            );\n          }\n\n          if (liveSyncPos != null && liveSyncPos > currentTime) {\n            video.currentTime = liveSyncPos;\n          }\n          this.host.restartHlsLoad(reloadPos);\n        } else {\n          if (this.debug) {\n            console.warn(\n              `[StormcloudVideoPlayer] Content still wedged after ad break — hard-reloading live stream (recovery ${recoveries}/${maxRecoveries}) — ${this.describeVideoState()}`\n            );\n          }\n          this.host.reloadLiveStream();\n        }\n\n        baseline = video.currentTime;\n        if (video.paused) {\n          video.play()?.catch(() => {});\n        }\n      }\n\n      window.setTimeout(poll, pollIntervalMs);\n    };\n\n    window.setTimeout(poll, pollIntervalMs);\n  }\n\n  private resumeContentPlayback(attempt: number = 0): void {\n    const maxAttempts = 5;\n    const video = this.host.video;\n\n    if (!video.paused) {\n      if (this.debug && attempt === 0) {\n        console.log(\"[StormcloudVideoPlayer] Content video already playing after ads\");\n      }\n      return;\n    }\n\n    if (this.debug) {\n      console.log(\n        `[StormcloudVideoPlayer] Resuming content playback after ads (attempt ${attempt + 1}/${maxAttempts}, readyState=${video.readyState})`\n      );\n    }\n\n    if (video.readyState < 3) {\n      if (attempt + 1 >= maxAttempts) {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] readyState never reached HAVE_FUTURE_DATA, forcing play()\"\n          );\n        }\n        video.play()?.catch(() => {});\n        return;\n      }\n\n      const onReady = (): void => {\n        video.removeEventListener(\"canplay\", onReady);\n        this.resumeContentPlayback(attempt + 1);\n      };\n      video.addEventListener(\"canplay\", onReady);\n\n      const backoffMs = 500 * (attempt + 1);\n      window.setTimeout(() => {\n        video.removeEventListener(\"canplay\", onReady);\n        if (video.paused) {\n          this.resumeContentPlayback(attempt + 1);\n        }\n      }, backoffMs);\n      return;\n    }\n\n    const playResult = video.play();\n    if (playResult && typeof playResult.catch === \"function\") {\n      playResult.catch((error) => {\n        if (attempt + 1 >= maxAttempts) {\n          if (this.debug) {\n            console.warn(\n              \"[StormcloudVideoPlayer] Failed to resume content playback after ads:\",\n              error\n            );\n          }\n          return;\n        }\n        const backoffMs = 250 * (attempt + 1);\n        window.setTimeout(() => {\n          this.resumeContentPlayback(attempt + 1);\n        }, backoffMs);\n      });\n    }\n  }\n\n  handleAdFailure(): void {\n    this.timing.consecutiveFailures++;\n    this.timing.recordGamNoFill();\n    const remaining = this.timing.getRemainingAdMs();\n\n    if (this.debug) {\n      console.log(\n        `[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}, consecutiveFailures=${this.timing.consecutiveFailures}`,\n        this.adRequestQueue.length > 0 ? { queuedUrls: [...this.adRequestQueue] } : {}\n      );\n    }\n\n    if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {\n      if (this.debug) console.log(`[CONTINUOUS-FETCH] Max consecutive failures reached (${this.timing.consecutiveFailures}), ending ad break gracefully`);\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (this.timing.hasTimeToStartAnotherAd()) {\n      this.tryNextAvailableAdWithRateLimit();\n    } else {\n      if (this.debug) console.log(\"[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:\", this.timing.failedVastUrls.size);\n      this.handleAdPodComplete();\n    }\n  }\n}\n"]}