{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/StormcloudVideoPlayer.cjs","../../src/ui/StormcloudVideoPlayer.tsx","../../src/sdk/hlsAdPlayer.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/AdPreloadPool.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","module","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","sessionId","preloadedAds","preloadingAds","destroyed","pendingTimeouts","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","emit","event","payload","set","Array","fn","error","console","warn","generateSessionId","Date","now","random","toString","substr","fireTrackingPixels","urls","length","forEach","url","trackingUrl","includes","img","Image","src","log","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","width","height","bitrate","selectBestMediaFile","mediaFiles","Error","firstFile","mainQuality","bestMatch","file","scoredFiles","widthDiff","map","abs","resolutionDiff","heightDiff","fileBitrate","score","bitrateDiff","resolution","isHlsMediaFile","mediaFile","type","toLowerCase","isProgressiveMediaFile","createEmptyTrackingUrls","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","extractTrackingUrls","trackingUrls","xmlDoc","el","textContent","trim","push","querySelectorAll","getAttribute","eventKey","mergeTrackingUrls","source","keys","concat","parseVastXml","xmlString","parser","DOMParser","parseFromString","parserError","querySelector","adElement","adId","title","clickThrough","wrapperUri","vastAdTagUri","isNoAdAvailable","durationText","durationParts","split","duration","parseInt","mediaFileElements","mf","index","bitrateAttr","bitrateValue","ad","id","fetchVastXml","vastTagUrl","response","fetch","mode","credentials","headers","referrerPolicy","ok","statusText","text","fetchAndParseVastAd","depth","accumulatedTracking","vastXml","parsed","substring","createAdVideoElement","video","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","muted","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","continueLiveStreamDuringAds","paused","play","catch","initialize","right","bottom","container","alignItems","justifyContent","zIndex","parentElement","appendChild","requestAds","has","delete","Promise","reject","resolve","isHlsAd","contentVolume","Hls","isSupported","destroy","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","ERROR","data","fatal","load","previousMutedState","visibility","opacity","timeoutId","clearTimeout","remove","removeChild","clear","isAdPlaying","listener","Set","add","off","updateOriginalMutedState","nextVolume","Number","isNaN","getOriginalMutedState","getOriginalVolume","setAdVolume","clamped","getAdVolume","showPlaceholder","hidePlaceholder","getLoadedAdDuration","getLoadedAdId","PAL_SDK_URL","_nonceLoader","_palLoadPromise","loadPalSdk","window","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","ppid","password","loadNonceManager","getNonce","getCurrentNonce","injectNonce","URL","searchParams","base","replace","sep","encodeURIComponent","sendPlaybackStart","sendPlaybackEnd","sendAdClick","sendAdTouch","reset","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","username","topicPrefix","qos","mqttConfig","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","buildPlayerTopic","channel","import_mqtt","LOG","client","status","initMQTTClient","clientId","slice","mqtt","connect","keepalive","clean","reconnectPeriod","connectTimeout","queueQoSZero","err","info","message","publishMQTT","AIRY_TIZEN_APP_ID","AIRY_ROKU_APP_ID","AIRY_APP_NAME","ensureMQTTClient","topic","AIRY_ANDROID_APP_ID","AIRY_WEBOS_APP_ID","AIRY_DEFAULT_CONTENT_URL","CTV_SESSION_STORAGE_KEY","PLAYER_ID_STORAGE_KEY","LG_TEST_APP_ID","LG_TEST_APP_NAME","LG_TEST_CONTENT_URL","_lgTestDeviceId","getLgTestDeviceId","createUuid","isLgWebOS","navigator","test","userAgent","getDefaultAppId","ua","DEVICE_ID_STORAGE_KEYS","resolveVastEnvironmentSignals","isCtv","platformLat","bridgeSignals","readNativeBridgeSignals","deviceId","platformDevice","readPlatformNativeDeviceId","readStoredDeviceId","lg","limitAdTracking","deviceIdType","readStoredString","inferDeviceIdType","readStoredLimitAdTracking","contentUrl","appId","appName","getOrCreateCtvSessionId","deviceTypeHint","isEquivalentDeviceIdType","tagType","runtimeType","tag","runtime","ANDROID_ID_TYPES","resolveNativeDeviceId","isMacroPlaceholder","isZeroedAdId","storageKey","localStorage","setItem","crypto","randomUUID","char","floor","nibble","adinfo","webapis","tifa","getTIFA","lat","isLATEnabled","webOSDev","lgudid","LGUDID","roku","Roku","rida","getPublisherUniqueId","ZEROED_AD_ID_PATTERNS","t","candidates","__STORMCLOUD_CTV_AD_INFO__","stormcloudCtv","AiryTV","Android","webOS","tizen","amazon","Boolean","readBridgeValue","readBridgeBoolean","result","normalized","normalizeBoolean","getItem","cachedBrowserId","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","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","sha256Hex","input","encodedData","utf8","buffer","i","hashBuffer","hash","fallbackHash","timestamp","subtle","digest","Uint8Array","TextEncoder","encode","unescape","charCodeAt","b","padStart","padEnd","resolvePlayerIdentitySeed","clientInfo","nativeDeviceId","persistedId","getOrCreateStoredUuid","JSON","stringify","getBrowserID","canPublish","buildPlayerMetricEvent","context","flags","playerId","captureAt","toISOString","player_id","device_type","ad_loaded","adLoaded","ad_detect","adDetect","capture_at","inputStreamType","input_stream_type","publishTracking","body","sendInitialTracking","metricEvent","events","sendAdDetectTracking","adDetectInfo","sendHeartbeat","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","ad_played_count","ad_url","adUrl","heartbeatData","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","String","getAll","callback","parts","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","UNEXPANDED_MACRO_PATTERN","INVALID_VAST_PARAM_KEY","EXAMPLE_COM_URL","CTV_UNSUPPORTED_PARAMS","INLINE_DEVICE_MACRO_REPLACEMENTS","pattern","getValue","ctx","generateCorrelator","getRandomValues","correlator","trimmed","buf","Uint32Array","MAX_SAFE_INTEGER","baseUrl","applyDeviceIdentityParams","runtimeId","tagRdid","tagLat","latValue","tagRdidValid","tagTypeValid","removeBrokenAppNameOrphans","toDelete","_value","suffix","trimStart","normalizeVastTagUrl","raw","anValue","orphanFragments","reconstructed","trimEnd","filter","_match","prefix","val","applyVastMacros","expandedUrl","expandInlineMacroPlaceholders","replaceCorrelatorFallback","streamCorrelator","pod","adPosition","requestUrl","pageUrl","existingUrl","consent","gdpr","gdprConsent","usPrivacy","adTest","staleKeys","correlatorRegex","fetchConsentSignals","timeoutMs","signals","tasks","tcfApi","__tcfapi","settled","tcData","success","eventStatus","gdprApplies","tcString","listenerId","uspApi","__uspapi","uspString","getChromeVersion","getWebKitVersion","webOSVersion","majorVersion","version","getPlatform","userAgentData","detectBrowser","isLegacyTV","supportsModernJS","tizenVersion","chromeVersionNum","chromeVersion","webkitVersion","getBrowserConfigOverrides","browser","overrides","allowNativeHls","logBrowserInfo","debug","parseCueOutDuration","num","parseFloat","dStr","d","parseCueOutCont","res","elapsedMatch","durationMatch","elapsed","slashMatch","parseAttributeList","attrs","regex","exec","rawVal","toNumber","n","isManifestBasedMarker","marker","id3","splice_command_type","decodeId3ValueToText","decoder","TextDecoder","decode","out","fromCharCode","getFragmentStartSeconds","frag","startPTS","candidate","isFinite","parseScte35FromId3","cueOutMatch","arg","dur","ptsSeconds","durationSeconds","cueOutContMatch","cont","cueInMatch","daterangeMatch","hasScteOut","hasScteIn","klass","bin","normalizeFragmentPayload","ArrayBuffer","isView","view","byteOffset","byteLength","detectTsPacketFormat","packetSizes","packetSize","tsPayloadOffset","offset","matchedPackets","packetStart","getPsiSectionStart","payloadUnitStart","pointerField","sectionStart","getPsiSectionLength","parsePatSection","pmtPids","sectionLength","sectionEnd","programNumber","pid","descriptorsIdentifyScte35","end","descriptorStart","descriptorEnd","registration","parsePmtSection","tsScte35Pids","programInfoLength","streamType","elementaryPid","esInfoLength","hasProcessedTsScte35Section","section","processedSections","checksum","firstKey","size","next","addScte35SectionMarker","markers","parseScte35Binary","appendScte35Bytes","bytes","assemblers","assembler","expectedLength","collectScte35SectionsFromPayload","previousAssembler","subarray","tableId","totalLength","packetInfo","sectionAssemblers","tsStart","secondByte","fourthByte","thirdByte","hasPayload","adaptationFieldControl","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","descriptorOffset","parseScte35SegmentationDescriptors","descriptorLoopLength","componentPtsSeconds","descriptorDataEnd","descriptorDataStart","programSpliceFlag","descriptorTag","descriptorLength","descriptorMarker","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","spliceEventId","commandBodyStart","cancel","outOfNetwork","durationFlag","spliceImmediateFlag","expectedDescriptorOffset","splice_event_id","segmentation_event_id","Scte35CueManager","callbacks","pendingScte35Cues","recentScte35CueKeys","recentScte35CueLimit","processedTsScte35Sections","pendingScte35CueKey","pendingScte35CueKeyValue","activeScte35BreakKey","activeScte35BreakKeyValue","scheduledScte35BreakKey","scheduledScte35BreakKeyValue","createScte35CueContext","readiness","sn","fragmentSn","fragmentStartSec","fragmentStartSeconds","onScte35Cue","cue","createScte35Cue","pendingKey","getPendingScte35CueKey","trimRecentScte35CueMaps","onEarlyStartCue","shouldAcceptScte35EndCue","inAdBreak","isInAdBreak","hasRecentlyHandledScte35Cue","markScte35CueHandled","onPlaybackCue","activatePendingScte35CuesForFragment","matchingCues","entries","getScte35CueKey","getScte35MarkerRaw","toIdentityString","daterangeId","ID","scteValue","round","isStrongScte35CueKey","recentKey","vmapBreaks","AdConfigManager","config","consumedVmapBreakIds","podCounter","podAssignedByPrefetch","adRequestPositionInBreak","lastHeartbeatTime","debugAdTiming","isVmapEnabled","isVmap","vmapUrl","fetchAdConfiguration","vastMode","vastEndpoint","apiUrl","imaPayload","decodedPayload","numberAds","fetchAndParseVmap","apiVastTagUrl","json","ima","vast","cue_tones","number_ads","apiNumberAds","vmapXml","parseVmapToBreaks","doc","VMAP_NS","adBreakNodes","getElementsByTagName","localName","node","timeOffsetRaw","startTimeMs","parseVmapTimeOffsetToMs","adTagNode","getElementsByTagNameNS","adTagUrl","breakId","sort","a","aStart","bStart","timeOffset","hms","hh","mm","ss","ms","hours","minutes","seconds","millis","percent","ratio","durationSec","getAdBreakKey","adBreak","resolveBreakStartMs","findCurrentOrNextBreak","nowMs","schedule","tol","driftToleranceMs","breakStartMs","findBreakForTime","durationMs","selectVastTagsForBreak","s","beginNewAdPod","generateVastUrlsWithCorrelators","count","adPlayer","envSignals","ctvAdRequest","urlWithMacros","autoplay","consentSignals","finalUrl","palNonce","initializeTracking","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","destroyTracking","clearInterval","AdTimingService","adRequestWatchdogToken","adFailsafeToken","ptsDriftEmaMs","adBreakPlayedDurationMs","adBreakEpoch","adRequestTokenCounter","activeAdRequestToken","currentAdIndex","totalAdsInBreak","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","lastAdRequestTime","consecutiveFailures","maxConsecutiveFailures","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","defaultMinRemainingMsToStartAd","failedVastUrls","temporaryFailureUrls","temporaryFailureCooldownMs","globalConsecutiveNoFills","globalNoFillThreshold","globalNoFillCooldownUntil","globalNoFillBackoffBaseMs","globalNoFillBackoffMaxMs","globalLastGamRequestTime","globalMinGamIntervalMs","scheduleAdStopCountdown","remainingMs","clearAdStopTimer","ensureAdStoppedByTimer","adStopTimerId","updatePtsDrift","getWallClockRemainingAdMs","endWallClockMs","accepted","onAdStopTimerFired","scheduleAdStartIn","cueKey","clearAdStartTimer","delayMs","onAdStartTimerFired","adStartTimerId","ptsSecondsSample","sampleMs","alpha","resolveScteBreakStartWallClockMs","nowWallClockMs","estimatedCurrentPtsMs","deltaMs","setAdBreakDurationBoundary","expectedAdBreakDurationMs","currentAdBreakStartWallClockMs","scteAdBreakEndWallClockMs","scheduleAdStopAtBreakBoundary","getAdBreakEndWallClockMs","getDurationBudgetRemainingMs","getLoadedAdDurationMs","adController","adFitsRemainingBudget","logAdDurationDecision","remainingBudget","recordPlayedAdDuration","ensureLoadedAdFitsBudget","fits","rejectLoadedAdForDuration","markAdStarted","getRemainingAdMs","wallClockRemaining","budgetRemaining","getMinRemainingMsToStartAd","configured","minRemainingMsToStartAd","hasTimeToStartAnotherAd","minRemaining","isTemporaryAdError","isUrlInCooldown","failureTime","cleanupTemporaryFailures","isGamInCooldown","recordGamNoFill","exponent","backoff","pow","resetGamNoFillCounter","enforceGlobalRateLimit","waitMs","adRequestWatchdogId","adFailsafeTimerId","failsafeMs","startAdRequestWatchdog","token","clearAdRequestWatchdog","adFailsafeTimeoutMs","logAdState","onWatchdogTimeout","startAdFailsafeTimer","clearAdFailsafeTimer","videoPaused","onFailsafeTimeout","AdPreloadPool","pool","loopRunning","extra","showAds","resetForBreakEnd","deps","maxPoolSize","poolActive","active","isLoopRunning","startPreloadPool","baseVastUrl","initialUrls","startLoopImmediately","preloadPoolLoop","preloadAdIntoPool","vastUrl","timing","epoch","loadPromise","preloadAd","errorListener","some","entry","hasAdError","adErrorPayload","errorListenerCleanup","isNoFill","poolEntry","loadedDuration","lateErrorListener","shouldContinueLiveStreamDuringAds","createAdPlayer","code","vastErrorCode","loadedAt","isReady","findIndex","splice","newUrls","newUrl","getPendingAdBreak","getPreloadedAd","stop","PlaceholderLayer","ensureContainer","show","transition","wasHidden","offsetHeight","requestAnimationFrame","hide","HlsEngine","cueManager","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","shouldUseNativeHls","getStreamType","canNative","canPlayType","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","id3Tags","samples","pts","onId3Tag","FRAG_LOADED","processFragmentScte35Payload","FRAG_DECRYPTED","FRAG_CHANGED","activatePendingCuesForFragment","prog","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","onFatalDestroy","payloadData","parseScte35FromTsPackets","getLiveSyncPosition","liveSyncPosition","getAdAudioVolume","toggleMute","newMutedState","restoreVolume","toggleFullscreen","fullscreenElement","isMuted","setMuted","setVolume","clampedVolume","getVolume","isFullscreen","clientWidth","clientHeight","AdBreakOrchestrator","host","preloadPool","adConfig","placeholder","isShowingPlaceholder","adDetectSentForCurrentBreak","continuousFetchingActive","continuousFetchLoopRunning","adRequestQueue","adPodQueue","maxPlaceholderDurationMs","pendingAdBreak","attachImaEventListeners","getAdPlayer","adIndex","remaining","queuedUrls","tryNextAvailableAdWithRateLimit","handleAdPodComplete","errorPayload","errorMessage","errorCode","cause","innerError","causeMessage","handleAdFailure","recreateAdController","shouldShowPlaceholder","preservedMutedState","preservedVolumeState","newAdPlayer","currentMuted","currentVolume","adBreakDurationMs","usePreloadedAd","preloaded","firstAdUrl","preloadedController","vastUrls","clearPendingAdBreak","firstAdUrlArray","generateVastUrls","startContinuousFetching","preservedVolume","setAdPlayer","preservedMuted","adVolume","fallbackPreloaded","swapToPreloadedAdPlayer","ap","fallbackError","continuousFetchLoop","maxQueueSize","newAdUrl","queuedUrlsPreview","generationDelay","stopContinuousFetching","backoffMultiplier","backoffDelay","effectiveMinInterval","timeSinceLastRequest","waitTime","tryNextAvailableAd","retryCount","nextAdUrl","maxRetries","playSingleAd","showPlaceholderAndWaitForAds","requestToken","playError","preloadedFallback","fbAp"],"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 sessionId;\n  const preloadedAds = /* @__PURE__ */ new Map();\n  const preloadingAds = /* @__PURE__ */ new Map();\n  let destroyed = false;\n  let pendingTimeouts = [];\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(xmlDoc) {\n    const trackingUrls = createEmptyTrackingUrls();\n    xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n      const url = el.textContent?.trim();\n      if (url) trackingUrls.impression.push(url);\n    });\n    xmlDoc.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    xmlDoc.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  async function fetchVastXml(vastTagUrl) {\n    const response = await fetch(vastTagUrl, {\n      mode: \"cors\",\n      credentials: \"include\",\n      headers: {\n        \"Accept\": \"application/xml, text/xml, */*\"\n      },\n      referrerPolicy: \"no-referrer-when-downgrade\"\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(vastTagUrl);\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  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      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      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      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      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 handleAdComplete() {\n    console.log(\"[HlsAdPlayer] Handling ad completion\");\n    adPlaying = false;\n    setAdPlayingFlag(false);\n    contentVideo.muted = true;\n    if (adContainerEl) {\n      adContainerEl.style.display = \"none\";\n      adContainerEl.style.pointerEvents = \"none\";\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(() => {\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    adPlaying = false;\n    setAdPlayingFlag(false);\n    contentVideo.muted = true;\n    if (adContainerEl) {\n      adContainerEl.style.display = \"none\";\n      adContainerEl.style.pointerEvents = \"none\";\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 ad;\n        if (preloadedAds.has(vastTagUrl)) {\n          ad = preloadedAds.get(vastTagUrl);\n          preloadedAds.delete(vastTagUrl);\n          console.log(\n            \"[HlsAdPlayer] Using preloaded VAST response:\",\n            vastTagUrl\n          );\n        } else {\n          ad = await fetchAndParseVastAd(vastTagUrl);\n        }\n        if (!ad) {\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        currentAd = ad;\n        console.log(\n          `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n        );\n        fireTrackingPixels(ad.trackingUrls.impression);\n        trackingFired.impression = true;\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        trackingFired = {\n          impression: trackingFired.impression,\n          start: false,\n          firstQuartile: false,\n          midpoint: false,\n          thirdQuartile: false,\n          complete: false\n        };\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        const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n        if (!mediaFile) {\n          throw new Error(\"No media file available for ad\");\n        }\n        if (adContainerEl) {\n          adContainerEl.style.display = \"flex\";\n          adContainerEl.style.pointerEvents = \"auto\";\n        }\n        emit(\"content_pause\");\n        const isHlsAd = isHlsMediaFile(mediaFile);\n        console.log(\n          `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad 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        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      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      if (adContainerEl) {\n        adContainerEl.style.display = \"none\";\n        adContainerEl.style.pointerEvents = \"none\";\n      }\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(() => {\n          });\n        }\n      }\n      if (adHls) {\n        adHls.destroy();\n        adHls = void 0;\n      }\n      if (adVideoElement) {\n        adVideoElement.pause();\n        adVideoElement.src = \"\";\n      }\n      currentAd = void 0;\n    },\n    destroy() {\n      console.log(\"[HlsAdPlayer] Destroying\");\n      destroyed = true;\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      if (adHls) {\n        adHls.destroy();\n        adHls = void 0;\n      }\n      if (adVideoElement) {\n        adVideoElement.pause();\n        adVideoElement.src = \"\";\n        adVideoElement.remove();\n        adVideoElement = void 0;\n      }\n      if (adContainerEl?.parentElement) {\n        adContainerEl.parentElement.removeChild(adContainerEl);\n      }\n      adContainerEl = void 0;\n      currentAd = void 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  };\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 = options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\");\n        request.iconsSupported = true;\n        request.playerType = \"StormcloudVideoPlayer\";\n        request.playerVersion = \"1.0\";\n        request.supportedApiFrameworks = \"2,7,9\";\n        request.url = options.descriptionUrl || (typeof window !== \"undefined\" ? window.location.href : \"\");\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        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 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 client = null;\nvar status = \"disconnected\";\nfunction initMQTTClient() {\n  if (client || !isMQTTEnabled()) return;\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: 60,\n      clean: true,\n      reconnectPeriod: 5e3,\n      connectTimeout: 1e4,\n      queueQoSZero: false\n    });\n  } catch (err) {\n    status = \"error\";\n    console.warn(`${LOG} connect() threw:`, err);\n    return;\n  }\n  client.on(\"connect\", () => {\n    status = \"connected\";\n    console.info(`${LOG} connected to ${url}`);\n  });\n  client.on(\"reconnect\", () => {\n    status = \"connecting\";\n    console.info(`${LOG} reconnecting\\u2026`);\n  });\n  client.on(\"offline\", () => {\n    status = \"disconnected\";\n    console.warn(`${LOG} offline`);\n  });\n  client.on(\"error\", (err) => {\n    status = \"error\";\n    console.warn(`${LOG} error:`, err.message);\n  });\n  client.on(\"close\", () => {\n    if (status === \"connected\") {\n      status = \"disconnected\";\n    }\n  });\n}\nfunction ensureMQTTClient() {\n  if (isMQTTEnabled() && !client) {\n    initMQTTClient();\n  }\n}\nfunction publishMQTT(topic, payload) {\n  if (!isMQTTEnabled()) {\n    return false;\n  }\n  ensureMQTTClient();\n  if (!client) {\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 = readStoredString(storageKey);\n  if (existing) {\n    return existing;\n  }\n  const id = createUuid();\n  try {\n    window.localStorage?.setItem(storageKey, id);\n  } catch {\n  }\n  return id;\n}\nfunction getOrCreateCtvSessionId() {\n  const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n  if (existing) {\n    return existing;\n  }\n  const sessionId = createUuid();\n  try {\n    window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n  } catch {\n  }\n  return sessionId;\n}\nfunction createUuid() {\n  if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n  return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n    const value = Math.floor(Math.random() * 16);\n    const nibble = char === \"x\" ? value : value & 3 | 8;\n    return nibble.toString(16);\n  });\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 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 playerId = await getBrowserID(clientInfo);\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.trimStart();\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.trimEnd(), ...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  if (ctx.adPosition != null) {\n    params.set(\"ppos\", String(ctx.adPosition));\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  }\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.consentSignals = {};\n    this.podCounter = 0;\n    this.podAssignedByPrefetch = false;\n    this.adRequestPositionInBreak = 0;\n    this.lastHeartbeatTime = 0;\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    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  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    this.adRequestPositionInBreak = 0;\n  }\n  generateVastUrlsWithCorrelators(baseUrl, count, adPlayer, palNonce, inAdBreak) {\n    const urls = [];\n    for (let i = 0; i < count; i++) {\n      this.adRequestPositionInBreak++;\n      const adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;\n      const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n      const urlWithMacros = applyVastMacros(baseUrl, {\n        correlator: generateCorrelator(),\n        streamCorrelator: this.streamCorrelator,\n        pod: this.podCounter > 0 ? this.podCounter : void 0,\n        adPosition: this.adRequestPositionInBreak,\n        isCtv: envSignals.isCtv,\n        contentUrl: envSignals.contentUrl,\n        pageUrl: !envSignals.isCtv && typeof window !== \"undefined\" ? 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 ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n        finalUrl\n      );\n      urls.push(finalUrl);\n    }\n    return urls;\n  }\n  // --- Tracking ---\n  initializeTracking() {\n    sendInitialTracking(this.config.licenseKey).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).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  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/AdPreloadPool.ts\nvar AdPreloadPool = class {\n  constructor(deps) {\n    this.pool = [];\n    this.maxPoolSize = 2;\n    this.poolActive = false;\n    this.loopRunning = false;\n    this.deps = deps;\n  }\n  get active() {\n    return this.poolActive;\n  }\n  set active(value) {\n    this.poolActive = value;\n  }\n  get isLoopRunning() {\n    return this.loopRunning;\n  }\n  startPreloadPool(baseVastUrl, initialUrls, startLoopImmediately = true) {\n    if (this.poolActive) {\n      if (this.deps.debug) {\n        console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n      }\n      return;\n    }\n    this.poolActive = true;\n    if (this.deps.debug) {\n      console.log(`[PRELOAD-POOL] Starting preload pool EARLY (target size: ${this.maxPoolSize})`);\n      console.log(`[PRELOAD-POOL] Ad break hasn't started yet, but preloading ads in advance`);\n    }\n    for (const url of initialUrls) {\n      if (this.pool.length < this.maxPoolSize) {\n        this.preloadAdIntoPool(url);\n      }\n    }\n    if (startLoopImmediately) {\n      this.preloadPoolLoop(baseVastUrl);\n    } else if (this.deps.debug) {\n      console.log(\n        \"[PRELOAD-POOL] Pre-break mode: preloaded once, waiting for SCTE start to continue fetching\"\n      );\n    }\n  }\n  async preloadAdIntoPool(vastUrl) {\n    const timing = this.deps.timing;\n    if (timing.isGamInCooldown()) {\n      if (this.deps.debug) {\n        console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n      }\n      return;\n    }\n    if (this.pool.some((entry) => entry.vastUrl === vastUrl) || timing.failedVastUrls.has(vastUrl) || timing.isUrlInCooldown(vastUrl)) {\n      return;\n    }\n    if (this.pool.length >= this.maxPoolSize) {\n      return;\n    }\n    if (this.deps.debug) {\n      console.log(`[PRELOAD-POOL] Preloading ad into pool: ${vastUrl}`);\n    }\n    const epoch = timing.adBreakEpoch;\n    const loadPromise = (async () => {\n      let hasAdError = false;\n      let adErrorPayload = null;\n      let errorListenerCleanup = null;\n      try {\n        const continueLiveStreamDuringAds = this.deps.shouldContinueLiveStreamDuringAds();\n        const preloadAd = this.deps.createAdPlayer(continueLiveStreamDuringAds);\n        preloadAd.initialize();\n        const errorListener = (payload) => {\n          hasAdError = true;\n          adErrorPayload = payload;\n        };\n        preloadAd.on(\"ad_error\", errorListener);\n        errorListenerCleanup = () => preloadAd.off(\"ad_error\", errorListener);\n        await timing.enforceGlobalRateLimit();\n        await preloadAd.requestAds(vastUrl);\n        preloadAd.pause();\n        await new Promise((resolve) => setTimeout(resolve, 1500));\n        preloadAd.pause();\n        if (hasAdError) {\n          const isNoFill = adErrorPayload?.isNoFill || adErrorPayload?.code === 303 || adErrorPayload?.vastErrorCode === 303;\n          if (errorListenerCleanup) {\n            errorListenerCleanup();\n          }\n          preloadAd.destroy();\n          timing.recordGamNoFill();\n          if (isNoFill) {\n            if (this.deps.debug) {\n              console.log(`[PRELOAD-POOL] Ad preload returned no-fill: ${vastUrl}`);\n            }\n            timing.temporaryFailureUrls.set(vastUrl, Date.now());\n          } else {\n            if (this.deps.debug) {\n              console.log(`[PRELOAD-POOL] Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n            }\n            if (adErrorPayload && !timing.isTemporaryAdError(adErrorPayload)) {\n              timing.failedVastUrls.add(vastUrl);\n            } else {\n              timing.temporaryFailureUrls.set(vastUrl, Date.now());\n            }\n          }\n          return;\n        }\n        if (!this.poolActive || epoch !== timing.adBreakEpoch) {\n          if (this.deps.debug) {\n            console.log(\n              \"[PRELOAD-POOL] Discarding preloaded ad - break ended during fetch\"\n            );\n          }\n          if (errorListenerCleanup) {\n            errorListenerCleanup();\n          }\n          try {\n            preloadAd.destroy();\n          } catch {\n          }\n          return;\n        }\n        const poolEntry = {\n          vastUrl,\n          adController: preloadAd,\n          loadedAt: Date.now(),\n          isReady: true,\n          loadPromise: Promise.resolve()\n        };\n        const loadedDuration = preloadAd.getLoadedAdDuration?.();\n        if (loadedDuration != null && loadedDuration > 0) {\n          poolEntry.durationSeconds = loadedDuration;\n        }\n        const lateErrorListener = (payload) => {\n          const index = this.pool.findIndex((entry) => entry.vastUrl === vastUrl);\n          if (index >= 0) {\n            this.pool.splice(index, 1);\n            if (this.deps.debug) {\n              console.log(`[PRELOAD-POOL] Late error detected, removed from pool: ${vastUrl}`, payload);\n            }\n            try {\n              preloadAd.destroy();\n            } catch {\n            }\n          }\n        };\n        preloadAd.on(\"ad_error\", lateErrorListener);\n        this.pool.push(poolEntry);\n        if (this.deps.debug) {\n          console.log(`[PRELOAD-POOL] Ad preloaded (no errors detected within timeout) (pool size: ${this.pool.length}/${this.maxPoolSize}, duration=${poolEntry.durationSeconds ?? \"?\"}s)`);\n        }\n        if (errorListenerCleanup) {\n          errorListenerCleanup();\n        }\n      } catch (error) {\n        if (errorListenerCleanup) {\n          errorListenerCleanup();\n        }\n        timing.recordGamNoFill();\n        if (this.deps.debug) {\n          console.warn(`[PRELOAD-POOL] Failed to preload ad: ${vastUrl}`, error);\n        }\n        if (error instanceof Error && !timing.isTemporaryAdError(error)) {\n          timing.failedVastUrls.add(vastUrl);\n        } else if (error instanceof Error && timing.isTemporaryAdError(error)) {\n          timing.temporaryFailureUrls.set(vastUrl, Date.now());\n        }\n      }\n    })();\n    loadPromise.catch(() => {\n    });\n  }\n  async preloadPoolLoop(baseVastUrl) {\n    if (this.loopRunning) {\n      return;\n    }\n    this.loopRunning = true;\n    const epoch = this.deps.timing.adBreakEpoch;\n    if (this.deps.debug) {\n      console.log(\"[PRELOAD-POOL] Starting continuous preload loop\");\n    }\n    while (this.poolActive && epoch === this.deps.timing.adBreakEpoch) {\n      if (this.deps.timing.isGamInCooldown()) {\n        if (this.deps.debug) {\n          console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n        }\n        break;\n      }\n      if (!this.deps.isInAdBreak() && this.pool.length >= this.maxPoolSize) {\n        await new Promise((resolve) => setTimeout(resolve, 2e3));\n        continue;\n      }\n      if (!this.deps.isInAdBreak() && this.deps.getPendingAdBreak() === null) {\n        if (this.deps.debug) {\n          console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n        }\n        break;\n      }\n      while (this.pool.length < this.maxPoolSize) {\n        if (!this.poolActive || epoch !== this.deps.timing.adBreakEpoch || this.deps.timing.isGamInCooldown()) {\n          break;\n        }\n        if (this.deps.isInAdBreak() && !this.deps.timing.hasTimeToStartAnotherAd()) {\n          if (this.deps.debug) {\n            console.log(\"[PRELOAD-POOL] Not enough ad break time left, stopping preload\");\n          }\n          break;\n        }\n        const newUrls = this.deps.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n        const newUrl = newUrls[0];\n        if (newUrl && !this.deps.timing.failedVastUrls.has(newUrl) && !this.deps.timing.isUrlInCooldown(newUrl)) {\n          await this.preloadAdIntoPool(newUrl);\n        }\n        await new Promise((resolve) => setTimeout(resolve, 1e3));\n      }\n      await new Promise((resolve) => setTimeout(resolve, 2e3));\n    }\n    this.loopRunning = false;\n    if (this.deps.debug) {\n      console.log(\"[PRELOAD-POOL] Preload loop ended\");\n    }\n  }\n  getPreloadedAd() {\n    if (this.pool.length === 0) {\n      return null;\n    }\n    const entry = this.pool.shift();\n    if (!entry || !entry.isReady) {\n      return null;\n    }\n    if (this.deps.debug) {\n      console.log(`[PRELOAD-POOL] Using preloaded ad from pool (${this.pool.length} remaining)`);\n    }\n    return {\n      vastUrl: entry.vastUrl,\n      adController: entry.adController\n    };\n  }\n  stop() {\n    this.poolActive = false;\n    this.loopRunning = false;\n    for (const entry of this.pool) {\n      try {\n        entry.adController.destroy();\n      } catch (error) {\n        if (this.deps.debug) {\n          console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n        }\n      }\n    }\n    this.pool = [];\n    if (this.deps.debug) {\n      console.log(\"[PRELOAD-POOL] Preload pool stopped and cleaned up\");\n    }\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.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    });\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  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, preloadPool, 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.preloadPool = preloadPool;\n    this.adConfig = adConfig;\n    this.cueManager = cueManager;\n    this.placeholder = placeholder;\n  }\n  get debug() {\n    return !!this.host.config.debugAdTiming;\n  }\n  // ───────────────────────────────────────────────────────────────\n  //  IMA event listeners\n  // ───────────────────────────────────────────────────────────────\n  attachImaEventListeners() {\n    const adPlayer = this.host.getAdPlayer();\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      ).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      ).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    let firstAdUrl;\n    let usePreloadedAd = false;\n    let preloadedController;\n    const preloaded = this.preloadPool.getPreloadedAd();\n    if (preloaded) {\n      firstAdUrl = preloaded.vastUrl;\n      preloadedController = preloaded.adController;\n      usePreloadedAd = true;\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n      ).catch(() => {\n      });\n      if (this.debug) {\n        console.log(\"[CONTINUOUS-FETCH] Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n      }\n    } else if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n      this.adRequestQueue = [...this.pendingAdBreak.vastUrls];\n      firstAdUrl = this.adRequestQueue.shift();\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n      }\n      this.clearPendingAdBreak();\n    } else {\n      if (this.debug) {\n        console.log(\"[CONTINUOUS-FETCH] Generating new ad URLs...\");\n      }\n      const firstAdUrlArray = this.host.generateVastUrls(baseVastUrl, 1);\n      firstAdUrl = firstAdUrlArray[0];\n      this.adRequestQueue = [];\n    }\n    if (!firstAdUrl) {\n      if (this.debug) {\n        console.warn(\"[CONTINUOUS-FETCH] Failed to get first ad URL\");\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n    if (this.debug) {\n      console.log(\"[CONTINUOUS-FETCH] First VAST URL:\", firstAdUrl);\n    }\n    try {\n      if (usePreloadedAd && preloadedController) {\n        if (!this.timing.ensureLoadedAdFitsBudget(preloadedController)) {\n          this.timing.rejectLoadedAdForDuration(preloadedController);\n          this.startContinuousFetching(baseVastUrl);\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n        const adPlayer = this.host.getAdPlayer();\n        const preservedMuted = adPlayer.getOriginalMutedState();\n        const preservedVolume = adPlayer.getOriginalVolume();\n        adPlayer.destroy();\n        this.host.video.muted = true;\n        this.host.setAdPlayer(preloadedController);\n        preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n        this.attachImaEventListeners();\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n        }\n        preloadedController.resume();\n        this.timing.consecutiveFailures = 0;\n        this.startContinuousFetching(baseVastUrl);\n        if (!this.preloadPool.active) {\n          this.preloadPool.active = true;\n        }\n        if (!this.preloadPool.isLoopRunning) {\n          this.preloadPool.preloadPoolLoop(baseVastUrl);\n        }\n        await preloadedController.play();\n        this.timing.markAdStarted();\n        if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n          this.timing.scheduleAdStopAtBreakBoundary();\n        }\n        const adVolume = currentMuted ? 0 : currentVolume;\n        preloadedController.setAdVolume(adVolume);\n      } else {\n        const adPlayer = this.host.getAdPlayer();\n        await this.timing.enforceGlobalRateLimit();\n        this.timing.lastAdRequestTime = Date.now();\n        await adPlayer.requestAds(firstAdUrl);\n        sendAdLoadedTracking(\n          this.host.config.licenseKey,\n          { source: \"hls\", vastUrl: firstAdUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n        ).catch(() => {\n        });\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] First ad request successful, starting playback\");\n        }\n        if (!this.timing.ensureLoadedAdFitsBudget(adPlayer)) {\n          this.timing.rejectLoadedAdForDuration(adPlayer);\n          this.recreateAdController();\n          this.startContinuousFetching(baseVastUrl);\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n        this.timing.consecutiveFailures = 0;\n        this.startContinuousFetching(baseVastUrl);\n        if (!this.preloadPool.active) {\n          this.preloadPool.startPreloadPool(baseVastUrl, []);\n        }\n        await adPlayer.play();\n        this.timing.markAdStarted();\n        if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n          this.timing.scheduleAdStopAtBreakBoundary();\n        }\n        const adVolume = currentMuted ? 0 : currentVolume;\n        adPlayer.setAdVolume(adVolume);\n      }\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\"[CONTINUOUS-FETCH] First ad request failed:\", error);\n      }\n      if (!usePreloadedAd) {\n        const fallbackPreloaded = this.preloadPool.getPreloadedAd();\n        if (fallbackPreloaded) {\n          if (this.debug) {\n            console.log(\"[CONTINUOUS-FETCH] First ad failed, using preloaded fallback\");\n          }\n          try {\n            if (!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) {\n              this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);\n              this.startContinuousFetching(baseVastUrl);\n              await this.tryNextAvailableAdWithRateLimit();\n              return;\n            }\n            this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);\n            this.timing.consecutiveFailures = 0;\n            this.startContinuousFetching(baseVastUrl);\n            if (!this.preloadPool.active) {\n              this.preloadPool.active = true;\n              this.preloadPool.preloadPoolLoop(baseVastUrl);\n            }\n            const ap = this.host.getAdPlayer();\n            await ap.play();\n            this.timing.markAdStarted();\n            if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n              this.timing.scheduleAdStopAtBreakBoundary();\n            }\n            const adVolume = currentMuted ? 0 : currentVolume;\n            ap.setAdVolume(adVolume);\n            return;\n          } catch (fallbackError) {\n            if (this.debug) {\n              console.warn(\"[CONTINUOUS-FETCH] Preloaded fallback also failed:\", fallbackError);\n            }\n          }\n        }\n      }\n      if (this.timing.isTemporaryAdError(error)) {\n        this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n        }\n      } else {\n        this.timing.failedVastUrls.add(firstAdUrl);\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n        }\n      }\n      this.timing.consecutiveFailures++;\n      this.startContinuousFetching(baseVastUrl);\n      await this.tryNextAvailableAdWithRateLimit();\n    }\n  }\n  swapToPreloadedAdPlayer(preloadedController) {\n    const adPlayer = this.host.getAdPlayer();\n    const preservedMuted = adPlayer.getOriginalMutedState();\n    const preservedVolume = adPlayer.getOriginalVolume();\n    adPlayer.destroy();\n    this.host.video.muted = true;\n    this.host.setAdPlayer(preloadedController);\n    this.attachImaEventListeners();\n    preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n    preloadedController.resume();\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.host.generateVastUrls(baseVastUrl, 1)[0];\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    const preloaded = this.preloadPool.getPreloadedAd();\n    if (preloaded) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Using preloaded ad from pool`);\n      }\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: preloaded.vastUrl, timestamp: (/* @__PURE__ */ new Date()).toISOString() }\n      ).catch(() => {\n      });\n      try {\n        if (!this.timing.ensureLoadedAdFitsBudget(preloaded.adController)) {\n          this.timing.rejectLoadedAdForDuration(preloaded.adController);\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n        this.swapToPreloadedAdPlayer(preloaded.adController);\n        const ap = this.host.getAdPlayer();\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        return;\n      } catch (error) {\n        if (this.debug) {\n          console.warn(\"[CONTINUOUS-FETCH] Preloaded ad failed to play:\", error);\n        }\n      }\n    }\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      ).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        const preloadedFallback = this.preloadPool.getPreloadedAd();\n        if (preloadedFallback) {\n          if (this.debug) console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n          try {\n            if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n              this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n              throw playError;\n            }\n            this.timing.clearAdFailsafeTimer();\n            this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n            this.timing.consecutiveFailures = 0;\n            const fbAp = this.host.getAdPlayer();\n            await fbAp.play();\n            this.timing.markAdStarted();\n            if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n              this.timing.scheduleAdStopAtBreakBoundary();\n            }\n            fbAp.setAdVolume(getAdAudioVolume(fbAp));\n            return;\n          } catch (fallbackError) {\n            if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n          }\n        }\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      const preloadedFallback = this.preloadPool.getPreloadedAd();\n      if (preloadedFallback) {\n        if (this.debug) console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n        try {\n          if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n            this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n            throw error;\n          }\n          this.timing.clearAdRequestWatchdog();\n          this.timing.clearAdFailsafeTimer();\n          this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n          this.timing.consecutiveFailures = 0;\n          const fbAp = this.host.getAdPlayer();\n          await fbAp.play();\n          this.timing.markAdStarted();\n          fbAp.setAdVolume(getAdAudioVolume(fbAp));\n          return;\n        } catch (fallbackError) {\n          if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n        }\n      }\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.preloadPool.stop();\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    if (this.host.shouldContinueLiveStreamDuringAds()) {\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      }\n      if (this.host.video.paused) {\n        if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n        this.host.video.play()?.catch(() => {\n        });\n      } else {\n        if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n      }\n    } else if (this.host.video.paused) {\n      this.host.video.play()?.catch(() => {\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.preloadPool = new AdPreloadPool({\n      debug: !!this.config.debugAdTiming,\n      createAdPlayer: (c) => this.createAdPlayer(c),\n      shouldContinueLiveStreamDuringAds: () => this.shouldContinueLiveStreamDuringAds(),\n      timing: this.timing,\n      generateVastUrlsWithCorrelators: (base, count) => this.generateVastUrls(base, count),\n      isInAdBreak: () => this.adBreak.inAdBreak,\n      getPendingAdBreak: () => this.adBreak.pendingAdBreak\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        getLiveSyncPosition: () => this.hlsEngine.getLiveSyncPosition(),\n        generateVastUrls: (base, count) => this.generateVastUrls(base, count)\n      },\n      this.timing,\n      this.preloadPool,\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  generateVastUrls(baseUrl, count) {\n    return this.adConfig.generateVastUrlsWithCorrelators(\n      baseUrl,\n      count,\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.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.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 }).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 generatedUrls = this.generateVastUrls(baseVastUrl, 1);\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 }).catch(() => {\n    });\n    if (this.debug) {\n      console.log(\"[PREFETCH] Starting ad prefetch for upcoming ad break\");\n      console.log(`[PREFETCH] Pre-generated ${generatedUrls.length} VAST URLs`);\n    }\n    this.preloadPool.startPreloadPool(baseVastUrl, generatedUrls.slice(0, 1), false);\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        this.adBreak.adPodQueue = [];\n        this.adBreak.inAdBreak = false;\n        this.adBreak.showAds = false;\n        if (this.debug) {\n          console.warn(\"[StormcloudVideoPlayer] VMAP ad request failed:\", error);\n        }\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.preloadPool.stop();\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 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)(import_fa.FaCompress, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, { 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)(import_fa.FaCompress, { size: Math.max(14, 18 * responsiveScale) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, { 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  FaExpand,\n  FaCompress,\n} from \"react-icons/fa\";\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                        <FaCompress size={Math.max(14, 18 * responsiveScale)} />\n                      ) : (\n                        <FaExpand 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                      <FaCompress size={Math.max(14, 18 * responsiveScale)} />\n                    ) : (\n                      <FaExpand 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 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  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(xmlDoc: Document): VastTrackingUrls {\n    const trackingUrls = createEmptyTrackingUrls();\n\n    xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n      const url = el.textContent?.trim();\n      if (url) trackingUrls.impression.push(url);\n    });\n\n    xmlDoc.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    xmlDoc.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  async function fetchVastXml(vastTagUrl: string): Promise<string> {\n    const response = await fetch(vastTagUrl, {\n      mode: \"cors\",\n      credentials: \"include\",\n      headers: {\n        \"Accept\": \"application/xml, text/xml, */*\",\n      },\n      referrerPolicy: \"no-referrer-when-downgrade\",\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(vastTagUrl);\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  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      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      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      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      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 handleAdComplete(): void {\n    console.log(\"[HlsAdPlayer] Handling ad completion\");\n    adPlaying = false;\n    setAdPlayingFlag(false);\n\n    contentVideo.muted = true;\n\n    if (adContainerEl) {\n      adContainerEl.style.display = \"none\";\n      adContainerEl.style.pointerEvents = \"none\";\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(() => {});\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    adPlaying = false;\n    setAdPlayingFlag(false);\n\n    contentVideo.muted = true;\n\n    if (adContainerEl) {\n      adContainerEl.style.display = \"none\";\n      adContainerEl.style.pointerEvents = \"none\";\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 ad: VastAd | null | undefined;\n\n        if (preloadedAds.has(vastTagUrl)) {\n          ad = preloadedAds.get(vastTagUrl);\n          preloadedAds.delete(vastTagUrl);\n          console.log(\n            \"[HlsAdPlayer] Using preloaded VAST response:\",\n            vastTagUrl\n          );\n        } else {\n          ad = await fetchAndParseVastAd(vastTagUrl);\n        }\n\n        if (!ad) {\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        currentAd = ad;\n        console.log(\n          `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n        );\n\n        fireTrackingPixels(ad.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\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        trackingFired = {\n          impression: trackingFired.impression,\n          start: false,\n          firstQuartile: false,\n          midpoint: false,\n          thirdQuartile: false,\n          complete: false,\n        };\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        const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n        if (!mediaFile) {\n          throw new Error(\"No media file available for ad\");\n        }\n\n        if (adContainerEl) {\n          adContainerEl.style.display = \"flex\";\n          adContainerEl.style.pointerEvents = \"auto\";\n        }\n\n        emit(\"content_pause\");\n\n        const isHlsAd = isHlsMediaFile(mediaFile);\n        console.log(\n          `[HlsAdPlayer] Loading ${isHlsAd ? \"HLS\" : \"progressive\"} ad 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 (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        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      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      if (adContainerEl) {\n        adContainerEl.style.display = \"none\";\n        adContainerEl.style.pointerEvents = \"none\";\n      }\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(() => {});\n        }\n      }\n\n      if (adHls) {\n        adHls.destroy();\n        adHls = undefined;\n      }\n\n      if (adVideoElement) {\n        adVideoElement.pause();\n        adVideoElement.src = \"\";\n      }\n\n      currentAd = undefined;\n    },\n\n    destroy() {\n      console.log(\"[HlsAdPlayer] Destroying\");\n      destroyed = true;\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      if (adHls) {\n        adHls.destroy();\n        adHls = undefined;\n      }\n\n      if (adVideoElement) {\n        adVideoElement.pause();\n        adVideoElement.src = \"\";\n        adVideoElement.remove();\n        adVideoElement = undefined;\n      }\n\n      if (adContainerEl?.parentElement) {\n        adContainerEl.parentElement.removeChild(adContainerEl);\n      }\n\n      adContainerEl = undefined;\n      currentAd = undefined;\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  };\n}\n","declare 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 =\n          options.descriptionUrl ||\n          (typeof window !== \"undefined\" ? window.location.href : \"\");\n        request.iconsSupported = true;\n        request.playerType = \"StormcloudVideoPlayer\";\n        request.playerVersion = \"1.0\";\n        request.supportedApiFrameworks = \"2,7,9\";\n        request.url =\n          options.descriptionUrl ||\n          (typeof window !== \"undefined\" ? window.location.href : \"\");\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        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\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\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\nexport function initMQTTClient(): void {\n  if (client || !isMQTTEnabled()) return;\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: 60,\n      clean: true,\n      reconnectPeriod: 5000,\n      connectTimeout: 10_000,\n      queueQoSZero: false,\n    });\n  } catch (err) {\n    status = \"error\";\n    console.warn(`${LOG} connect() threw:`, err);\n    return;\n  }\n\n  client.on(\"connect\", () => {\n    status = \"connected\";\n    console.info(`${LOG} connected to ${url}`);\n  });\n\n  client.on(\"reconnect\", () => {\n    status = \"connecting\";\n    console.info(`${LOG} reconnecting…`);\n  });\n\n  client.on(\"offline\", () => {\n    status = \"disconnected\";\n    console.warn(`${LOG} offline`);\n  });\n\n  client.on(\"error\", (err) => {\n    status = \"error\";\n    console.warn(`${LOG} error:`, err.message);\n  });\n\n  client.on(\"close\", () => {\n    if (status === \"connected\") {\n      status = \"disconnected\";\n    }\n  });\n}\n\nexport function ensureMQTTClient(): void {\n  if (isMQTTEnabled() && !client) {\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) {\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  if (client) {\n    client.end(true);\n    client = null;\n    status = \"disconnected\";\n  }\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 = readStoredString(storageKey);\n  if (existing) {\n    return existing;\n  }\n\n  const id = createUuid();\n  try {\n    window.localStorage?.setItem(storageKey, id);\n  } catch {}\n  return id;\n}\n\nfunction getOrCreateCtvSessionId(): string {\n  const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n  if (existing) {\n    return existing;\n  }\n\n  const sessionId = createUuid();\n  try {\n    window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n  } catch {}\n  return sessionId;\n}\n\nfunction createUuid(): string {\n  if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n\n  return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n    const value = Math.floor(Math.random() * 16);\n    const nibble = char === \"x\" ? value : (value & 0x3) | 0x8;\n    return nibble.toString(16);\n  });\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} from \"../types\";\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 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  const playerId = await getBrowserID(clientInfo);\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  adPosition?: 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.trimStart();\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.trimEnd(), ...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  if (ctx.adPosition != null) {\n    params.set(\"ppos\", String(ctx.adPosition));\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} {\n  const browser = detectBrowser();\n  const overrides: { allowNativeHls?: boolean } = {};\n\n  if (browser.isSmartTV) {\n    overrides.allowNativeHls = 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 { sendHeartbeat, sendInitialTracking } from \"../utils/tracking\";\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  consentSignals: VastConsentSignals = {};\n  podCounter: number = 0;\n  podAssignedByPrefetch: boolean = false;\n  adRequestPositionInBreak: number = 0;\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    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 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    this.adRequestPositionInBreak = 0;\n  }\n\n  generateVastUrlsWithCorrelators(\n    baseUrl: string,\n    count: number,\n    adPlayer: AdController,\n    palNonce: PalNonceManager,\n    inAdBreak: boolean\n  ): string[] {\n    const urls: string[] = [];\n\n    for (let i = 0; i < count; i++) {\n      this.adRequestPositionInBreak++;\n\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: generateCorrelator(),\n        streamCorrelator: this.streamCorrelator,\n        pod: this.podCounter > 0 ? this.podCounter : undefined,\n        adPosition: this.adRequestPositionInBreak,\n        isCtv: envSignals.isCtv,\n        contentUrl: envSignals.contentUrl,\n        pageUrl:\n          !envSignals.isCtv && typeof window !== \"undefined\"\n            ? 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 ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n        finalUrl\n      );\n      urls.push(finalUrl);\n    }\n\n    return urls;\n  }\n\n  // --- Tracking ---\n\n  initializeTracking(): void {\n    sendInitialTracking(this.config.licenseKey)\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).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  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","import type { AdController, Scte35Marker } from \"../types\";\nimport type { AdTimingService } from \"./AdTimingService\";\n\nexport interface AdPreloadPoolDeps {\n  debug: boolean;\n  createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;\n  shouldContinueLiveStreamDuringAds(): boolean;\n  timing: AdTimingService;\n  generateVastUrlsWithCorrelators(baseUrl: string, count: number): string[];\n  isInAdBreak(): boolean;\n  getPendingAdBreak(): { marker: Scte35Marker; vastUrls: string[]; isFetching: boolean } | null;\n}\n\nexport class AdPreloadPool {\n  private pool: Array<{\n    vastUrl: string;\n    adController: AdController;\n    loadedAt: number;\n    isReady: boolean;\n    loadPromise: Promise<void>;\n    durationSeconds?: number;\n  }> = [];\n  private readonly maxPoolSize: number = 2;\n  private poolActive: boolean = false;\n  private loopRunning: boolean = false;\n\n  private deps: AdPreloadPoolDeps;\n\n  constructor(deps: AdPreloadPoolDeps) {\n    this.deps = deps;\n  }\n\n  get active(): boolean {\n    return this.poolActive;\n  }\n\n  set active(value: boolean) {\n    this.poolActive = value;\n  }\n\n  get isLoopRunning(): boolean {\n    return this.loopRunning;\n  }\n\n  startPreloadPool(\n    baseVastUrl: string,\n    initialUrls: string[],\n    startLoopImmediately: boolean = true\n  ): void {\n    if (this.poolActive) {\n      if (this.deps.debug) {\n        console.log(\"[PRELOAD-POOL] Already active, skipping duplicate start\");\n      }\n      return;\n    }\n\n    this.poolActive = true;\n\n    if (this.deps.debug) {\n      console.log(`[PRELOAD-POOL] Starting preload pool EARLY (target size: ${this.maxPoolSize})`);\n      console.log(`[PRELOAD-POOL] Ad break hasn't started yet, but preloading ads in advance`);\n    }\n\n    for (const url of initialUrls) {\n      if (this.pool.length < this.maxPoolSize) {\n        this.preloadAdIntoPool(url);\n      }\n    }\n\n    if (startLoopImmediately) {\n      this.preloadPoolLoop(baseVastUrl);\n    } else if (this.deps.debug) {\n      console.log(\n        \"[PRELOAD-POOL] Pre-break mode: preloaded once, waiting for SCTE start to continue fetching\"\n      );\n    }\n  }\n\n  private async preloadAdIntoPool(vastUrl: string): Promise<void> {\n    const timing = this.deps.timing;\n\n    if (timing.isGamInCooldown()) {\n      if (this.deps.debug) {\n        console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, skipping preload\");\n      }\n      return;\n    }\n\n    if (\n      this.pool.some(entry => entry.vastUrl === vastUrl) ||\n      timing.failedVastUrls.has(vastUrl) ||\n      timing.isUrlInCooldown(vastUrl)\n    ) {\n      return;\n    }\n\n    if (this.pool.length >= this.maxPoolSize) {\n      return;\n    }\n\n    if (this.deps.debug) {\n      console.log(`[PRELOAD-POOL] Preloading ad into pool: ${vastUrl}`);\n    }\n\n    const epoch = timing.adBreakEpoch;\n    const loadPromise = (async () => {\n      let hasAdError = false;\n      let adErrorPayload: any = null;\n      let errorListenerCleanup: (() => void) | null = null;\n\n      try {\n        const continueLiveStreamDuringAds = this.deps.shouldContinueLiveStreamDuringAds();\n        const preloadAd = this.deps.createAdPlayer(continueLiveStreamDuringAds);\n        preloadAd.initialize();\n\n        const errorListener = (payload?: any) => {\n          hasAdError = true;\n          adErrorPayload = payload;\n        };\n        preloadAd.on(\"ad_error\", errorListener);\n        errorListenerCleanup = () => preloadAd.off(\"ad_error\", errorListener);\n\n        await timing.enforceGlobalRateLimit();\n        await preloadAd.requestAds(vastUrl);\n\n        preloadAd.pause();\n\n        await new Promise(resolve => setTimeout(resolve, 1500));\n\n        preloadAd.pause();\n\n        if (hasAdError) {\n          const isNoFill = adErrorPayload?.isNoFill ||\n                          adErrorPayload?.code === 303 ||\n                          adErrorPayload?.vastErrorCode === 303;\n\n          if (errorListenerCleanup) {\n            errorListenerCleanup();\n          }\n          preloadAd.destroy();\n\n          timing.recordGamNoFill();\n\n          if (isNoFill) {\n            if (this.deps.debug) {\n              console.log(`[PRELOAD-POOL] Ad preload returned no-fill: ${vastUrl}`);\n            }\n            timing.temporaryFailureUrls.set(vastUrl, Date.now());\n          } else {\n            if (this.deps.debug) {\n              console.log(`[PRELOAD-POOL] Ad preload failed with error: ${vastUrl}`, adErrorPayload);\n            }\n            if (adErrorPayload && !timing.isTemporaryAdError(adErrorPayload as Error)) {\n              timing.failedVastUrls.add(vastUrl);\n            } else {\n              timing.temporaryFailureUrls.set(vastUrl, Date.now());\n            }\n          }\n          return;\n        }\n\n        if (!this.poolActive || epoch !== timing.adBreakEpoch) {\n          if (this.deps.debug) {\n            console.log(\n              \"[PRELOAD-POOL] Discarding preloaded ad - break ended during fetch\"\n            );\n          }\n          if (errorListenerCleanup) {\n            errorListenerCleanup();\n          }\n          try {\n            preloadAd.destroy();\n          } catch {}\n          return;\n        }\n\n        const poolEntry: {\n          vastUrl: string;\n          adController: AdController;\n          loadedAt: number;\n          isReady: boolean;\n          loadPromise: Promise<void>;\n          durationSeconds?: number;\n        } = {\n          vastUrl,\n          adController: preloadAd,\n          loadedAt: Date.now(),\n          isReady: true,\n          loadPromise: Promise.resolve(),\n        };\n        const loadedDuration = preloadAd.getLoadedAdDuration?.();\n        if (loadedDuration != null && loadedDuration > 0) {\n          poolEntry.durationSeconds = loadedDuration;\n        }\n\n        const lateErrorListener = (payload?: any) => {\n          const index = this.pool.findIndex(entry => entry.vastUrl === vastUrl);\n          if (index >= 0) {\n            this.pool.splice(index, 1);\n            if (this.deps.debug) {\n              console.log(`[PRELOAD-POOL] Late error detected, removed from pool: ${vastUrl}`, payload);\n            }\n            try {\n              preloadAd.destroy();\n            } catch {}\n          }\n        };\n        preloadAd.on(\"ad_error\", lateErrorListener);\n\n        this.pool.push(poolEntry);\n\n        if (this.deps.debug) {\n          console.log(`[PRELOAD-POOL] Ad preloaded (no errors detected within timeout) (pool size: ${this.pool.length}/${this.maxPoolSize}, duration=${poolEntry.durationSeconds ?? \"?\"}s)`);\n        }\n\n        if (errorListenerCleanup) {\n          errorListenerCleanup();\n        }\n      } catch (error) {\n        if (errorListenerCleanup) {\n          errorListenerCleanup();\n        }\n\n        timing.recordGamNoFill();\n\n        if (this.deps.debug) {\n          console.warn(`[PRELOAD-POOL] Failed to preload ad: ${vastUrl}`, error);\n        }\n\n        if (error instanceof Error && !timing.isTemporaryAdError(error)) {\n          timing.failedVastUrls.add(vastUrl);\n        } else if (error instanceof Error && timing.isTemporaryAdError(error)) {\n          timing.temporaryFailureUrls.set(vastUrl, Date.now());\n        }\n      }\n    })();\n\n    loadPromise.catch(() => {});\n  }\n\n  async preloadPoolLoop(baseVastUrl: string): Promise<void> {\n    if (this.loopRunning) {\n      return;\n    }\n\n    this.loopRunning = true;\n    const epoch = this.deps.timing.adBreakEpoch;\n\n    if (this.deps.debug) {\n      console.log(\"[PRELOAD-POOL] Starting continuous preload loop\");\n    }\n\n    while (this.poolActive && epoch === this.deps.timing.adBreakEpoch) {\n      if (this.deps.timing.isGamInCooldown()) {\n        if (this.deps.debug) {\n          console.log(\"[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop\");\n        }\n        break;\n      }\n\n      if (!this.deps.isInAdBreak() && this.pool.length >= this.maxPoolSize) {\n        await new Promise(resolve => setTimeout(resolve, 2000));\n        continue;\n      }\n\n      if (!this.deps.isInAdBreak() && this.deps.getPendingAdBreak() === null) {\n        if (this.deps.debug) {\n          console.log(\"[PRELOAD-POOL] Ad break cancelled, stopping preload pool\");\n        }\n        break;\n      }\n\n      while (this.pool.length < this.maxPoolSize) {\n        if (\n          !this.poolActive ||\n          epoch !== this.deps.timing.adBreakEpoch ||\n          this.deps.timing.isGamInCooldown()\n        ) {\n          break;\n        }\n\n        if (this.deps.isInAdBreak() && !this.deps.timing.hasTimeToStartAnotherAd()) {\n          if (this.deps.debug) {\n            console.log(\"[PRELOAD-POOL] Not enough ad break time left, stopping preload\");\n          }\n          break;\n        }\n\n        const newUrls = this.deps.generateVastUrlsWithCorrelators(baseVastUrl, 1);\n        const newUrl = newUrls[0];\n\n        if (newUrl && !this.deps.timing.failedVastUrls.has(newUrl) && !this.deps.timing.isUrlInCooldown(newUrl)) {\n          await this.preloadAdIntoPool(newUrl);\n        }\n\n        await new Promise(resolve => setTimeout(resolve, 1000));\n      }\n\n      await new Promise(resolve => setTimeout(resolve, 2000));\n    }\n\n    this.loopRunning = false;\n\n    if (this.deps.debug) {\n      console.log(\"[PRELOAD-POOL] Preload loop ended\");\n    }\n  }\n\n  getPreloadedAd(): { vastUrl: string; adController: AdController } | null {\n    if (this.pool.length === 0) {\n      return null;\n    }\n\n    const entry = this.pool.shift();\n    if (!entry || !entry.isReady) {\n      return null;\n    }\n\n    if (this.deps.debug) {\n      console.log(`[PRELOAD-POOL] Using preloaded ad from pool (${this.pool.length} remaining)`);\n    }\n\n    return {\n      vastUrl: entry.vastUrl,\n      adController: entry.adController,\n    };\n  }\n\n  stop(): void {\n    this.poolActive = false;\n    this.loopRunning = false;\n\n    for (const entry of this.pool) {\n      try {\n        entry.adController.destroy();\n      } catch (error) {\n        if (this.deps.debug) {\n          console.warn(\"[PRELOAD-POOL] Error destroying preloaded controller:\", error);\n        }\n      }\n    }\n\n    this.pool = [];\n\n    if (this.deps.debug) {\n      console.log(\"[PRELOAD-POOL] Preload pool stopped and cleaned up\");\n    }\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\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\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  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  sendAdLoadedTracking,\n  sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport type { AdTimingService } from \"./AdTimingService\";\nimport type { AdPreloadPool } from \"./AdPreloadPool\";\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  getLiveSyncPosition(): number | undefined;\n  generateVastUrls(baseUrl: string, count: 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 preloadPool: AdPreloadPool;\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    preloadPool: AdPreloadPool,\n    adConfig: AdConfigManager,\n    cueManager: Scte35CueManager,\n    placeholder: PlaceholderLayer\n  ) {\n    this.host = host;\n    this.timing = timing;\n    this.preloadPool = preloadPool;\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  // ───────────────────────────────────────────────────────────────\n  //  IMA event listeners\n  // ───────────────────────────────────────────────────────────────\n\n  attachImaEventListeners(): void {\n    const adPlayer = this.host.getAdPlayer();\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      ).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      ).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    let firstAdUrl: string | undefined;\n    let usePreloadedAd = false;\n    let preloadedController: AdController | undefined;\n\n    const preloaded = this.preloadPool.getPreloadedAd();\n    if (preloaded) {\n      firstAdUrl = preloaded.vastUrl;\n      preloadedController = preloaded.adController;\n      usePreloadedAd = true;\n\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n      ).catch(() => {});\n      if (this.debug) {\n        console.log(\"[CONTINUOUS-FETCH] Using preloaded ad from pool (preloaded in advance, ready immediately!)\");\n      }\n    } else if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {\n      this.adRequestQueue = [...this.pendingAdBreak.vastUrls];\n      firstAdUrl = this.adRequestQueue.shift();\n\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Pool empty, using prefetched URLs (${this.adRequestQueue.length + 1} available)`);\n      }\n\n      this.clearPendingAdBreak();\n    } else {\n      if (this.debug) {\n        console.log(\"[CONTINUOUS-FETCH] Generating new ad URLs...\");\n      }\n\n      const firstAdUrlArray = this.host.generateVastUrls(baseVastUrl, 1);\n      firstAdUrl = firstAdUrlArray[0];\n      this.adRequestQueue = [];\n    }\n\n    if (!firstAdUrl) {\n      if (this.debug) {\n        console.warn(\"[CONTINUOUS-FETCH] Failed to get first ad URL\");\n      }\n      this.handleAdPodComplete();\n      return;\n    }\n\n    if (this.debug) {\n      console.log(\"[CONTINUOUS-FETCH] First VAST URL:\", firstAdUrl);\n    }\n\n    try {\n      if (usePreloadedAd && preloadedController) {\n        if (!this.timing.ensureLoadedAdFitsBudget(preloadedController)) {\n          this.timing.rejectLoadedAdForDuration(preloadedController);\n          this.startContinuousFetching(baseVastUrl);\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n\n        const adPlayer = this.host.getAdPlayer();\n        const preservedMuted = adPlayer.getOriginalMutedState();\n        const preservedVolume = adPlayer.getOriginalVolume();\n        adPlayer.destroy();\n        this.host.video.muted = true;\n        this.host.setAdPlayer(preloadedController);\n        preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n\n        this.attachImaEventListeners();\n\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] Using preloaded ad, resuming and starting playback immediately (no request delay!)\");\n        }\n\n        preloadedController.resume();\n\n        this.timing.consecutiveFailures = 0;\n        this.startContinuousFetching(baseVastUrl);\n\n        if (!this.preloadPool.active) {\n          this.preloadPool.active = true;\n        }\n        if (!this.preloadPool.isLoopRunning) {\n          this.preloadPool.preloadPoolLoop(baseVastUrl);\n        }\n\n        await preloadedController.play();\n        this.timing.markAdStarted();\n\n        if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n          this.timing.scheduleAdStopAtBreakBoundary();\n        }\n\n        const adVolume = currentMuted ? 0 : currentVolume;\n        preloadedController.setAdVolume(adVolume);\n      } else {\n        const adPlayer = this.host.getAdPlayer();\n        await this.timing.enforceGlobalRateLimit();\n        this.timing.lastAdRequestTime = Date.now();\n        await adPlayer.requestAds(firstAdUrl);\n        sendAdLoadedTracking(\n          this.host.config.licenseKey,\n          { source: \"hls\", vastUrl: firstAdUrl, timestamp: new Date().toISOString() }\n        ).catch(() => {});\n\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] First ad request successful, starting playback\");\n        }\n\n        if (!this.timing.ensureLoadedAdFitsBudget(adPlayer)) {\n          this.timing.rejectLoadedAdForDuration(adPlayer);\n          this.recreateAdController();\n          this.startContinuousFetching(baseVastUrl);\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n\n        this.timing.consecutiveFailures = 0;\n        this.startContinuousFetching(baseVastUrl);\n\n        if (!this.preloadPool.active) {\n          this.preloadPool.startPreloadPool(baseVastUrl, []);\n        }\n\n        await adPlayer.play();\n        this.timing.markAdStarted();\n\n        if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n          this.timing.scheduleAdStopAtBreakBoundary();\n        }\n\n        const adVolume = currentMuted ? 0 : currentVolume;\n        adPlayer.setAdVolume(adVolume);\n      }\n    } catch (error) {\n      if (this.debug) {\n        console.warn(\"[CONTINUOUS-FETCH] First ad request failed:\", error);\n      }\n\n      if (!usePreloadedAd) {\n        const fallbackPreloaded = this.preloadPool.getPreloadedAd();\n        if (fallbackPreloaded) {\n          if (this.debug) {\n            console.log(\"[CONTINUOUS-FETCH] First ad failed, using preloaded fallback\");\n          }\n\n          try {\n            if (!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) {\n              this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);\n              this.startContinuousFetching(baseVastUrl);\n              await this.tryNextAvailableAdWithRateLimit();\n              return;\n            }\n\n            this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);\n\n            this.timing.consecutiveFailures = 0;\n            this.startContinuousFetching(baseVastUrl);\n\n            if (!this.preloadPool.active) {\n              this.preloadPool.active = true;\n              this.preloadPool.preloadPoolLoop(baseVastUrl);\n            }\n\n            const ap = this.host.getAdPlayer();\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            const adVolume = currentMuted ? 0 : currentVolume;\n            ap.setAdVolume(adVolume);\n\n            return;\n          } catch (fallbackError) {\n            if (this.debug) {\n              console.warn(\"[CONTINUOUS-FETCH] Preloaded fallback also failed:\", fallbackError);\n            }\n          }\n        }\n      }\n\n      if (this.timing.isTemporaryAdError(error as Error)) {\n        this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] First ad had temporary error (no-fill) - will try alternatives\");\n        }\n      } else {\n        this.timing.failedVastUrls.add(firstAdUrl);\n        if (this.debug) {\n          console.log(\"[CONTINUOUS-FETCH] First ad had permanent error - URL blacklisted\");\n        }\n      }\n      this.timing.consecutiveFailures++;\n\n      this.startContinuousFetching(baseVastUrl);\n      await this.tryNextAvailableAdWithRateLimit();\n    }\n  }\n\n  private swapToPreloadedAdPlayer(preloadedController: AdController): void {\n    const adPlayer = this.host.getAdPlayer();\n    const preservedMuted = adPlayer.getOriginalMutedState();\n    const preservedVolume = adPlayer.getOriginalVolume();\n    adPlayer.destroy();\n    this.host.video.muted = true;\n    this.host.setAdPlayer(preloadedController);\n    this.attachImaEventListeners();\n    preloadedController.updateOriginalMutedState(preservedMuted, preservedVolume);\n    preloadedController.resume();\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.host.generateVastUrls(baseVastUrl, 1)[0];\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    const preloaded = this.preloadPool.getPreloadedAd();\n    if (preloaded) {\n      if (this.debug) {\n        console.log(`[CONTINUOUS-FETCH] Using preloaded ad from pool`);\n      }\n\n      sendAdLoadedTracking(\n        this.host.config.licenseKey,\n        { source: \"hls\", vastUrl: preloaded.vastUrl, timestamp: new Date().toISOString() }\n      ).catch(() => {});\n\n      try {\n        if (!this.timing.ensureLoadedAdFitsBudget(preloaded.adController)) {\n          this.timing.rejectLoadedAdForDuration(preloaded.adController);\n          await this.tryNextAvailableAdWithRateLimit();\n          return;\n        }\n\n        this.swapToPreloadedAdPlayer(preloaded.adController);\n\n        const ap = this.host.getAdPlayer();\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\n        this.timing.consecutiveFailures = 0;\n        return;\n      } catch (error) {\n        if (this.debug) {\n          console.warn(\"[CONTINUOUS-FETCH] Preloaded ad failed to play:\", error);\n        }\n      }\n    }\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      ).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        const preloadedFallback = this.preloadPool.getPreloadedAd();\n        if (preloadedFallback) {\n          if (this.debug) console.log(\"[AD-ERROR] Play failed, trying preloaded fallback ad\");\n          try {\n            if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n              this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n              throw playError;\n            }\n            this.timing.clearAdFailsafeTimer();\n            this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n            this.timing.consecutiveFailures = 0;\n            const fbAp = this.host.getAdPlayer();\n            await fbAp.play();\n            this.timing.markAdStarted();\n            if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {\n              this.timing.scheduleAdStopAtBreakBoundary();\n            }\n            fbAp.setAdVolume(getAdAudioVolume(fbAp));\n            return;\n          } catch (fallbackError) {\n            if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n          }\n        }\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      const preloadedFallback = this.preloadPool.getPreloadedAd();\n      if (preloadedFallback) {\n        if (this.debug) console.log(\"[AD-ERROR] Request failed, trying preloaded fallback ad\");\n        try {\n          if (!this.timing.ensureLoadedAdFitsBudget(preloadedFallback.adController)) {\n            this.timing.rejectLoadedAdForDuration(preloadedFallback.adController);\n            throw error;\n          }\n          this.timing.clearAdRequestWatchdog();\n          this.timing.clearAdFailsafeTimer();\n          this.swapToPreloadedAdPlayer(preloadedFallback.adController);\n          this.timing.consecutiveFailures = 0;\n          const fbAp = this.host.getAdPlayer();\n          await fbAp.play();\n          this.timing.markAdStarted();\n          fbAp.setAdVolume(getAdAudioVolume(fbAp));\n          return;\n        } catch (fallbackError) {\n          if (this.debug) console.warn(\"[AD-ERROR] Preloaded fallback also failed:\", fallbackError);\n        }\n      }\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.preloadPool.stop();\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    if (this.host.shouldContinueLiveStreamDuringAds()) {\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      }\n\n      if (this.host.video.paused) {\n        if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n        this.host.video.play()?.catch(() => {});\n      } else {\n        if (this.debug) console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n      }\n    } else if (this.host.video.paused) {\n      this.host.video.play()?.catch(() => {});\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"]}