stormcloud-video-player 0.5.11 → 0.5.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/StormcloudVideoPlayer.cjs","../../src/ui/StormcloudVideoPlayer.tsx","../../src/player/StormcloudVideoPlayer.ts","../../src/sdk/prebid.ts","../../src/sdk/vastParser.ts","../../src/sdk/prebidAdLayer.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/browserCompat.ts"],"names":["__create","Object","create","__defProp","__copyProps","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","to","from","except","desc","call","key","__toESM","mod","isNodeMode","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayerComponent","module","exports","import_react","require","import_hls","DEFAULT_TIMEOUT_MS","AUCTION_URL","createPrebidManager","options","initialized","debug","log","args","console","warn","parseResponse","data","bids","seatbids","seatbid","currency","cur","seat","bidArray","bid","cacheUrl","ext","prebid","cache","vastXml","url","adm","bidResponse","bidder","cpm","price","width","w","height","h","adId","id","impId","impid","creativeId","crid","vastUrl","adomain","push","sort","a","b","initialize","requestBids","timeout","controller","timeoutId","fetchOptions","response","body","error","Error","AbortController","setTimeout","abort","method","signal","fetch","clearTimeout","ok","text","catch","status","slice","json","responsetimemillis","errors","length","toFixed","REQUEST_BIDS_MAX_RETRIES","REQUEST_BIDS_BACKOFF_MS","requestBidsUntilResponse","lastError","attempt","err","delay","Promise","resolve","destroy","isInitialized","isHlsType","type","includes","isMp4Type","parseVastXml","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","Math","round","parseFloat","mediaFileElements","querySelectorAll","mediaFiles","forEach","mf","index","trim","substring","isHls","isMp4","accepted","bitrateAttr","bitrateValue","bitrate","aIsMp4","bIsMp4","trackingUrls","impression","start","firstQuartile","midpoint","thirdQuartile","complete","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","eventKey","el","event","clickThrough","vastTagUrl","mode","credentials","headers","Accept","referrerPolicy","statusText","createEmptyTrackingState","fireTrackingPixels","urls","sessionId","trackingUrl","img","Image","onerror","src","LOG","resolveBidToVastAd","winner","ad","fetchAndParseVastAd","createPrebidAdLayer","contentVideo","adPlaying","originalMutedState","originalVolume","max","min","volume","listeners","Map","mainHlsInstance","continueLiveStreamDuringAds","adVideoElement","adHls","adContainerEl","currentAd","destroyed","tornDown","trackingFired","emit","payload","set","Array","fn","generateSessionId","Date","now","random","toString","substr","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","firstFile","scoredFiles","widthDiff","fileBitrate","file","isHlsMediaFile","selectBestMediaFile","mainQuality","map","abs","heightDiff","resolutionDiff","bitrateDiff","score","createAdVideoElement","video","document","createElement","style","position","left","muted","top","objectFit","backgroundColor","playsInline","setupAdEventListeners","addEventListener","progress","currentTime","handleAdComplete","e","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","visibility","opacity","teardownCurrentPlayback","removeAttribute","load","mediaFile","play","startHlsPlayback","Hls","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","handleAdError","ERROR","_event","fatal","canPlayType","startPlayback","startNativePlayback","playAd","container","contentVolume","adVolume","reject","right","bottom","alignItems","zIndex","parentElement","appendChild","updateOptions","opts","paused","stop","remove","removeChild","clear","isAdPlaying","resize","listener","has","Set","add","off","delete","updateOriginalMutedState","nextVolume","Number","isNaN","getOriginalMutedState","getOriginalVolume","setAdVolume","getAdVolume","showPlaceholder","justifyContent","hidePlaceholder","cachedBrowserId","getClientInfo","screen","window","navigator","ua","userAgent","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","test","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","location","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","crypto","subtle","digest","Uint8Array","TextEncoder","encode","unescape","encodeURIComponent","charCodeAt","padStart","padEnd","TRACK_URL","sendTrackRequest","licenseKey","sendInitialTracking","browserId","trackingData","sendAdDetectTracking","adDetectInfo","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","sendHeartbeat","heartbeatData","toISOString","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","replace","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","result","len","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","getChromeVersion","getWebKitVersion","chromeVersion","detectBrowser","getPlatform","userAgentData","supportsModernJS","version","majorVersion","isLegacyTV","supportsIMA","recommendedAdPlayer","webOSVersion","chromeVersionNum","webkitVersion","tizenVersion","supportsGoogleIMA","browser","logBrowserInfo","imaSupport","getBrowserConfigOverrides","overrides","allowNativeHls","StormcloudVideoPlayer","config","pendingNextAdBids","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","adRequestTokenCounter","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","continuousFetchingActive","adRequestQueue","maxPlaceholderDurationMs","isShowingPlaceholder","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","pendingAdBreak","prefetchAdPromise","savedMutedStateBeforeScte","consecutiveFailures","maxConsecutiveFailures","lastAdRequestTime","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","browserOverrides","videoElement","debugAdTiming","prebidManager","adLayer","adRequest","attach","initializeTracking","shouldUseNativeHls","isLive","adBehavior","hls","import_hls2","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","liveSyncDuration","highBufferWatchdogPeriod","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","minSegments","details","live","shouldContinueLiveStreamDuringAds","autoplay","minSegmentsBeforePlay","LEVEL_LOADED","_evt","fragments","fragmentsToScan","frag","tagList","isArray","entry","tag","idx","hasScteOut","attrs","durationSeconds","parseCueOutDuration","marker","raw","earlyDetection","startAdPrefetch","sn","FRAG_BUFFERED","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","onId3Tag","FRAG_CHANGED","prog","parseCueOutCont","elapsed","onScte35Marker","parseAttributeList","hasScteIn","toNumber","klass","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","getAdSource","attachAdLayerEventListeners","source","adIndex","errorPayload","errorMessage","errorCode","code","vastErrorCode","message","cause","innerError","causeMessage","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","expectedAdBreakDurationMs","adStopTimerId","scheduleAdStopCountdown","getRemainingAdMs","currentMuted","currentVolume","hidePlaceholderLayer","remaining","restoredMuted","restoredVolume","showPlaceholderLayer","handleAdPodComplete","ensurePlaceholderContainer","placeholderContainer","transition","wasHidden","offsetHeight","requestAnimationFrame","timeUpdateHandler","onTimeUpdate","emptiedHandler","wasPaused","streamType","getStreamType","canNative","parseScte35FromId3","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","cueInMatch","daterangeMatch","bin","parseScte35Binary","decoder","TextDecoder","decode","out","fromCharCode","hasPendingAdBreak","durationMs","currentAdBreakStartWallClockMs","detectedAtFragmentSn","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","handleAdStart","tol","driftToleranceMs","nowMs","estCurrentPtsMs","deltaMs","floor","markerPtsMs","tolerance","scheduleAdStartIn","clearAdStartTimer","elapsedMs","remainingMs","hasQueuedAds","activeAdRequest","clearAdStopTimer","num","dStr","d","res","durationMatch","elapsedMatch","slashMatch","regex","exec","rawVal","val","n","splice_command_type","remainingInByte","BitReader","buf","bytePos","bitPos","readBits","numBits","currentByte","shift","toRead","mask","bits","skipBits","tableId","r","sectionLength","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","timeSpecifiedFlag","componentCount","high","low","durationTicks","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","getCurrentAdIndex","getTotalAdsInBreak","clearPendingAdBreak","prefetchTimerId","startContinuousFetchLoop","continuousFetchLoopPromise","runContinuousFetchLoop","backoffMs","mult","pow","_marker","adBreakDurationMs","state","stopContinuousFetching","tryNextAvailableAdWithRateLimit","backoffMultiplier","backoffDelay","effectiveMinInterval","timeSinceLastRequest","waitTime","tryNextAvailableAd","_retryCount","showPlaceholderAndWaitForAds","checkInterval","maxChecks","_currentTimeSec","ensureAdStoppedByTimer","ms","adBreakCheckIntervalMs","maxAdBreakExtensionMs","maxExtensionMsConfig","elapsedSinceStartMs","expectedDurationMs","pendingAds","overrunMs","maxExtensionMs","checkIntervalMs","delayMs","adStartTimerId","updatePtsDrift","ptsSecondsSample","sampleMs","alpha","isTizen","startAdRequestWatchdog","token","timeoutMs","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","startAdFailsafeTimer","adFailsafeTimerId","failsafeMs","videoPaused","imaAdPlaying","extra","MAX_SAFE_INTEGER","toggleMute","currentPerceptualState","isMuted","newMutedState","toggleFullscreen","requestFullscreen","setMuted","setVolume","clampedVolume","getVolume","isFullscreen","fullscreenElement","clientWidth","clientHeight","removeEventListener","clearInterval","import_fa","import_jsx_runtime","CRITICAL_PROPS","React","memo","props","showCustomControls","hideLoadingIndicator","onVolumeToggle","onFullscreenToggle","onControlClick","onReady","wrapperClassName","wrapperStyle","className","controls","preload","poster","children","restVideoAttrs"],"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/player/StormcloudVideoPlayer.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\n\n// src/sdk/prebid.ts\nvar DEFAULT_TIMEOUT_MS = 3e3;\nvar AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\nfunction createPrebidManager(options = {}) {\n let initialized = false;\n const debug = options.debug ?? false;\n function log(...args) {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n function warn(...args) {\n console.warn(\"[Prebid]\", ...args);\n }\n function parseResponse(data) {\n const bids = [];\n const seatbids = data?.seatbid || [];\n const currency = data?.cur || \"USD\";\n for (const seatbid of seatbids) {\n const seat = seatbid.seat || \"unknown\";\n const bidArray = seatbid.bid || [];\n for (const bid of bidArray) {\n const cacheUrl = bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml = bid.adm || void 0;\n const bidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n bids.push(bidResponse);\n }\n }\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n async function initialize() {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n async function requestBids() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n const timeout = DEFAULT_TIMEOUT_MS;\n log(\"Fetching auction response from:\", AUCTION_URL);\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2e3);\n try {\n const fetchOptions = {\n method: \"POST\"\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n const data = await response.json();\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency} ${b.width}x${b.height}` + (b.vastUrl ? \" [cached VAST]\" : \"\") + (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n return bids;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2e3}ms`);\n return [];\n }\n throw error;\n }\n }\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n async function requestBidsUntilResponse() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n function destroy() {\n initialized = false;\n log(\"Destroyed\");\n }\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n }\n };\n}\n\n// src/sdk/vastParser.ts\nfunction isHlsType(type) {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\nfunction isMp4Type(type) {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\nfunction parseVastXml(xmlString, filter = \"all\", logPrefix = \"[VastParser]\") {\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 `${logPrefix} XML parsing error (malformed VAST XML):`,\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(`${logPrefix} No Ad element found in VAST XML`);\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\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 + Math.round(parseFloat(durationParts[2] || \"0\"));\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible media files found in VAST XML`);\n }\n return null;\n }\n const trackingUrls = {\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 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 const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\nasync function fetchAndParseVastAd(vastTagUrl, filter = \"all\", logPrefix = \"[VastParser]\") {\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 const vastXml = await response.text();\n console.log(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml, filter, logPrefix);\n}\nfunction createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n}\nfunction fireTrackingPixels(urls, sessionId, logPrefix = \"[VastParser]\") {\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 const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n\n// src/sdk/prebidAdLayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar LOG = \"[PrebidAdLayer]\";\nfunction resolveBidToVastAd(winner, logPrefix) {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\nfunction createPrebidAdLayer(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 let mainHlsInstance = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels2(urls) {\n fireTrackingPixels(urls, sessionId, LOG);\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance?.levels) return null;\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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0];\n if (mediaFiles.length === 1) return firstFile;\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\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 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 };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n function isHlsMediaFile(file) {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels2(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels2(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels2(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) return;\n if (adVideoElement.muted) {\n fireTrackingPixels2(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels2(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels2(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels2(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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n function handleAdError() {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n function teardownCurrentPlayback() {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n function startNativePlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n function startHlsPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n if (import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adHls = new import_hls.default({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n function startPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n async function playAd(bids) {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n const winner = bids[0];\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels2(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n updateOptions(opts) {\n if (opts.continueLiveStreamDuringAds !== void 0) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== void 0) {\n mainHlsInstance = opts.mainHlsInstance ?? void 0;\n }\n },\n playAd,\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {\n });\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = void 0;\n tornDown = false;\n },\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"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 },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, 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 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 adVideoElement.volume = Math.max(0, Math.min(1, volume));\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 };\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 getBrowserID(clientInfo) {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n const fingerprintString = JSON.stringify(clientInfo);\n if (typeof crypto !== \"undefined\" && crypto.subtle && 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(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\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 const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.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 cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\nvar TRACK_URL = \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\nasync function sendTrackRequest(licenseKey, body) {\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\nasync function sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendAdDetectTracking(licenseKey, adDetectInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\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/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 supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer = \"ima\";\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 if (webOSVersion !== void 0 && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (webOSVersion !== void 0 && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\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 if (tizenVersion !== void 0 && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (tizenVersion !== void 0 && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\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 supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\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 supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\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}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.pendingNextAdBids = null;\n this.continuousFetchLoopPromise = null;\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\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.adRequestTokenCounter = 0;\n this.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.continuousFetchingActive = false;\n this.adRequestQueue = [];\n this.maxPlaceholderDurationMs = 5e3;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 20;\n this.pendingAdBreak = null;\n this.prefetchAdPromise = null;\n this.savedMutedStateBeforeScte = null;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.lastAdRequestTime = 0;\n this.minAdRequestIntervalMs = 2500;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.prebidManager = createPrebidManager(\n config.debugAdTiming !== void 0 ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming\n });\n }\n async adRequest() {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n this.initializeTracking();\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\"\n }\n );\n }\n this.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\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 if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n if (this.config.debugAdTiming) {\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: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null\n });\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\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.inAdBreak || this.pendingAdBreak) {\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\") ? this.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 = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3AF} EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n this.startAdPrefetch(marker, frag?.sn);\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\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 = this.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.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.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 = this.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.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\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.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n getAdSource() {\n return \"prebid\";\n }\n attachAdLayerEventListeners() {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {\n });\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.adLayer.setAdVolume(adVolume);\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) this.video.muted = restoredMuted;\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) this.video.volume = restoredVolume;\n return;\n }\n this.consecutiveFailures = 0;\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n setTimeout(() => {\n if (!this.inAdBreak || bids.length === 0) return;\n this.currentAdIndex++;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adLayer.playAd(bids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, 500);\n return;\n }\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: remaining time low and duration known, ending ad pod\");\n }\n this.handleAdPodComplete();\n } else {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n }\n });\n }\n ensurePlaceholderContainer() {\n if (this.placeholderContainer) {\n return;\n }\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 = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n showPlaceholderLayer() {\n this.ensurePlaceholderContainer();\n if (!this.placeholderContainer) {\n return;\n }\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer\");\n }\n }\n hidePlaceholderLayer() {\n if (!this.placeholderContainer) {\n return;\n }\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\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.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.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 shouldUseNativeHls() {\n const streamType = this.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 onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.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 = this.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 = this.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 = this.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 = this.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 = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n 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 }\n onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\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.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.pendingAdBreak?.marker.durationSeconds != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...marker.durationSeconds != null && { durationSeconds: marker.durationSeconds },\n ...marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds },\n ...this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn\n }\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\"\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\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.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null\n });\n }\n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\n }\n return;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n if (adPlaying) {\n this.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n 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 }\n 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 }\n 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 }\n 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 }\n 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 }\n parseScte35Binary(data) {\n class BitReader {\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 }\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 r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return void 0;\n }\n 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 if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\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 timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds = void 0;\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 if (outOfNetwork) {\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { splice_command_type: 5 }\n };\n return marker;\n }\n return void 0;\n }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n isAdPlaying() {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n isShowingAds() {\n return this.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 shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) {\n return false;\n }\n if (!this.isLiveStream) {\n return false;\n }\n return true;\n }\n startAdPrefetch(marker, fragmentSn) {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n this.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n isFetching: false,\n fetchStartTime: Date.now()\n };\n this.prefetchAdPromise = this.adRequest().then(() => {\n }).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.prefetchAdPromise = null;\n this.pendingAdBreak = null;\n }\n startContinuousFetchLoop() {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n async runContinuousFetchLoop() {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing)\");\n }\n } else {\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = this.video.muted ? 0 : this.video.volume;\n this.adLayer.setAdVolume(adVolume);\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n async handleAdStart(_marker) {\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : void 0;\n if (this.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4FA} ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\n this.savedMutedStateBeforeScte = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n this.showAds = true;\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n this.clearPendingAdBreak();\n this.startContinuousFetchLoop();\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 0 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n }\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = false;\n this.hidePlaceholderLayer();\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Stopping continuous ad fetching\");\n }\n }\n async tryNextAvailableAdWithRateLimit() {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n return this.tryNextAvailableAd(0);\n }\n async tryNextAvailableAd(_retryCount = 0) {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(this.video.muted ? 0 : this.video.volume);\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2B1B Showing placeholder for ${waitTime}ms while waiting for ad response`);\n }\n this.isShowingPlaceholder = true;\n this.adLayer.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.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Too many failures during placeholder wait\");\n }\n break;\n }\n if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n return;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F0 Placeholder timeout, ending ad break\");\n }\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n onTimeUpdate(_currentTimeSec) {\n if (this.adLayer.isAdPlaying()) return;\n }\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 if (!this.inAdBreak) return;\n this.adStopTimerId = void 0;\n const adPlaying = this.adLayer.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\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 : 6e4;\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (adPlaying) {\n this.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\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 handleAdPodComplete() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3C1} Ad pod complete - cleaning up\");\n }\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n this.adLayer.stop().catch(() => {\n });\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n const isTizen = detectBrowser().tizenVersion !== void 0;\n if (isTizen && this.hls) {\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Tizen: re-attached HLS to video element after ad break to restore audio\");\n }\n }\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {\n });\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n if (isTizen && !restoredMuted) {\n requestAnimationFrame(() => {\n this.video.muted = false;\n this.video.volume = restoredVolume;\n });\n }\n }\n handleAdFailure() {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\n );\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n }\n }\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.handleAdFailure();\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 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 imaAdPlaying: this.adLayer.isAdPlaying()\n });\n this.handleAdFailure();\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 = {}) {\n if (!this.config.debugAdTiming) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: this.showAds,\n adPlaying: this.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n getRemainingAdMs() {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n toggleMute() {\n if (this.adLayer.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n this.adLayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adLayer.setAdVolume(newMutedState ? 0 : this.adLayer.getOriginalVolume());\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n isMuted() {\n if (this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n this.video.muted = muted;\n if (adPlaying) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n this.adLayer.setAdVolume(muted ? 0 : this.adLayer.getOriginalVolume());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n getVolume() {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.getAdVolume();\n }\n return this.video.volume;\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (this.adLayer && this.adLayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n this.adLayer.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = void 0;\n }\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n this.hls?.destroy();\n this.adLayer?.destroy();\n this.adRequestQueue = [];\n this.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 \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\"\n];\nvar StormcloudVideoPlayerComponent = import_react.default.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\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 minSegmentsBeforePlay,\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 [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0 });\n const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);\n const [isMuted, setIsMuted] = import_react.default.useState(false);\n const [isFullscreen, 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, setVolume] = 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 [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 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 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 };\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 };\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 shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);\n const criticalPropsKey = (0, import_react.useMemo)(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs\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 (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 (minSegmentsBeforePlay !== void 0)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\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 setAdStatus((prev) => {\n if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds };\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 setVolume(\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 === videoRef.current?.parentElement\n );\n };\n const interval = setInterval(updateStates, 200);\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\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 if (videoRef.current) {\n const video2 = videoRef.current;\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 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: `\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper: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 \n .stormcloud-video-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 \n *:fullscreen {\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 }\n ` }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: `stormcloud-video-wrapper ${wrapperClassName || \"\"}`,\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen ? \"fixed\" : \"relative\",\n top: isFullscreen ? 0 : void 0,\n left: isFullscreen ? 0 : void 0,\n overflow: \"hidden\",\n width: isFullscreen ? \"100vw\" : \"100%\",\n height: isFullscreen ? \"100vh\" : \"auto\",\n minHeight: isFullscreen ? \"100vh\" : \"auto\",\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : void 0,\n backgroundColor: isFullscreen ? \"#000\" : void 0,\n borderRadius: isFullscreen ? 0 : void 0,\n boxShadow: isFullscreen ? \"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: isFullscreen ? \"100%\" : \"auto\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen ? \"100%\" : \"none\",\n objectFit: isFullscreen ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen ? \"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.jsx)(\n import_fa.FaSpinner,\n {\n className: \"stormcloud-loading-indicator\",\n size: 42,\n color: \"white\",\n style: {\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\"\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: \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow: \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\"\n },\n children: \"License Key Required\"\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\"\n },\n 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 }\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: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\"\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n },\n title: \"Play\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPlay,\n {\n size: 36,\n color: \"white\",\n style: {\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\"\n }\n }\n )\n }\n ),\n shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"8px\",\n background: \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\"\n },\n onClick: handleTimelineSeek,\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n height: \"100%\",\n background: \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${duration > 0 ? currentTime / duration * 100 : 0}%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"-6px\",\n right: `${duration > 0 ? 100 - currentTime / duration * 100 : 100}%`,\n width: \"20px\",\n height: \"20px\",\n background: \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow: \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\"\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 flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\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: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: handlePlayPause,\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow = \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow = \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n },\n title: isPlaying ? \"Pause\" : \"Play\",\n children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPause,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPlay,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor = \"rgba(59, 130, 246, 0.4)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.15)\";\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n },\n onMouseLeave: (e) => {\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow: \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\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: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\"\n },\n children: [\n formatTime(currentTime),\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: `${12 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n onClick: () => setShowSpeedMenu(!showSpeedMenu),\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\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: \"12px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow: \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\"\n },\n children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n onClick: () => handlePlaybackRateChange(speed),\n style: {\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background: playbackRate === speed ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\" : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom: speed !== 2 ? \"1px solid rgba(255, 255, 255, 0.05)\" : \"none\"\n },\n onMouseEnter: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n },\n onMouseLeave: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"transparent\";\n }\n },\n children: [\n speed,\n \"x\"\n ]\n },\n speed\n )\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n )\n ]\n }\n )\n ]\n }\n )\n ]\n }\n ) }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor = \"rgba(96, 165, 250, 0.8)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.7)\";\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow: \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\n }\n )\n ]\n }\n )\n }\n )\n ] })\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\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 } 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 FaSpinner,\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 \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n] as const;\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 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 minSegmentsBeforePlay,\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 [adStatus, setAdStatus] = React.useState<{\n showAds: boolean;\n currentIndex: number;\n totalAds: number;\n }>({ showAds: false, currentIndex: 0, totalAds: 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 [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\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 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 };\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 };\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 shouldShowEnhancedControls =\n showCustomControls && (isHlsStream ? allowNativeHls : true);\n\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs,\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 (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 (minSegmentsBeforePlay !== undefined)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\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\n setAdStatus((prev) => {\n if (\n prev.showAds !== showAds ||\n prev.currentIndex !== currentIndex ||\n prev.totalAds !== totalAds\n ) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds };\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 === videoRef.current?.parentElement\n );\n };\n\n const interval = setInterval(updateStates, 200);\n\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\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 if (videoRef.current) {\n const video = videoRef.current;\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 return (\n <>\n <style>\n {`\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper: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 \n .stormcloud-video-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 \n *:fullscreen {\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 }\n `}\n </style>\n <div\n className={`stormcloud-video-wrapper ${wrapperClassName || \"\"}`}\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 maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : undefined,\n backgroundColor: isFullscreen ? \"#000\" : undefined,\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: isFullscreen ? \"100%\" : \"auto\",\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 <FaSpinner\n className=\"stormcloud-loading-indicator\"\n size={42}\n color=\"white\"\n style={{\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\",\n }}\n />\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:\n \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\",\n }}\n >\n <div\n style={{\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\",\n }}\n >\n License Key Required\n </div>\n <div\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\",\n }}\n >\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 {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:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n }}\n title=\"Play\"\n >\n <FaPlay\n size={36}\n color=\"white\"\n style={{\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n }}\n />\n </div>\n )}\n\n {shouldShowEnhancedControls && !showLicenseWarning ? (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background:\n \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10,\n }}\n >\n <div\n style={{\n width: \"100%\",\n height: \"8px\",\n background:\n \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\",\n }}\n onClick={handleTimelineSeek}\n >\n <div\n style={{\n height: \"100%\",\n background:\n \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${\n duration > 0 ? (currentTime / duration) * 100 : 0\n }%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"-6px\",\n right: `${\n duration > 0\n ? 100 - (currentTime / duration) * 100\n : 100\n }%`,\n width: \"20px\",\n height: \"20px\",\n background:\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow:\n \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\",\n }}\n >\n <button\n onClick={handlePlayPause}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow =\n \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow =\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n }}\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <FaPause\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaPlay\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor =\n \"rgba(59, 130, 246, 0.4)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.15)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n // Hover effect removed\n }}\n onMouseLeave={(e) => {\n // Hover effect removed\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow:\n \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow:\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <div\n style={{\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n }}\n >\n {formatTime(currentTime)} / {formatTime(duration)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\",\n }}\n >\n <button\n onClick={() => setShowSpeedMenu(!showSpeedMenu)}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${\n 14 * responsiveScale\n }px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\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: \"12px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow:\n \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\",\n }}\n >\n {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => (\n <button\n key={speed}\n onClick={() =>\n handlePlaybackRateChange(speed)\n }\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background:\n playbackRate === speed\n ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\"\n : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition:\n \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom:\n speed !== 2\n ? \"1px solid rgba(255, 255, 255, 0.05)\"\n : \"none\",\n }}\n onMouseEnter={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background =\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n }}\n onMouseLeave={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background = \"transparent\";\n }\n }}\n >\n {speed}x\n </button>\n )\n )}\n </div>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current\n .toggleFullscreen()\n .catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n </div>\n </div>\n </div>\n </>\n ) : (\n showCustomControls &&\n !showLicenseWarning && (\n <div\n style={{\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor =\n \"rgba(96, 165, 250, 0.8)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.7)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow:\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n </div>\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 Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n AdBreak,\n} from \"../types\";\nimport type { PrebidBidResponse } from \"../types\";\nimport { createPrebidManager } from \"../sdk/prebid\";\nimport { createPrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport type { PrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport {\n sendInitialTracking,\n sendHeartbeat,\n sendAdDetectTracking,\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport { logBrowserInfo, getBrowserConfigOverrides, detectBrowser } from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private prebidManager: ReturnType<typeof createPrebidManager>;\n private adLayer: PrebidAdLayer;\n private pendingNextAdBids: PrebidBidResponse[] | null = null;\n private continuousFetchLoopPromise: Promise<void> | null = null;\n private attached = false;\n private inAdBreak = false;\n private currentAdBreakStartWallClockMs: number | undefined;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private adPodQueue: string[] = [];\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n private currentAdIndex: number = 0;\n private totalAdsInBreak: number = 0;\n private showAds: boolean = false;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private adRequestTokenCounter = 0;\n private activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private continuousFetchingActive: boolean = false;\n private adRequestQueue: string[] = [];\n private maxPlaceholderDurationMs: number = 5000;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n \n private totalAdRequestsInBreak: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 20;\n \n private pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n private prefetchTimerId: number | undefined;\n private prefetchAdPromise: Promise<void> | null = null;\n private savedMutedStateBeforeScte: { muted: boolean; volume: number } | null = null;\n\n private consecutiveFailures: number = 0;\n private readonly maxConsecutiveFailures: number = 5;\n private lastAdRequestTime: number = 0;\n private readonly minAdRequestIntervalMs: number = 2500;\n private readonly backoffBaseMs: number = 1000;\n private readonly maxBackoffMs: number = 15000;\n private placeholderContainer: HTMLDivElement | undefined;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n \n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n this.prebidManager = createPrebidManager(\n config.debugAdTiming !== undefined ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming,\n });\n }\n\n private async adRequest(): Promise<PrebidBidResponse[]> {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n this.initializeTracking();\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\",\n }\n );\n }\n\n this.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\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 if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds()\n ? \"live (main video continues muted during ads)\"\n : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior,\n });\n }\n\n this.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null,\n });\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.config.debugAdTiming) {\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.inAdBreak || this.pendingAdBreak) {\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 ? this.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 = this.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.config.debugAdTiming) {\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.startAdPrefetch(marker, frag?.sn);\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) 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\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.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.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.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 = this.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.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\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.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private getAdSource(): \"prebid\" {\n return \"prebid\";\n }\n\n private attachAdLayerEventListeners(): void {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: new Date().toISOString(),\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {});\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n \n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n\n const currentMuted = this.video.muted;\n const currentVolume = this.video.volume;\n const adVolume = currentMuted ? 0 : currentVolume;\n this.adLayer.setAdVolume(adVolume);\n\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) this.video.muted = restoredMuted;\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) this.video.volume = restoredVolume;\n return;\n }\n\n this.consecutiveFailures = 0;\n\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n setTimeout(() => {\n if (!this.inAdBreak || bids.length === 0) return;\n this.currentAdIndex++;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adLayer.playAd(bids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, 500);\n return;\n }\n\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: remaining time low and duration known, ending ad pod\");\n }\n this.handleAdPodComplete();\n } else {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n }\n });\n }\n\n private ensurePlaceholderContainer(): void {\n if (this.placeholderContainer) {\n return;\n }\n\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 = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n\n private showPlaceholderLayer(): void {\n this.ensurePlaceholderContainer();\n \n if (!this.placeholderContainer) {\n return;\n }\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n \n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n \n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer\");\n }\n }\n\n private hidePlaceholderLayer(): void {\n if (!this.placeholderContainer) {\n return;\n }\n\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\n\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (\n this.nativeHlsMode &&\n this.videoSrcProtection &&\n !this.adLayer.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.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 = this.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 = this.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 = this.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 = this.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 = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private 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\n private onScte35Marker(marker: Scte35Marker): void {\n if (this.config.debugAdTiming) {\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.pendingAdBreak,\n });\n }\n\n if (marker.type === \"start\") {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n\n this.inAdBreak = true;\n const durationMs =\n marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : (this.pendingAdBreak?.marker.durationSeconds != null \n ? this.pendingAdBreak.marker.durationSeconds * 1000 \n : undefined);\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\" as const,\n timestamp: new Date().toISOString(),\n ...(marker.durationSeconds != null && { durationSeconds: marker.durationSeconds }),\n ...(marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds }),\n ...(this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn,\n }),\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n \n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null,\n });\n }\n \n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\n }\n return;\n }\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n \n if (adPlaying) {\n this.adLayer.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private 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\n private 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\n private 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\n private 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\n private 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\n private parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class 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 }\n\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 r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return undefined;\n }\n 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 if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\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 timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds: number | undefined = undefined;\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\n if (outOfNetwork) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { splice_command_type: 5 },\n } as Scte35Marker;\n return marker;\n }\n return undefined;\n }\n\n private 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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n private shouldContinueLiveStreamDuringAds(): boolean {\n if (this.config.allowNativeHls) {\n return false;\n }\n\n if (!this.isLiveStream) {\n return false;\n }\n\n return true;\n }\n\n private startAdPrefetch(marker: Scte35Marker, fragmentSn?: number): void {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n\n this.pendingAdBreak = {\n marker,\n ...(fragmentSn !== undefined ? { detectedAtFragmentSn: fragmentSn } : {}),\n isFetching: false,\n fetchStartTime: Date.now(),\n };\n\n this.prefetchAdPromise = this.adRequest().then(() => {}).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\n }\n\n private clearPendingAdBreak(): void {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = undefined;\n }\n this.prefetchAdPromise = null;\n this.pendingAdBreak = null;\n }\n\n private startContinuousFetchLoop(): void {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n\n private async runContinuousFetchLoop(): Promise<void> {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing)\");\n }\n } else {\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = this.video.muted ? 0 : this.video.volume;\n this.adLayer.setAdVolume(adVolume);\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const adBreakDurationMs =\n _marker.durationSeconds != null\n ? _marker.durationSeconds * 1000\n : undefined;\n\n if (this.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] 📺 ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\n this.savedMutedStateBeforeScte = null;\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n\n this.showAds = true;\n\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n this.clearPendingAdBreak();\n this.startContinuousFetchLoop();\n\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 0 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n }\n }\n\n private stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n \n this.hidePlaceholderLayer();\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Stopping continuous ad fetching\");\n }\n }\n\n private async tryNextAvailableAdWithRateLimit(): Promise<void> {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n \n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise(resolve => setTimeout(resolve, waitTime));\n }\n\n return this.tryNextAvailableAd(0);\n }\n\n private async tryNextAvailableAd(_retryCount: number = 0): Promise<void> {\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(this.video.muted ? 0 : this.video.volume);\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n }\n }\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⬛ Showing placeholder for ${waitTime}ms while waiting for ad response`);\n }\n\n this.isShowingPlaceholder = true;\n this.adLayer.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.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Too many failures during placeholder wait\");\n }\n break;\n }\n\n if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n return;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏰ Placeholder timeout, ending ad break\");\n }\n\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private onTimeUpdate(_currentTimeSec: number): void {\n if (this.adLayer.isAdPlaying()) return;\n }\n\n private 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 private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n if (!this.inAdBreak) return;\n\n this.adStopTimerId = undefined;\n\n const adPlaying = this.adLayer.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1000)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs =\n typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0\n ? maxExtensionMsConfig\n : 60000;\n\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n\n const shouldExtendAdBreak =\n (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n\n if (adPlaying) {\n this.adLayer.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(delayMs: number): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private 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 private handleAdPodComplete(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] 🏁 Ad pod complete - cleaning up\");\n }\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n\n this.adLayer.stop().catch(() => {});\n\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n const isTizen = detectBrowser().tizenVersion !== undefined;\n if (isTizen && this.hls) {\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Tizen: re-attached HLS to video element after ad break to restore audio\");\n }\n }\n\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {});\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n\n if (isTizen && !restoredMuted) {\n requestAnimationFrame(() => {\n this.video.muted = false;\n this.video.volume = restoredVolume;\n });\n }\n }\n\n private handleAdFailure(): void {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\n );\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n }\n }\n\n private 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.handleAdFailure();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n private 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 private 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 imaAdPlaying: this.adLayer.isAdPlaying(),\n });\n\n this.handleAdFailure();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n private 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 private logAdState(event: string, extra: Record<string, unknown> = {}): void {\n if (!this.config.debugAdTiming) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: this.showAds,\n adPlaying: this.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private getRemainingAdMs(): number {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n toggleMute(): void {\n if (this.adLayer.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n\n this.adLayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adLayer.setAdVolume(newMutedState ? 0 : this.adLayer.getOriginalVolume());\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.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 (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n\n isMuted(): boolean {\n if (this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.adLayer.isAdPlaying();\n\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (adPlaying) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n this.adLayer.setAdVolume(muted ? 0 : this.adLayer.getOriginalVolume());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.adLayer.isAdPlaying();\n\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n getVolume(): number {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.getAdVolume();\n }\n return this.video.volume;\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (this.adLayer && this.adLayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n this.adLayer.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n \n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = undefined;\n }\n \n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n \n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n this.hls?.destroy();\n this.adLayer?.destroy();\n this.adRequestQueue = [];\n this.consecutiveFailures = 0;\n }\n}\n","import type { PrebidBidResponse, PrebidManager } from \"../types\";\n\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\n\nexport interface PrebidManagerOptions {\n debug?: boolean;\n}\n\nexport function createPrebidManager(\n options: PrebidManagerOptions = {}\n): PrebidManager {\n let initialized = false;\n const debug = options.debug ?? false;\n\n function log(...args: any[]): void {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n\n function warn(...args: any[]): void {\n console.warn(\"[Prebid]\", ...args);\n }\n\n function parseResponse(data: any): PrebidBidResponse[] {\n const bids: PrebidBidResponse[] = [];\n const seatbids: any[] = data?.seatbid || [];\n const currency: string = data?.cur || \"USD\";\n\n for (const seatbid of seatbids) {\n const seat: string = seatbid.seat || \"unknown\";\n const bidArray: any[] = seatbid.bid || [];\n\n for (const bid of bidArray) {\n const cacheUrl: string | undefined =\n bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml: string | undefined = bid.adm || undefined;\n\n const bidResponse: PrebidBidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency,\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n\n bids.push(bidResponse);\n }\n }\n\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n\n async function initialize(): Promise<void> {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n\n async function requestBids(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n\n const timeout = DEFAULT_TIMEOUT_MS;\n\n log(\"Fetching auction response from:\", AUCTION_URL);\n\n const controller =\n typeof AbortController !== \"undefined\"\n ? new AbortController()\n : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2000);\n\n try {\n const fetchOptions: RequestInit = {\n method: \"POST\",\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n\n const data = await response.json();\n\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency}` +\n ` ${b.width}x${b.height}` +\n (b.vastUrl ? \" [cached VAST]\" : \"\") +\n (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n\n return bids;\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2000}ms`);\n return [];\n }\n\n throw error;\n }\n }\n\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n\n async function requestBidsUntilResponse(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError: unknown;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n\n function destroy(): void {\n initialized = false;\n log(\"Destroyed\");\n }\n\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n },\n };\n}\n","export interface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nexport interface 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\nexport interface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport type MediaFileFilter = \"hls-only\" | \"mp4-first\" | \"all\";\n\nfunction isHlsType(type: string): boolean {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\n\nfunction isMp4Type(type: string): boolean {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\n\nexport function parseVastXml(\n xmlString: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): VastAd | null {\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 `${logPrefix} XML parsing error (malformed VAST XML):`,\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(`${logPrefix} No Ad element found in VAST XML`);\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\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 Math.round(parseFloat(durationParts[2] || \"0\"));\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible media files found in VAST XML`);\n }\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\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 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 const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\n\nexport async function fetchAndParseVastAd(\n vastTagUrl: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): Promise<VastAd | null> {\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\n const vastXml = await response.text();\n console.log(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml, filter, logPrefix);\n}\n\nexport function createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n}\n\nexport function fireTrackingPixels(\n urls: string[],\n sessionId?: string,\n logPrefix = \"[VastParser]\"\n): 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 const img = new Image(1, 1);\n img.onerror = () => {\n // 502 or other network errors are fire-and-forget; do not affect playback\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n","import type { PrebidBidResponse } from \"../types\";\nimport type { VastAd, VastMediaFile } from \"./vastParser\";\nimport {\n parseVastXml,\n fetchAndParseVastAd,\n fireTrackingPixels as fireTrackingPixelsShared,\n createEmptyTrackingState,\n} from \"./vastParser\";\nimport Hls from \"hls.js\";\n\nconst LOG = \"[PrebidAdLayer]\";\n\nexport interface PrebidAdLayerOptions {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls;\n debug?: boolean;\n}\n\nexport interface PrebidAdLayerOptionsUpdate {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls | null;\n}\n\nexport interface PrebidAdLayer {\n initialize: () => void;\n updateOptions: (opts: PrebidAdLayerOptionsUpdate) => void;\n playAd: (bids: PrebidBidResponse[]) => Promise<void>;\n pause: () => void;\n resume: () => void;\n stop: () => Promise<void>;\n destroy: () => void;\n isAdPlaying: () => boolean;\n resize: (width: number, height: number) => void;\n on: (event: string, listener: (payload?: any) => void) => void;\n off: (event: string, listener: (payload?: any) => void) => void;\n updateOriginalMutedState: (muted: boolean, volume?: number) => void;\n getOriginalMutedState: () => boolean;\n getOriginalVolume: () => number;\n setAdVolume: (volume: number) => void;\n getAdVolume: () => number;\n showPlaceholder: () => void;\n hidePlaceholder: () => void;\n}\n\nfunction resolveBidToVastAd(winner: PrebidBidResponse, logPrefix: string): Promise<VastAd | null> {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\n\nexport function createPrebidAdLayer(\n contentVideo: HTMLVideoElement,\n options?: PrebidAdLayerOptions\n): PrebidAdLayer {\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 let mainHlsInstance: Hls | undefined = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\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 let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\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 fireTrackingPixelsShared(urls, sessionId, LOG);\n }\n\n function getMainStreamQuality(): { width: number; height: number; bitrate: number } | null {\n if (!mainHlsInstance?.levels) return null;\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 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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0]!;\n if (mediaFiles.length === 1) return firstFile;\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\n }\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 const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n return { file, score };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n\n function isHlsMediaFile(file: VastMediaFile): boolean {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 video.volume = 1.0;\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels(currentAd.trackingUrls.error);\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) 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 && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && 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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n function teardownCurrentPlayback(): void {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n\n function startNativePlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n\n function startHlsPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n adHls = new Hls({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n adVideoElement!.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n\n function startPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n\n async function playAd(bids: PrebidBidResponse[]): Promise<void> {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n\n const winner = bids[0]!;\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n\n updateOptions(opts: PrebidAdLayerOptionsUpdate) {\n if (opts.continueLiveStreamDuringAds !== undefined) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== undefined) {\n mainHlsInstance = opts.mainHlsInstance ?? undefined;\n }\n },\n\n playAd,\n\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {});\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = undefined;\n tornDown = false;\n },\n\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\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\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 originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\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\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 };\n}\n","import type {\n ClientInfo,\n TrackingData,\n HeartbeatData,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\n} from \"../types\";\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\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n\n const fingerprintString = JSON.stringify(clientInfo);\n\n if (typeof crypto !== \"undefined\" && crypto.subtle && 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(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\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 const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.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 cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\n\nconst TRACK_URL =\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\n\nasync function sendTrackRequest(\n licenseKey: string | undefined,\n body: Record<string, unknown>\n): Promise<void> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\n\nexport async function sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\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","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 supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\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 supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\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 if (webOSVersion !== undefined && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (webOSVersion !== undefined && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\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 if (tizenVersion !== undefined && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (tizenVersion !== undefined && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\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 supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\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 const imaSupport = supportsGoogleIMA();\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 supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\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 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 supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\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\n"]}
1
+ {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/ui/StormcloudVideoPlayer.cjs","../../src/ui/StormcloudVideoPlayer.tsx","../../src/player/StormcloudVideoPlayer.ts","../../src/sdk/prebid.ts","../../src/sdk/vastParser.ts","../../src/sdk/prebidAdLayer.ts","../../src/utils/tracking.ts","../../src/utils/polyfills.ts","../../src/utils/browserCompat.ts"],"names":["__create","Object","create","__defProp","__copyProps","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","to","from","except","desc","call","key","__toESM","mod","isNodeMode","value","__toCommonJS","StormcloudVideoPlayer_exports","StormcloudVideoPlayerComponent","module","exports","import_react","require","import_hls","DEFAULT_TIMEOUT_MS","AUCTION_URL","createPrebidManager","options","initialized","debug","log","args","console","warn","parseResponse","data","bids","seatbids","seatbid","currency","cur","seat","bidArray","bid","cacheUrl","ext","prebid","cache","vastXml","url","adm","bidResponse","bidder","cpm","price","width","w","height","h","adId","id","impId","impid","creativeId","crid","vastUrl","adomain","push","sort","a","b","initialize","requestBids","timeout","controller","timeoutId","fetchOptions","response","body","error","Error","AbortController","setTimeout","abort","method","signal","fetch","clearTimeout","ok","text","catch","status","slice","json","responsetimemillis","errors","length","toFixed","REQUEST_BIDS_MAX_RETRIES","REQUEST_BIDS_BACKOFF_MS","requestBidsUntilResponse","lastError","attempt","err","delay","Promise","resolve","destroy","isInitialized","isHlsType","type","includes","isMp4Type","parseVastXml","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","textContent","adElement","getAttribute","title","isNoAdAvailable","toLowerCase","durationText","durationParts","split","duration","parseInt","Math","round","parseFloat","mediaFileElements","querySelectorAll","mediaFiles","forEach","mf","index","trim","substring","isHls","isMp4","accepted","bitrateAttr","bitrateValue","bitrate","aIsMp4","bIsMp4","trackingUrls","impression","start","firstQuartile","midpoint","thirdQuartile","complete","mute","unmute","pause","resume","fullscreen","exitFullscreen","skip","eventKey","el","event","clickThrough","vastTagUrl","mode","credentials","headers","Accept","referrerPolicy","statusText","createEmptyTrackingState","fireTrackingPixels","urls","sessionId","trackingUrl","img","Image","onerror","src","LOG","resolveBidToVastAd","winner","ad","fetchAndParseVastAd","createPrebidAdLayer","contentVideo","adPlaying","originalMutedState","originalVolume","max","min","volume","listeners","Map","mainHlsInstance","continueLiveStreamDuringAds","adVideoElement","adHls","adContainerEl","currentAd","destroyed","tornDown","trackingFired","emit","payload","set","Array","fn","generateSessionId","Date","now","random","toString","substr","getMainStreamQuality","levels","currentLevel","autoLevel","loadLevel","level","firstFile","widthDiff","scoredFiles","isHlsMediaFile","selectBestMediaFile","mainQuality","map","file","abs","heightDiff","resolutionDiff","fileBitrate","bitrateDiff","score","createAdVideoElement","video","document","createElement","style","position","left","top","objectFit","backgroundColor","playsInline","setupAdEventListeners","muted","addEventListener","progress","currentTime","handleAdComplete","e","ended","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","display","pointerEvents","visibility","opacity","play","teardownCurrentPlayback","removeAttribute","load","mediaFile","startHlsPlayback","Hls","isSupported","enableWorker","lowLatencyMode","loadSource","attachMedia","on","Events","MANIFEST_PARSED","handleAdError","ERROR","_event","fatal","canPlayType","startPlayback","startNativePlayback","playAd","container","contentVolume","adVolume","reject","right","bottom","alignItems","zIndex","parentElement","appendChild","updateOptions","opts","paused","stop","remove","removeChild","clear","isAdPlaying","resize","listener","has","Set","add","off","delete","updateOriginalMutedState","nextVolume","Number","isNaN","getOriginalMutedState","getOriginalVolume","setAdVolume","getAdVolume","showPlaceholder","justifyContent","hidePlaceholder","cachedBrowserId","getClientInfo","screen","window","navigator","ua","userAgent","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","screenInfo","availWidth","availHeight","orientation","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","test","androidModelMatch","outerHeight","outerWidth","matchMedia","matches","standalone","angle","domain","location","hostname","origin","path","pathname","language","languages","join","cookieEnabled","doNotTrack","referrer","visibilityState","getBrowserID","clientInfo","fingerprintString","encodedData","utf8","buffer","i","hashBuffer","hashArray","hashHex","hash","char","fallbackHash","timestamp","JSON","stringify","crypto","subtle","digest","Uint8Array","TextEncoder","encode","unescape","encodeURIComponent","charCodeAt","padStart","padEnd","sendTrackRequest","licenseKey","TRACK_URL","sendInitialTracking","browserId","trackingData","adDetectInfo","sendAdLoadedTracking","adLoadedInfo","sendAdImpressionTracking","adImpressionInfo","sendHeartbeat","heartbeatData","toISOString","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","replace","values","String","getAll","callback","parts","polyfillTextEncoder","TextEncoderPolyfill","encoding","charcode","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","items","arrayLike","len","result","mapFn","thisArg","polyfillStringStartsWith","search","pos","polyfillStringEndsWith","endsWith","polyfillStringIncludes","indexOf","initializePolyfills","webOSVersion","getChromeVersion","getWebKitVersion","getPlatform","userAgentData","version","detectBrowser","majorVersion","supportsIMA","supportsModernJS","recommendedAdPlayer","tizenVersion","chromeVersionNum","chromeVersion","webkitVersion","isLegacyTV","supportsGoogleIMA","browser","logBrowserInfo","imaSupport","getBrowserConfigOverrides","overrides","allowNativeHls","StormcloudVideoPlayer","config","pendingNextAdBids","continuousFetchLoopPromise","attached","inAdBreak","ptsDriftEmaMs","adPodQueue","lastHeartbeatTime","currentAdIndex","totalAdsInBreak","showAds","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","activeAdRequestToken","adRequestWatchdogToken","adFailsafeToken","continuousFetchingActive","maxPlaceholderDurationMs","isShowingPlaceholder","totalAdRequestsInBreak","maxTotalAdRequestsPerBreak","pendingAdBreak","savedMutedStateBeforeScte","consecutiveFailures","maxConsecutiveFailures","lastAdRequestTime","minAdRequestIntervalMs","backoffBaseMs","maxBackoffMs","adTransitionGapMs","browserOverrides","videoElement","debugAdTiming","prebidManager","adLayer","adRequest","attach","shouldUseNativeHls","isLive","adBehavior","autoplay","hls","import_hls2","backBufferLength","liveDurationInfinity","maxBufferLength","maxLiveSyncPlaybackRate","liveSyncDuration","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeOffset","nudgeMaxRetry","startPosition","MEDIA_ATTACHED","_","minSegments","some","details","live","shouldContinueLiveStreamDuringAds","LEVEL_LOADED","_evt","fragments","fragmentsToScan","isArray","tagList","entry","tag","minSegmentsBeforePlay","idx","attrs","parseAttributeList","hasScteOut","durationSeconds","parseCueOutDuration","marker","raw","earlyDetection","startAdPrefetch","frag","sn","FRAG_BUFFERED","FRAG_PARSING_METADATA","id3Tags","samples","s","ptsSeconds","pts","onId3Tag","FRAG_CHANGED","prog","elapsed","onScte35Marker","hasScteIn","klass","toNumber","ErrorTypes","NETWORK_ERROR","startLoad","MEDIA_ERROR","recoverMediaError","getAdSource","attachAdLayerEventListeners","source","adIndex","errorPayload","errorMessage","errorCode","code","vastErrorCode","message","cause","innerError","causeMessage","handleAdFailure","clearAdFailsafeTimer","clearAdRequestWatchdog","expectedAdBreakDurationMs","adStopTimerId","scheduleAdStopCountdown","getRemainingAdMs","hidePlaceholderLayer","remaining","restoredMuted","restoredVolume","showPlaceholderLayer","handleAdPodComplete","ensurePlaceholderContainer","placeholderContainer","transition","wasHidden","offsetHeight","requestAnimationFrame","timeUpdateHandler","onTimeUpdate","emptiedHandler","wasPaused","streamType","getStreamType","canNative","updatePtsDrift","parseScte35FromId3","decodeId3ValueToText","cueOutMatch","arg","dur","id3","cueOutContMatch","cont","parseCueOutCont","cueInMatch","daterangeMatch","bin","parseScte35Binary","decoder","TextDecoder","out","fromCharCode","hasPendingAdBreak","durationMs","currentAdBreakStartWallClockMs","detectedAtFragmentSn","sendAdDetectTracking","isManifestMarker","isManifestBasedMarker","forceImmediate","immediateManifestAds","hasPts","clearAdStartTimer","handleAdStart","tol","driftToleranceMs","nowMs","estCurrentPtsMs","deltaMs","floor","markerPtsMs","tolerance","scheduleAdStartIn","elapsedMs","remainingMs","hasQueuedAds","activeAdRequest","clearAdStopTimer","num","dStr","d","res","elapsedMatch","durationMatch","slashMatch","regex","exec","rawVal","val","n","splice_command_type","BitReader","buf","bytePos","bitPos","numBits","readBits","remainingInByte","toRead","currentByte","shift","mask","bits","skipBits","r","tableId","sectionLength","ptsAdjHigh","ptsAdjLow","spliceCommandLength","spliceCommandType","cancel","outOfNetwork","programSpliceFlag","durationFlag","spliceImmediateFlag","timeSpecifiedFlag","componentCount","high","low","durationTicks","initializeTracking","heartbeatInterval","setInterval","sendHeartbeatIfNeeded","getCurrentAdIndex","getTotalAdsInBreak","isShowingAds","startContinuousFetchLoop","runContinuousFetchLoop","backoffMs","mult","pow","_marker","adBreakDurationMs","state","clearPendingAdBreak","showPlaceholderAndWaitForAds","stopContinuousFetching","tryNextAvailableAdWithRateLimit","backoffMultiplier","backoffDelay","effectiveMinInterval","timeSinceLastRequest","waitTime","tryNextAvailableAd","_retryCount","checkInterval","maxChecks","_currentTimeSec","ms","ensureAdStoppedByTimer","adBreakCheckIntervalMs","maxAdBreakExtensionMs","maxExtensionMsConfig","expectedDurationMs","shouldExtendAdBreak","pendingAds","overrunMs","maxExtensionMs","delayMs","adStartTimerId","ptsSecondsSample","sampleMs","alpha","isTizen","startAdRequestWatchdog","token","adFailsafeTimeoutMs","adRequestWatchdogId","logAdState","timeoutMs","startAdFailsafeTimer","failsafeMs","adFailsafeTimerId","videoPaused","imaAdPlaying","extra","MAX_SAFE_INTEGER","toggleMute","currentPerceptualState","isMuted","newMutedState","toggleFullscreen","fullscreenElement","requestFullscreen","setMuted","setVolume","clampedVolume","getVolume","isFullscreen","clientWidth","clientHeight","removeEventListener","clearInterval","import_fa","import_jsx_runtime","CRITICAL_PROPS","React","memo","props"],"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/player/StormcloudVideoPlayer.ts\nvar import_hls2 = __toESM(require(\"hls.js\"), 1);\n\n// src/sdk/prebid.ts\nvar DEFAULT_TIMEOUT_MS = 3e3;\nvar AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\nfunction createPrebidManager(options = {}) {\n let initialized = false;\n const debug = options.debug ?? false;\n function log(...args) {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n function warn(...args) {\n console.warn(\"[Prebid]\", ...args);\n }\n function parseResponse(data) {\n const bids = [];\n const seatbids = data?.seatbid || [];\n const currency = data?.cur || \"USD\";\n for (const seatbid of seatbids) {\n const seat = seatbid.seat || \"unknown\";\n const bidArray = seatbid.bid || [];\n for (const bid of bidArray) {\n const cacheUrl = bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml = bid.adm || void 0;\n const bidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n bids.push(bidResponse);\n }\n }\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n async function initialize() {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n async function requestBids() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n const timeout = DEFAULT_TIMEOUT_MS;\n log(\"Fetching auction response from:\", AUCTION_URL);\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2e3);\n try {\n const fetchOptions = {\n method: \"POST\"\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n const data = await response.json();\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency} ${b.width}x${b.height}` + (b.vastUrl ? \" [cached VAST]\" : \"\") + (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n return bids;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2e3}ms`);\n return [];\n }\n throw error;\n }\n }\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n async function requestBidsUntilResponse() {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n function destroy() {\n initialized = false;\n log(\"Destroyed\");\n }\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n }\n };\n}\n\n// src/sdk/vastParser.ts\nfunction isHlsType(type) {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\nfunction isMp4Type(type) {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\nfunction parseVastXml(xmlString, filter = \"all\", logPrefix = \"[VastParser]\") {\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 `${logPrefix} XML parsing error (malformed VAST XML):`,\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(`${logPrefix} No Ad element found in VAST XML`);\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\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 + Math.round(parseFloat(durationParts[2] || \"0\"));\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0\n });\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible media files found in VAST XML`);\n }\n return null;\n }\n const trackingUrls = {\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 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 const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\nasync function fetchAndParseVastAd(vastTagUrl, filter = \"all\", logPrefix = \"[VastParser]\") {\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 const vastXml = await response.text();\n console.log(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml, filter, logPrefix);\n}\nfunction createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n}\nfunction fireTrackingPixels(urls, sessionId, logPrefix = \"[VastParser]\") {\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 const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n\n// src/sdk/prebidAdLayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\nvar LOG = \"[PrebidAdLayer]\";\nfunction resolveBidToVastAd(winner, logPrefix) {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\nfunction createPrebidAdLayer(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 let mainHlsInstance = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\n let adVideoElement;\n let adHls;\n let adContainerEl;\n let currentAd;\n let sessionId;\n let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\n }\n }\n }\n function generateSessionId() {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n function fireTrackingPixels2(urls) {\n fireTrackingPixels(urls, sessionId, LOG);\n }\n function getMainStreamQuality() {\n if (!mainHlsInstance?.levels) return null;\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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0];\n if (mediaFiles.length === 1) return firstFile;\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\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 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 };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n function isHlsMediaFile(file) {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 return video;\n }\n function setupAdEventListeners() {\n if (!adVideoElement) return;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels2(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels2(ad.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels2(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels2(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);\n handleAdError();\n });\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) return;\n if (adVideoElement.muted) {\n fireTrackingPixels2(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels2(currentAd.trackingUrls.unmute);\n }\n });\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && adVideoElement && !adVideoElement.ended) {\n fireTrackingPixels2(currentAd.trackingUrls.pause);\n }\n });\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {\n fireTrackingPixels2(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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n function handleAdError() {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n function teardownCurrentPlayback() {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n function startNativePlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n function startHlsPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n if (import_hls.default.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = void 0;\n }\n adHls = new import_hls.default({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n adHls.on(import_hls.default.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n function startPlayback(mediaFile) {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n async function playAd(bids) {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n const winner = bids[0];\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels2(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n updateOptions(opts) {\n if (opts.continueLiveStreamDuringAds !== void 0) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== void 0) {\n mainHlsInstance = opts.mainHlsInstance ?? void 0;\n }\n },\n playAd,\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {\n });\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {\n });\n }\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = void 0;\n tornDown = false;\n },\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"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 },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, 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 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 adVideoElement.volume = Math.max(0, Math.min(1, volume));\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 };\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 getBrowserID(clientInfo) {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n const fingerprintString = JSON.stringify(clientInfo);\n if (typeof crypto !== \"undefined\" && crypto.subtle && 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(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\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 const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.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 cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\nvar TRACK_URL = \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\nasync function sendTrackRequest(licenseKey, body) {\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\nasync function sendInitialTracking(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = {\n browserId,\n ...clientInfo\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData)\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n error\n );\n }\n}\nasync function sendAdDetectTracking(licenseKey, adDetectInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n error\n );\n }\n}\nasync function sendAdLoadedTracking(licenseKey, adLoadedInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n error\n );\n }\n}\nasync function sendAdImpressionTracking(licenseKey, adImpressionInfo) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\nasync function sendHeartbeat(licenseKey) {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const heartbeatData = {\n browserId,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n };\n const headers = {\n \"Content-Type\": \"application/json\"\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData)\n }\n );\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\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/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 supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer = \"ima\";\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 if (webOSVersion !== void 0 && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (webOSVersion !== void 0 && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\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 if (tizenVersion !== void 0 && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (tizenVersion !== void 0 && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = \"ima\";\n } else {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\n }\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = \"hls\";\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 supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum\n };\n}\nfunction supportsGoogleIMA() {\n const browser = detectBrowser();\n if (browser.isLegacyTV) {\n return false;\n }\n if (typeof document === \"undefined\" || typeof document.createElement !== \"function\") {\n return false;\n }\n try {\n const video = document.createElement(\"video\");\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n if (typeof Promise === \"undefined\") {\n return false;\n }\n return browser.supportsIMA;\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n const imaSupport = supportsGoogleIMA();\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 supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\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}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.pendingNextAdBids = null;\n this.continuousFetchLoopPromise = null;\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.adPodQueue = [];\n this.lastHeartbeatTime = 0;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.showAds = false;\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.activeAdRequestToken = null;\n this.adRequestWatchdogToken = null;\n this.adFailsafeToken = null;\n this.continuousFetchingActive = false;\n this.maxPlaceholderDurationMs = 5e3;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n this.maxTotalAdRequestsPerBreak = 20;\n this.pendingAdBreak = null;\n this.savedMutedStateBeforeScte = null;\n this.consecutiveFailures = 0;\n this.maxConsecutiveFailures = 5;\n this.lastAdRequestTime = 0;\n this.minAdRequestIntervalMs = 2500;\n this.backoffBaseMs = 1e3;\n this.maxBackoffMs = 15e3;\n this.adTransitionGapMs = 1500;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n this.prebidManager = createPrebidManager(\n config.debugAdTiming !== void 0 ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming\n });\n }\n async adRequest() {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n this.initializeTracking();\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\"\n }\n );\n }\n this.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\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 if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n if (this.config.debugAdTiming) {\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: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior\n });\n }\n this.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null\n });\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\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.inAdBreak || this.pendingAdBreak) {\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\") ? this.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 = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value, earlyDetection: true }\n };\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3AF} EARLY SCTE-35 DETECTION: Ad break marker found in fragment\", i, \"- starting pre-fetch (NOT playing yet)\");\n }\n this.startAdPrefetch(marker, frag?.sn);\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\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 = this.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.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n };\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.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 = this.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.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\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.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n getAdSource() {\n return \"prebid\";\n }\n attachAdLayerEventListeners() {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {\n });\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 0 : this.adLayer.getOriginalVolume()\n );\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n if (!this.inAdBreak) {\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) this.video.muted = restoredMuted;\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) this.video.volume = restoredVolume;\n return;\n }\n this.consecutiveFailures = 0;\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n setTimeout(() => {\n if (!this.inAdBreak || bids.length === 0) return;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, this.adTransitionGapMs);\n return;\n }\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: remaining time low and duration known, ending ad pod\");\n }\n this.handleAdPodComplete();\n } else {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n }\n });\n }\n ensurePlaceholderContainer() {\n if (this.placeholderContainer) {\n return;\n }\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 = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n showPlaceholderLayer() {\n this.ensurePlaceholderContainer();\n if (!this.placeholderContainer) {\n return;\n }\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer\");\n }\n }\n hidePlaceholderLayer() {\n if (!this.placeholderContainer) {\n return;\n }\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\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.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.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 shouldUseNativeHls() {\n const streamType = this.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 onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.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 = this.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 = this.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 = this.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 = this.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 = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n return void 0;\n }\n 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 }\n onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\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.pendingAdBreak\n });\n }\n if (marker.type === \"start\") {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : this.pendingAdBreak?.marker.durationSeconds != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...marker.durationSeconds != null && { durationSeconds: marker.durationSeconds },\n ...marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds },\n ...this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn\n }\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\"\n });\n }\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\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.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);\n if (this.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null\n });\n }\n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\n }\n return;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n if (adPlaying) {\n this.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n return;\n }\n }\n 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 }\n 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 }\n 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 }\n 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 }\n 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 }\n parseScte35Binary(data) {\n class BitReader {\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 }\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 r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return void 0;\n }\n 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 if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\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 timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds = void 0;\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 if (outOfNetwork) {\n const marker = {\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { splice_command_type: 5 }\n };\n return marker;\n }\n return void 0;\n }\n initializeTracking() {\n sendInitialTracking(this.config.licenseKey).then(() => {\n this.heartbeatInterval = window.setInterval(() => {\n this.sendHeartbeatIfNeeded();\n }, 5e3);\n }).catch((error) => {\n if (this.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n getCurrentAdIndex() {\n return this.currentAdIndex;\n }\n getTotalAdsInBreak() {\n return this.totalAdsInBreak;\n }\n isAdPlaying() {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n isShowingAds() {\n return this.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 shouldContinueLiveStreamDuringAds() {\n if (this.config.allowNativeHls) {\n return false;\n }\n if (!this.isLiveStream) {\n return false;\n }\n return true;\n }\n startAdPrefetch(marker, fragmentSn) {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n this.pendingAdBreak = {\n marker,\n ...fragmentSn !== void 0 ? { detectedAtFragmentSn: fragmentSn } : {},\n isFetching: false,\n fetchStartTime: Date.now()\n };\n void this.adRequest().then(() => {\n }).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\n }\n clearPendingAdBreak() {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = void 0;\n }\n this.pendingAdBreak = null;\n }\n startContinuousFetchLoop() {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n async runContinuousFetchLoop() {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing)\");\n }\n } else {\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 0 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n async handleAdStart(_marker) {\n const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : void 0;\n if (this.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] \\u{1F4FA} ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\n this.savedMutedStateBeforeScte = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n this.showAds = true;\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n this.clearPendingAdBreak();\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u2705 First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 0 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] \\u26A0\\uFE0F First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n this.startContinuousFetchLoop();\n }\n stopContinuousFetching() {\n this.continuousFetchingActive = false;\n this.hidePlaceholderLayer();\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Stopping continuous ad fetching\");\n }\n }\n async tryNextAvailableAdWithRateLimit() {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u23F3 Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n return this.tryNextAvailableAd(0);\n }\n async tryNextAvailableAd(_retryCount = 0) {\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max ad requests per break (${this.maxTotalAdRequestsPerBreak}) reached`);\n }\n this.handleAdPodComplete();\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F9\\uFE0F No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 0 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n await this.showPlaceholderAndWaitForAds();\n }\n }\n async showPlaceholderAndWaitForAds() {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n if (waitTime < 1e3) {\n this.handleAdPodComplete();\n return;\n }\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u2B1B Showing placeholder for ${waitTime}ms while waiting for ad response`);\n }\n this.isShowingPlaceholder = true;\n this.adLayer.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.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u{1F6D1} Too many failures during placeholder wait\");\n }\n break;\n }\n if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n return;\n }\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] \\u23F0 Placeholder timeout, ending ad break\");\n }\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n onTimeUpdate(_currentTimeSec) {\n if (this.adLayer.isAdPlaying()) return;\n }\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 if (!this.inAdBreak) return;\n this.adStopTimerId = void 0;\n const adPlaying = this.adLayer.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\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 : 6e4;\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n if (adPlaying) {\n this.adLayer.stop().catch(() => {\n });\n }\n this.handleAdPodComplete();\n }\n scheduleAdStartIn(delayMs) {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" }).catch(() => {\n });\n }, ms);\n }\n clearAdStartTimer() {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = void 0;\n }\n }\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 handleAdPodComplete() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] \\u{1F3C1} Ad pod complete - cleaning up\");\n }\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.currentAdBreakStartWallClockMs = void 0;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n this.adLayer.stop().catch(() => {\n });\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n const isTizen = detectBrowser().tizenVersion !== void 0;\n if (isTizen && this.hls) {\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Tizen: re-attached HLS to video element after ad break to restore audio\");\n }\n }\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {\n });\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n if (isTizen && !restoredMuted) {\n requestAnimationFrame(() => {\n this.video.muted = false;\n this.video.volume = restoredVolume;\n });\n }\n }\n handleAdFailure() {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\n );\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] \\u{1F6D1} Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n }\n }\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.handleAdFailure();\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 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 imaAdPlaying: this.adLayer.isAdPlaying()\n });\n this.handleAdFailure();\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 = {}) {\n if (!this.config.debugAdTiming) {\n return;\n }\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n showAds: this.showAds,\n adPlaying: this.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra\n });\n }\n getRemainingAdMs() {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n toggleMute() {\n if (this.adLayer.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n this.adLayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adLayer.setAdVolume(newMutedState ? 0 : this.adLayer.getOriginalVolume());\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document.exitFullscreen().then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n }).catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n isMuted() {\n if (this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n setMuted(muted) {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n this.video.muted = muted;\n if (adPlaying) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n this.adLayer.setAdVolume(muted ? 0 : this.adLayer.getOriginalVolume());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted\n });\n }\n return;\n }\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n getVolume() {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.getAdVolume();\n }\n return this.video.volume;\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n if (this.adLayer && this.adLayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n this.adLayer.resize(width, height);\n }\n }\n destroy() {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = void 0;\n }\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = void 0;\n }\n this.hls?.destroy();\n this.adLayer?.destroy();\n this.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 \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\"\n];\nvar StormcloudVideoPlayerComponent = import_react.default.memo(\n (props) => {\n const {\n src,\n autoplay,\n muted,\n lowLatencyMode,\n allowNativeHls,\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 minSegmentsBeforePlay,\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 [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0 });\n const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);\n const [isMuted, setIsMuted] = import_react.default.useState(false);\n const [isFullscreen, 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, setVolume] = 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 [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 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 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 };\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 };\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 shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);\n const criticalPropsKey = (0, import_react.useMemo)(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs\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 (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 (minSegmentsBeforePlay !== void 0)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\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 setAdStatus((prev) => {\n if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds };\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 setVolume(\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 === videoRef.current?.parentElement\n );\n };\n const interval = setInterval(updateStates, 200);\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\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 if (videoRef.current) {\n const video2 = videoRef.current;\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 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\"style\", { children: `\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper: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 \n .stormcloud-video-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 \n *:fullscreen {\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 }\n ` }),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n className: `stormcloud-video-wrapper ${wrapperClassName || \"\"}`,\n style: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n position: isFullscreen ? \"fixed\" : \"relative\",\n top: isFullscreen ? 0 : void 0,\n left: isFullscreen ? 0 : void 0,\n overflow: \"hidden\",\n width: isFullscreen ? \"100vw\" : \"100%\",\n height: isFullscreen ? \"100vh\" : \"auto\",\n minHeight: isFullscreen ? \"100vh\" : \"auto\",\n maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : void 0,\n backgroundColor: isFullscreen ? \"#000\" : void 0,\n borderRadius: isFullscreen ? 0 : void 0,\n boxShadow: isFullscreen ? \"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: isFullscreen ? \"100%\" : \"auto\",\n maxWidth: \"100%\",\n maxHeight: isFullscreen ? \"100%\" : \"none\",\n objectFit: isFullscreen ? \"cover\" : \"contain\",\n backgroundColor: \"#000\",\n aspectRatio: isFullscreen ? \"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.jsx)(\n import_fa.FaSpinner,\n {\n className: \"stormcloud-loading-indicator\",\n size: 42,\n color: \"white\",\n style: {\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\"\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: \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow: \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\"\n },\n children: \"License Key Required\"\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\"\n },\n 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 }\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: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\"\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n },\n title: \"Play\",\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPlay,\n {\n size: 36,\n color: \"white\",\n style: {\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\"\n }\n }\n )\n }\n ),\n shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background: \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n width: \"100%\",\n height: \"8px\",\n background: \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\"\n },\n onClick: handleTimelineSeek,\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n height: \"100%\",\n background: \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${duration > 0 ? currentTime / duration * 100 : 0}%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n top: \"-6px\",\n right: `${duration > 0 ? 100 - currentTime / duration * 100 : 100}%`,\n width: \"20px\",\n height: \"20px\",\n background: \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow: \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\"\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 flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\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: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: handlePlayPause,\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow = \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow = \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n },\n title: isPlaying ? \"Pause\" : \"Play\",\n children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPause,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaPlay,\n {\n size: Math.max(16, 20 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 0 0 transparent)\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor = \"rgba(59, 130, 246, 0.4)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.15)\";\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n },\n onMouseLeave: (e) => {\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow: \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\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: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\"\n },\n children: [\n formatTime(currentTime),\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: `${12 * responsiveScale}px`\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\"\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n onClick: () => setShowSpeedMenu(!showSpeedMenu),\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${14 * responsiveScale}px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\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: \"12px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow: \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\"\n },\n children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"button\",\n {\n onClick: () => handlePlaybackRateChange(speed),\n style: {\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background: playbackRate === speed ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\" : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom: speed !== 2 ? \"1px solid rgba(255, 255, 255, 0.05)\" : \"none\"\n },\n onMouseEnter: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n },\n onMouseLeave: (e) => {\n if (playbackRate !== speed) {\n e.target.style.background = \"transparent\";\n }\n },\n children: [\n speed,\n \"x\"\n ]\n },\n speed\n )\n )\n }\n )\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${2 * responsiveScale}px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`\n },\n onMouseEnter: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n },\n onMouseLeave: (e) => {\n const target = e.target;\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow = \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: { filter: \"drop-shadow(0 0 0 transparent)\" }\n }\n )\n }\n )\n ]\n }\n )\n ]\n }\n )\n ]\n }\n ) }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\"\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false),\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isMuted ? \"Unmute\" : \"Mute\",\n children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeMute,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeDown,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaVolumeUp,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n )\n }\n ),\n showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9\n },\n onMouseEnter: () => setShowVolumeSlider(true),\n onMouseLeave: () => setShowVolumeSlider(false)\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow: \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition: \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\"\n },\n onMouseEnter: (e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow = \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor = \"rgba(96, 165, 250, 0.8)\";\n },\n onMouseLeave: (e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow = \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor = \"rgba(255, 255, 255, 0.7)\";\n },\n children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(\n \"div\",\n {\n style: {\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\"\n },\n onMouseDown: (e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n const handleMouseMove = (moveEvent) => {\n if (!sliderElement) return;\n const rect2 = sliderElement.getBoundingClientRect();\n const y2 = moveEvent.clientY - rect2.top;\n const percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));\n handleVolumeChange(percentage2);\n };\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n const rect = sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n onClick: (e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage = 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n },\n children: [\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background: \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background: \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition: \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow: \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\"\n }\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"div\",\n {\n style: {\n position: \"absolute\",\n bottom: `calc(${(isMuted ? 0 : volume) * 100}% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background: \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow: \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition: \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\"\n },\n onMouseEnter: (e) => {\n e.currentTarget.style.boxShadow = \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n },\n onMouseLeave: (e) => {\n e.currentTarget.style.boxShadow = \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n },\n onMouseDown: (e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n },\n onMouseUp: (e) => {\n e.currentTarget.style.cursor = \"grab\";\n }\n }\n )\n ]\n }\n )\n }\n )\n ] })\n ]\n }\n ),\n /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n \"button\",\n {\n onClick: () => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n },\n onMouseEnter: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n },\n onMouseLeave: (e) => {\n const target = e.currentTarget;\n target.style.boxShadow = \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background = \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n },\n style: {\n background: \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow: \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`\n },\n title: isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\",\n children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaCompress,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\n ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(\n import_fa.FaExpand,\n {\n size: Math.max(14, 16 * responsiveScale),\n style: {\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\"\n }\n }\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 } 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 FaSpinner,\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 \"licenseKey\",\n \"lowLatencyMode\",\n \"driftToleranceMs\",\n] as const;\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 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 minSegmentsBeforePlay,\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 [adStatus, setAdStatus] = React.useState<{\n showAds: boolean;\n currentIndex: number;\n totalAds: number;\n }>({ showAds: false, currentIndex: 0, totalAds: 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 [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\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 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 };\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 };\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 shouldShowEnhancedControls =\n showCustomControls && (isHlsStream ? allowNativeHls : true);\n\n const criticalPropsKey = useMemo(() => {\n return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join(\"|\");\n }, [\n src,\n allowNativeHls,\n licenseKey,\n lowLatencyMode,\n driftToleranceMs,\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 (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 (minSegmentsBeforePlay !== undefined)\n cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;\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\n setAdStatus((prev) => {\n if (\n prev.showAds !== showAds ||\n prev.currentIndex !== currentIndex ||\n prev.totalAds !== totalAds\n ) {\n if (showAds && !prev.showAds) {\n setShowCenterPlay(false);\n }\n return { showAds, currentIndex, totalAds };\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 === videoRef.current?.parentElement\n );\n };\n\n const interval = setInterval(updateStates, 200);\n\n const handleFullscreenChange = () => {\n setIsFullscreen(\n document.fullscreenElement === videoRef.current?.parentElement\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 if (videoRef.current) {\n const video = videoRef.current;\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 return (\n <>\n <style>\n {`\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper: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 \n .stormcloud-video-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 \n *:fullscreen {\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 }\n `}\n </style>\n <div\n className={`stormcloud-video-wrapper ${wrapperClassName || \"\"}`}\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 maxWidth: isFullscreen ? \"100vw\" : \"100%\",\n maxHeight: isFullscreen ? \"100vh\" : \"none\",\n zIndex: isFullscreen ? 999999 : undefined,\n backgroundColor: isFullscreen ? \"#000\" : undefined,\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: isFullscreen ? \"100%\" : \"auto\",\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 <FaSpinner\n className=\"stormcloud-loading-indicator\"\n size={42}\n color=\"white\"\n style={{\n position: \"absolute\",\n top: \"calc(50% - 21px)\",\n left: \"calc(50% - 21px)\",\n zIndex: 20,\n animation: \"spin 1s linear infinite\",\n filter: \"drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))\",\n }}\n />\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:\n \"linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)\",\n color: \"white\",\n padding: \"24px 32px\",\n borderRadius: \"16px\",\n backdropFilter: \"blur(20px)\",\n border: \"2px solid rgba(255, 255, 255, 0.2)\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)\",\n textAlign: \"center\",\n maxWidth: \"400px\",\n margin: \"0 16px\",\n }}\n >\n <div\n style={{\n fontSize: \"20px\",\n fontWeight: \"bold\",\n marginBottom: \"12px\",\n color: \"#ffffff\",\n textShadow: \"0 2px 4px rgba(0, 0, 0, 0.5)\",\n }}\n >\n License Key Required\n </div>\n <div\n style={{\n fontSize: \"14px\",\n lineHeight: \"1.5\",\n color: \"rgba(255, 255, 255, 0.9)\",\n textShadow: \"0 1px 2px rgba(0, 0, 0, 0.3)\",\n }}\n >\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 {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:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\",\n borderRadius: \"50%\",\n width: \"100px\",\n height: \"100px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n border: \"3px solid rgba(255, 255, 255, 0.8)\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)\";\n target.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.9)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLElement;\n target.style.transform = \"translate(-50%, -50%)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)\";\n target.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)\";\n target.style.borderColor = \"rgba(255, 255, 255, 0.8)\";\n }}\n title=\"Play\"\n >\n <FaPlay\n size={36}\n color=\"white\"\n style={{\n marginLeft: \"6px\",\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n }}\n />\n </div>\n )}\n\n {shouldShowEnhancedControls && !showLicenseWarning ? (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n right: 0,\n background:\n \"linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)\",\n padding: \"20px 16px 16px\",\n zIndex: 10,\n }}\n >\n <div\n style={{\n width: \"100%\",\n height: \"8px\",\n background:\n \"linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)\",\n borderRadius: \"8px\",\n marginBottom: \"16px\",\n cursor: \"pointer\",\n position: \"relative\",\n backdropFilter: \"blur(5px)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"inset 0 2px 4px rgba(0, 0, 0, 0.2)\",\n }}\n onClick={handleTimelineSeek}\n >\n <div\n style={{\n height: \"100%\",\n background:\n \"linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)\",\n borderRadius: \"8px\",\n width: `${\n duration > 0 ? (currentTime / duration) * 100 : 0\n }%`,\n transition: \"width 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow: \"0 2px 8px rgba(139, 92, 246, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n top: \"-6px\",\n right: `${\n duration > 0\n ? 100 - (currentTime / duration) * 100\n : 100\n }%`,\n width: \"20px\",\n height: \"20px\",\n background:\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)\",\n borderRadius: \"50%\",\n border: \"3px solid rgba(139, 92, 246, 0.8)\",\n boxShadow:\n \"0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)\",\n transform: \"translateX(50%)\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n color: \"white\",\n flexWrap: viewportWidth < 768 ? \"wrap\" : \"nowrap\",\n gap: `${8 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n flexWrap: viewportWidth < 480 ? \"wrap\" : \"nowrap\",\n }}\n >\n <button\n onClick={handlePlayPause}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n backdropFilter: \"blur(12px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${10 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n minWidth: `${48 * responsiveScale}px`,\n minHeight: `${48 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n target.style.boxShadow =\n \"0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n target.style.boxShadow =\n \"0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n }}\n title={isPlaying ? \"Pause\" : \"Play\"}\n >\n {isPlaying ? (\n <FaPause\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaPlay\n size={Math.max(16, 20 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 0 0 transparent)\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(15px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"1px solid rgba(255, 255, 255, 0.15)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)\";\n e.currentTarget.style.borderColor =\n \"rgba(59, 130, 246, 0.4)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.15)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n // Hover effect removed\n }}\n onMouseLeave={(e) => {\n // Hover effect removed\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 -\n Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)\",\n borderRadius: \"4px\",\n boxShadow:\n \"inset 0 1px 3px rgba(0, 0, 0, 0.2)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 7px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"14px\",\n height: \"14px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n boxShadow:\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <div\n style={{\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n color: \"rgba(255, 255, 255, 0.9)\",\n display: viewportWidth < 480 ? \"none\" : \"block\",\n }}\n >\n {formatTime(currentTime)} / {formatTime(duration)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: `${12 * responsiveScale}px`,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: viewportWidth < 600 ? \"none\" : \"block\",\n }}\n >\n <button\n onClick={() => setShowSpeedMenu(!showSpeedMenu)}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px ${\n 14 * responsiveScale\n }px`,\n borderRadius: `${14 * responsiveScale}px`,\n fontSize: `${14 * responsiveScale}px`,\n fontFamily: \"monospace\",\n fontWeight: \"700\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${56 * responsiveScale}px`,\n minHeight: `${40 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\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: \"12px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)\",\n backdropFilter: \"blur(20px)\",\n borderRadius: \"12px\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n overflow: \"hidden\",\n minWidth: \"90px\",\n boxShadow:\n \"0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)\",\n }}\n >\n {[0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(\n (speed) => (\n <button\n key={speed}\n onClick={() =>\n handlePlaybackRateChange(speed)\n }\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"10px 16px\",\n background:\n playbackRate === speed\n ? \"linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)\"\n : \"transparent\",\n border: \"none\",\n color: \"white\",\n cursor: \"pointer\",\n fontSize: \"13px\",\n fontFamily: \"monospace\",\n fontWeight: \"600\",\n textAlign: \"center\",\n transition:\n \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n borderBottom:\n speed !== 2\n ? \"1px solid rgba(255, 255, 255, 0.05)\"\n : \"none\",\n }}\n onMouseEnter={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background =\n \"linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)\";\n }\n }}\n onMouseLeave={(e) => {\n if (playbackRate !== speed) {\n (\n e.target as HTMLElement\n ).style.background = \"transparent\";\n }\n }}\n >\n {speed}x\n </button>\n )\n )}\n </div>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current\n .toggleFullscreen()\n .catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\",\n backdropFilter: \"blur(10px)\",\n border: `${\n 2 * responsiveScale\n }px solid rgba(255, 255, 255, 0.3)`,\n color: \"#ffffff\",\n cursor: \"pointer\",\n padding: `${8 * responsiveScale}px`,\n borderRadius: `${16 * responsiveScale}px`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)\",\n boxShadow:\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\",\n minWidth: `${44 * responsiveScale}px`,\n minHeight: `${44 * responsiveScale}px`,\n }}\n onMouseEnter={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)\";\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)\";\n }}\n onMouseLeave={(e) => {\n const target = e.target as HTMLElement;\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)\";\n target.style.boxShadow =\n \"0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)\";\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{ filter: \"drop-shadow(0 0 0 transparent)\" }}\n />\n )}\n </button>\n </div>\n </div>\n </div>\n </>\n ) : (\n showCustomControls &&\n !showLicenseWarning && (\n <div\n style={{\n position: \"absolute\",\n bottom: `${10 * responsiveScale}px`,\n right: `${10 * responsiveScale}px`,\n transform: \"none\",\n display: \"flex\",\n flexDirection: isPortrait ? \"column\" : \"row\",\n gap: `${10 * responsiveScale}px`,\n zIndex: 10,\n }}\n >\n <div\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n padding: \"8px\",\n margin: \"-8px\",\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n >\n <button\n onClick={() => {\n if (playerRef.current) {\n playerRef.current.toggleMute();\n }\n if (onVolumeToggle) {\n onVolumeToggle();\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={isMuted ? \"Unmute\" : \"Mute\"}\n >\n {isMuted || volume === 0 ? (\n <FaVolumeMute\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : volume < 0.5 ? (\n <FaVolumeDown\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaVolumeUp\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n\n {showVolumeSlider && (\n <>\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"60px\",\n height: \"20px\",\n marginBottom: \"-16px\",\n zIndex: 9,\n }}\n onMouseEnter={() => setShowVolumeSlider(true)}\n onMouseLeave={() => setShowVolumeSlider(false)}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: \"4px\",\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)\",\n backdropFilter: \"blur(20px)\",\n padding: \"10px 14px\",\n borderRadius: \"14px\",\n border: \"2px solid rgba(255, 255, 255, 0.7)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"128px\",\n boxShadow:\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\",\n zIndex: 10,\n transition:\n \"transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out\",\n }}\n onMouseEnter={(e) => {\n setShowVolumeSlider(true);\n e.currentTarget.style.boxShadow =\n \"0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)\";\n e.currentTarget.style.borderColor =\n \"rgba(96, 165, 250, 0.8)\";\n }}\n onMouseLeave={(e) => {\n setShowVolumeSlider(false);\n e.currentTarget.style.boxShadow =\n \"0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)\";\n e.currentTarget.style.borderColor =\n \"rgba(255, 255, 255, 0.7)\";\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: \"8px\",\n height: \"104px\",\n cursor: \"pointer\",\n transition: \"transform 0.2s ease-in-out\",\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n const sliderElement = e.currentTarget;\n\n const handleMouseMove = (\n moveEvent: MouseEvent\n ) => {\n if (!sliderElement) return;\n const rect =\n sliderElement.getBoundingClientRect();\n const y = moveEvent.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n };\n\n const handleMouseUp = () => {\n document.removeEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleMouseUp\n );\n };\n\n document.addEventListener(\n \"mousemove\",\n handleMouseMove\n );\n document.addEventListener(\n \"mouseup\",\n handleMouseUp\n );\n\n const rect =\n sliderElement.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n onClick={(e) => {\n e.stopPropagation();\n const rect =\n e.currentTarget.getBoundingClientRect();\n const y = e.clientY - rect.top;\n const percentage =\n 1 - Math.max(0, Math.min(1, y / rect.height));\n handleVolumeChange(percentage);\n }}\n >\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n background:\n \"linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)\",\n borderRadius: \"4px\",\n border: \"1px solid rgba(255, 255, 255, 0.4)\",\n boxShadow: \"inset 0 1px 3px rgba(0, 0, 0, 0.3)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: `${(isMuted ? 0 : volume) * 100}%`,\n background:\n \"linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)\",\n borderRadius: \"4px\",\n transition:\n \"height 0.15s ease-out, box-shadow 0.2s ease-in-out\",\n boxShadow:\n \"0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n bottom: `calc(${\n (isMuted ? 0 : volume) * 100\n }% - 8px)`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n width: \"16px\",\n height: \"16px\",\n background:\n \"linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)\",\n borderRadius: \"50%\",\n border: \"2px solid rgba(96, 165, 250, 0.9)\",\n boxShadow:\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\",\n transition:\n \"bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out\",\n cursor: \"grab\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)\";\n e.currentTarget.style.cursor = \"grab\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.boxShadow =\n \"0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)\";\n }}\n onMouseDown={(e) => {\n e.currentTarget.style.cursor = \"grabbing\";\n }}\n onMouseUp={(e) => {\n e.currentTarget.style.cursor = \"grab\";\n }}\n />\n </div>\n </div>\n </>\n )}\n </div>\n\n <button\n onClick={() => {\n if (onFullscreenToggle) {\n onFullscreenToggle();\n } else if (playerRef.current) {\n playerRef.current.toggleFullscreen().catch((err) => {\n console.error(\"Fullscreen error:\", err);\n });\n }\n }}\n onMouseEnter={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)\";\n }}\n onMouseLeave={(e) => {\n const target = e.currentTarget as HTMLButtonElement;\n target.style.boxShadow =\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\";\n target.style.background =\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\";\n }}\n style={{\n background:\n \"linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)\",\n color: \"#ffffff\",\n border: \"none\",\n borderRadius: `${18 * responsiveScale}px`,\n padding: `${8 * responsiveScale}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backdropFilter: \"blur(20px)\",\n boxShadow:\n \"0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n minWidth: `${46 * responsiveScale}px`,\n minHeight: `${46 * responsiveScale}px`,\n }}\n title={\n isFullscreen ? \"Exit Fullscreen\" : \"Enter Fullscreen\"\n }\n >\n {isFullscreen ? (\n <FaCompress\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n ) : (\n <FaExpand\n size={Math.max(14, 16 * responsiveScale)}\n style={{\n filter: \"drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))\",\n color: \"#ffffff\",\n }}\n />\n )}\n </button>\n </div>\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 Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n} from \"../types\";\nimport type { PrebidBidResponse } from \"../types\";\nimport { createPrebidManager } from \"../sdk/prebid\";\nimport { createPrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport type { PrebidAdLayer } from \"../sdk/prebidAdLayer\";\nimport {\n sendInitialTracking,\n sendHeartbeat,\n sendAdDetectTracking,\n sendAdLoadedTracking,\n sendAdImpressionTracking,\n} from \"../utils/tracking\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport { logBrowserInfo, getBrowserConfigOverrides, detectBrowser } from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private prebidManager: ReturnType<typeof createPrebidManager>;\n private adLayer: PrebidAdLayer;\n private pendingNextAdBids: PrebidBidResponse[] | null = null;\n private continuousFetchLoopPromise: Promise<void> | null = null;\n private attached = false;\n private inAdBreak = false;\n private currentAdBreakStartWallClockMs: number | undefined;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private adStartTimerId: number | undefined;\n private adFailsafeTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private adPodQueue: string[] = [];\n private lastHeartbeatTime: number = 0;\n private heartbeatInterval: number | undefined;\n private currentAdIndex: number = 0;\n private totalAdsInBreak: number = 0;\n private showAds: boolean = false;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private activeAdRequestToken: number | null = null;\n private adRequestWatchdogId: number | undefined;\n private adRequestWatchdogToken: number | null = null;\n private adFailsafeToken: number | null = null;\n private continuousFetchingActive: boolean = false;\n private maxPlaceholderDurationMs: number = 5000;\n private isShowingPlaceholder: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n \n private totalAdRequestsInBreak: number = 0;\n private readonly maxTotalAdRequestsPerBreak: number = 20;\n \n private pendingAdBreak: {\n marker: Scte35Marker;\n detectedAtFragmentSn?: number;\n isFetching: boolean;\n fetchStartTime?: number;\n } | null = null;\n private prefetchTimerId: number | undefined;\n private savedMutedStateBeforeScte: { muted: boolean; volume: number } | null = null;\n\n private consecutiveFailures: number = 0;\n private readonly maxConsecutiveFailures: number = 5;\n private lastAdRequestTime: number = 0;\n private readonly minAdRequestIntervalMs: number = 2500;\n private readonly backoffBaseMs: number = 1000;\n private readonly maxBackoffMs: number = 15000;\n private readonly adTransitionGapMs: number = 1500;\n private placeholderContainer: HTMLDivElement | undefined;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n \n this.config = { ...browserOverrides, ...config };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n this.prebidManager = createPrebidManager(\n config.debugAdTiming !== undefined ? { debug: !!config.debugAdTiming } : {}\n );\n this.adLayer = createPrebidAdLayer(this.video, {\n continueLiveStreamDuringAds: false,\n debug: !!config.debugAdTiming,\n });\n }\n\n private async adRequest(): Promise<PrebidBidResponse[]> {\n await this.prebidManager.initialize();\n return this.prebidManager.requestBidsUntilResponse();\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n this.initializeTracking();\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:\",\n {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior: \"vod (main video pauses during ads)\",\n }\n );\n }\n\n this.adLayer.updateOptions({ continueLiveStreamDuringAds: false, mainHlsInstance: null });\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\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 if (this.config.allowNativeHls === false) {\n this.isLiveStream = true;\n } else {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n }\n\n if (this.config.debugAdTiming) {\n const adBehavior = this.shouldContinueLiveStreamDuringAds()\n ? \"live (main video continues muted during ads)\"\n : \"vod (main video pauses during ads)\";\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n adBehavior,\n });\n }\n\n this.adLayer.updateOptions({\n continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds(),\n mainHlsInstance: this.hls ?? null,\n });\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.config.debugAdTiming) {\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.inAdBreak || this.pendingAdBreak) {\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 ? this.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 = this.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.config.debugAdTiming) {\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.startAdPrefetch(marker, frag?.sn);\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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.config.debugAdTiming) {\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_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) 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\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.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.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n } as Scte35Marker;\n this.onScte35Marker(marker);\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.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 = this.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.onScte35Marker(marker);\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\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.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private getAdSource(): \"prebid\" {\n return \"prebid\";\n }\n\n private attachAdLayerEventListeners(): void {\n this.adLayer.on(\"ad_impression\", () => {\n if (this.config.licenseKey) {\n sendAdImpressionTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n adIndex: this.currentAdIndex,\n timestamp: new Date().toISOString(),\n });\n }\n });\n this.adLayer.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.adLayer.stop().catch(() => {});\n this.handleAdFailure();\n });\n this.adLayer.on(\"content_pause\", () => {\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = true;\n \n if (this.inAdBreak && this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)\");\n }\n }\n\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 0 : this.adLayer.getOriginalVolume()\n );\n\n if (this.isShowingPlaceholder) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder - new ads starting\");\n }\n this.hidePlaceholderLayer();\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n });\n this.adLayer.on(\"content_resume\", () => {\n const remaining = this.getRemainingAdMs();\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, pendingNext=%s\",\n this.inAdBreak,\n remaining,\n !!this.pendingNextAdBids\n );\n }\n\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.activeAdRequestToken = null;\n this.showAds = false;\n\n if (!this.inAdBreak) {\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) this.video.muted = restoredMuted;\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) this.video.volume = restoredVolume;\n return;\n }\n\n this.consecutiveFailures = 0;\n\n if (this.pendingNextAdBids && this.pendingNextAdBids.length > 0) {\n const bids = [...this.pendingNextAdBids];\n this.pendingNextAdBids = null;\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n setTimeout(() => {\n if (!this.inAdBreak || bids.length === 0) return;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch((err) => {\n if (this.config.debugAdTiming) console.warn(\"[StormcloudVideoPlayer] playAd(pending) failed:\", err);\n this.handleAdFailure();\n });\n }, this.adTransitionGapMs);\n return;\n }\n\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] content_resume: remaining time low and duration known, ending ad pod\");\n }\n this.handleAdPodComplete();\n } else {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n }\n }\n });\n }\n\n private ensurePlaceholderContainer(): void {\n if (this.placeholderContainer) {\n return;\n }\n\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 = \"5\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n\n if (!this.video.parentElement) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Video element has no parent for placeholder container\");\n }\n return;\n }\n\n this.video.parentElement.appendChild(container);\n this.placeholderContainer = container;\n }\n\n private showPlaceholderLayer(): void {\n this.ensurePlaceholderContainer();\n \n if (!this.placeholderContainer) {\n return;\n }\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video when showing placeholder\");\n }\n }\n\n const wasHidden = this.placeholderContainer.style.display === \"none\" || this.placeholderContainer.style.opacity === \"0\";\n if (wasHidden) {\n this.placeholderContainer.style.transition = \"none\";\n } else {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n \n this.placeholderContainer.style.backgroundColor = \"#000\";\n this.placeholderContainer.style.display = \"flex\";\n this.placeholderContainer.offsetHeight;\n this.placeholderContainer.style.opacity = \"1\";\n this.placeholderContainer.style.pointerEvents = \"auto\";\n \n if (wasHidden) {\n requestAnimationFrame(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.transition = \"opacity 0.3s ease-in-out\";\n }\n });\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Showing placeholder layer\");\n }\n }\n\n private hidePlaceholderLayer(): void {\n if (!this.placeholderContainer) {\n return;\n }\n\n this.placeholderContainer.style.opacity = \"0\";\n setTimeout(() => {\n if (this.placeholderContainer) {\n this.placeholderContainer.style.display = \"none\";\n this.placeholderContainer.style.pointerEvents = \"none\";\n this.placeholderContainer.style.backgroundColor = \"#000\";\n }\n }, 300);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Hiding placeholder layer\");\n }\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.adLayer.initialize();\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.attachAdLayerEventListeners();\n\n this.timeUpdateHandler = () => {\n this.onTimeUpdate(this.video.currentTime);\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (\n this.nativeHlsMode &&\n this.videoSrcProtection &&\n !this.adLayer.isAdPlaying()\n ) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Video src was cleared, restoring:\",\n this.videoSrcProtection\n );\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n\n if (streamType === \"other\") {\n return true;\n }\n\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.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 = this.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 = this.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 = this.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 = this.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 = this.parseScte35Binary(tag.value);\n if (bin) return bin;\n }\n\n return undefined;\n }\n\n private 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\n private onScte35Marker(marker: Scte35Marker): void {\n if (this.config.debugAdTiming) {\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.pendingAdBreak,\n });\n }\n\n if (marker.type === \"start\") {\n this.savedMutedStateBeforeScte = {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE start marker\");\n }\n }\n\n if (this.inAdBreak) {\n if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n if (this.config.debugAdTiming) {\n console.log(`[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ${this.expectedAdBreakDurationMs}ms`);\n }\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n\n this.inAdBreak = true;\n const durationMs =\n marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : (this.pendingAdBreak?.marker.durationSeconds != null \n ? this.pendingAdBreak.marker.durationSeconds * 1000 \n : undefined);\n this.expectedAdBreakDurationMs = durationMs;\n this.currentAdBreakStartWallClockMs = Date.now();\n\n if (this.config.licenseKey) {\n const adDetectInfo = {\n source: \"scte35\" as const,\n timestamp: new Date().toISOString(),\n ...(marker.durationSeconds != null && { durationSeconds: marker.durationSeconds }),\n ...(marker.ptsSeconds != null && { ptsSeconds: marker.ptsSeconds }),\n ...(this.pendingAdBreak?.detectedAtFragmentSn != null && {\n detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn,\n }),\n };\n sendAdDetectTracking(this.config.licenseKey, adDetectInfo);\n }\n\n const isManifestMarker = this.isManifestBasedMarker(marker);\n const forceImmediate = this.config.immediateManifestAds ?? true;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad start decision:\", {\n isManifestMarker,\n forceImmediate,\n hasPts: typeof marker.ptsSeconds === \"number\",\n });\n }\n\n if (isManifestMarker && forceImmediate) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (manifest-based)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n } else if (typeof marker.ptsSeconds === \"number\") {\n const tol = this.config.driftToleranceMs ?? 1000;\n const nowMs = this.video.currentTime * 1000;\n const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;\n const deltaMs = Math.floor(marker.ptsSeconds * 1000 - estCurrentPtsMs);\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] PTS-based timing calculation:\", {\n nowMs,\n estCurrentPtsMs,\n markerPtsMs: marker.ptsSeconds * 1000,\n deltaMs,\n tolerance: tol,\n });\n }\n\n if (deltaMs > tol) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`\n );\n }\n this.scheduleAdStartIn(deltaMs);\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (within tolerance)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n } else {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Starting ad immediately (fallback)\"\n );\n }\n this.clearAdStartTimer();\n this.handleAdStart(marker);\n }\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n if (\n this.expectedAdBreakDurationMs != null &&\n this.currentAdBreakStartWallClockMs != null\n ) {\n const elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;\n const remainingMs = Math.max(\n 0,\n this.expectedAdBreakDurationMs - elapsedMs\n );\n this.scheduleAdStopCountdown(remainingMs);\n }\n \n if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.currentAdIndex++;\n this.adLayer.playAd(bids).catch(() => this.handleAdFailure());\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video on SCTE end marker\");\n }\n }\n\n const remaining = this.getRemainingAdMs();\n const adPlaying = this.adLayer.isAdPlaying();\n const hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;\n \n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 end marker received:\", {\n remaining,\n adPlaying,\n hasQueuedAds,\n activeAdRequest: this.activeAdRequestToken !== null,\n });\n }\n \n if (adPlaying || remaining > 500) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining\");\n }\n return;\n }\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n \n if (adPlaying) {\n this.adLayer.stop().catch(() => {});\n }\n \n this.handleAdPodComplete();\n return;\n }\n }\n\n private 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\n private 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\n private 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\n private 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\n private 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\n private parseScte35Binary(data: Uint8Array): Scte35Marker | undefined {\n class 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 }\n\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 r.readBits(8);\n r.readBits(1);\n r.readBits(6);\n const ptsAdjHigh = r.readBits(1);\n const ptsAdjLow = r.readBits(32);\n void ptsAdjHigh;\n void ptsAdjLow;\n r.readBits(8);\n r.readBits(12);\n const spliceCommandLength = r.readBits(12);\n const spliceCommandType = r.readBits(8);\n if (spliceCommandType !== 5) {\n return undefined;\n }\n 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 if (programSpliceFlag && !spliceImmediateFlag) {\n const timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\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 timeSpecifiedFlag = r.readBits(1) === 1;\n if (timeSpecifiedFlag) {\n r.readBits(6);\n r.readBits(33);\n } else {\n r.readBits(7);\n }\n }\n }\n }\n let durationSeconds: number | undefined = undefined;\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\n if (outOfNetwork) {\n const marker: Scte35Marker = {\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { splice_command_type: 5 },\n } as Scte35Marker;\n return marker;\n }\n return undefined;\n }\n\n private 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.config.debugAdTiming) {\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.config.debugAdTiming) {\n console.warn(\n \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n error\n );\n }\n });\n }\n }\n\n getCurrentAdIndex(): number {\n return this.currentAdIndex;\n }\n\n getTotalAdsInBreak(): number {\n return this.totalAdsInBreak;\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.adLayer.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.showAds;\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n private shouldContinueLiveStreamDuringAds(): boolean {\n if (this.config.allowNativeHls) {\n return false;\n }\n\n if (!this.isLiveStream) {\n return false;\n }\n\n return true;\n }\n\n private startAdPrefetch(marker: Scte35Marker, fragmentSn?: number): void {\n if (this.pendingAdBreak || this.inAdBreak) {\n return;\n }\n\n this.pendingAdBreak = {\n marker,\n ...(fragmentSn !== undefined ? { detectedAtFragmentSn: fragmentSn } : {}),\n isFetching: false,\n fetchStartTime: Date.now(),\n };\n\n void this.adRequest().then(() => {}).catch(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Prebid auction prefetch failed, will request at playback time\");\n }\n });\n\n if (this.config.debugAdTiming) {\n console.log(\"[PREFETCH] Ad break marker registered, auction prefetch started\");\n }\n }\n\n private clearPendingAdBreak(): void {\n if (this.prefetchTimerId != null) {\n clearTimeout(this.prefetchTimerId);\n this.prefetchTimerId = undefined;\n }\n this.pendingAdBreak = null;\n }\n\n private startContinuousFetchLoop(): void {\n if (this.continuousFetchLoopPromise != null) return;\n this.continuousFetchLoopPromise = this.runContinuousFetchLoop();\n }\n\n private async runContinuousFetchLoop(): Promise<void> {\n const backoffMs = () => {\n const mult = Math.pow(2, this.consecutiveFailures);\n return Math.min(this.backoffBaseMs * mult, this.maxBackoffMs);\n };\n while (this.inAdBreak && this.continuousFetchingActive) {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) break;\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) break;\n const delay = this.lastAdRequestTime ? this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;\n const elapsed = Date.now() - this.lastAdRequestTime;\n if (elapsed < delay && this.lastAdRequestTime > 0) {\n await new Promise((r) => setTimeout(r, delay - elapsed));\n }\n if (!this.inAdBreak || !this.continuousFetchingActive) break;\n try {\n const bids = await this.adRequest();\n this.lastAdRequestTime = Date.now();\n if (!this.inAdBreak) break;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] Next ad response stored (ad currently playing)\");\n }\n } else {\n this.currentAdIndex++;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 0 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n }\n } catch (err) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] adRequest failed:\", err);\n }\n }\n await new Promise((r) => setTimeout(r, backoffMs()));\n }\n this.continuousFetchLoopPromise = null;\n }\n\n private async handleAdStart(_marker: Scte35Marker): Promise<void> {\n const adBreakDurationMs =\n _marker.durationSeconds != null\n ? _marker.durationSeconds * 1000\n : undefined;\n\n if (this.config.debugAdTiming) {\n const mode = this.isLiveStream ? \"LIVE\" : \"VOD\";\n console.log(\n `[CONTINUOUS-FETCH] 📺 ${mode} MODE: Target duration=${adBreakDurationMs}ms`\n );\n }\n\n this.consecutiveFailures = 0;\n this.continuousFetchingActive = true;\n this.continuousFetchLoopPromise = null;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.totalAdRequestsInBreak = 0;\n\n const state = this.savedMutedStateBeforeScte ?? {\n muted: this.video.muted,\n volume: this.video.volume,\n };\n this.adLayer.updateOriginalMutedState(state.muted, state.volume);\n this.savedMutedStateBeforeScte = null;\n\n if (!this.video.muted) {\n this.video.muted = true;\n this.video.volume = 0;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted video in handleAdStart\");\n }\n }\n\n this.inAdBreak = true;\n this.currentAdBreakStartWallClockMs = Date.now();\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 1;\n this.adPodQueue = [];\n\n this.showAds = true;\n\n this.showPlaceholderLayer();\n this.adLayer.showPlaceholder();\n\n if (\n this.expectedAdBreakDurationMs == null &&\n adBreakDurationMs != null\n ) {\n this.expectedAdBreakDurationMs = adBreakDurationMs;\n }\n\n this.clearPendingAdBreak();\n\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ✅ First ad request successful, starting playback\");\n }\n this.currentAdIndex++;\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n const adVolume = state.muted ? 0 : state.volume;\n this.adLayer.setAdVolume(adVolume);\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] ⚠️ First ad request failed:\", error);\n }\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n\n this.startContinuousFetchLoop();\n }\n\n private stopContinuousFetching(): void {\n this.continuousFetchingActive = false;\n \n this.hidePlaceholderLayer();\n \n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Stopping continuous ad fetching\");\n }\n }\n\n private async tryNextAvailableAdWithRateLimit(): Promise<void> {\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n const backoffMultiplier = Math.pow(2, this.consecutiveFailures);\n const backoffDelay = Math.min(this.backoffBaseMs * backoffMultiplier, this.maxBackoffMs);\n const effectiveMinInterval = this.minAdRequestIntervalMs + (this.consecutiveFailures > 0 ? backoffDelay : 0);\n \n const timeSinceLastRequest = Date.now() - this.lastAdRequestTime;\n if (timeSinceLastRequest < effectiveMinInterval) {\n const waitTime = effectiveMinInterval - timeSinceLastRequest;\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⏳ Rate limiting: waiting ${waitTime}ms before next request (backoff: ${this.consecutiveFailures} failures)`);\n }\n await new Promise(resolve => setTimeout(resolve, waitTime));\n }\n\n return this.tryNextAvailableAd(0);\n }\n\n private async tryNextAvailableAd(_retryCount: number = 0): Promise<void> {\n if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max ad requests per break (${this.maxTotalAdRequestsPerBreak}) reached`);\n }\n this.handleAdPodComplete();\n return;\n }\n const remaining = this.getRemainingAdMs();\n if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏹️ No time remaining, ending ad break\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Too many consecutive failures (${this.consecutiveFailures}), ending ad break`);\n }\n this.handleAdPodComplete();\n return;\n }\n\n try {\n this.lastAdRequestTime = Date.now();\n const bids = await this.adRequest();\n if (!this.inAdBreak) return;\n if (bids.length > 0) {\n this.consecutiveFailures = 0;\n this.currentAdIndex++;\n this.totalAdRequestsInBreak++;\n if (this.adLayer.isAdPlaying()) {\n this.pendingNextAdBids = bids;\n } else {\n if (this.config.licenseKey) {\n sendAdLoadedTracking(this.config.licenseKey, {\n source: this.getAdSource(),\n timestamp: new Date().toISOString(),\n });\n }\n await this.adLayer.playAd(bids);\n if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {\n this.scheduleAdStopCountdown(this.getRemainingAdMs());\n }\n this.adLayer.setAdVolume(\n this.adLayer.getOriginalMutedState() ? 0 : this.adLayer.getOriginalVolume()\n );\n }\n } else {\n this.consecutiveFailures++;\n await this.showPlaceholderAndWaitForAds();\n }\n } catch (error) {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.warn(\"[CONTINUOUS-FETCH] tryNextAvailableAd request failed:\", error);\n }\n await this.showPlaceholderAndWaitForAds();\n }\n }\n\n private async showPlaceholderAndWaitForAds(): Promise<void> {\n const remaining = this.getRemainingAdMs();\n const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);\n\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Skipping placeholder - too many consecutive failures\");\n }\n this.handleAdPodComplete();\n return;\n }\n\n if (waitTime < 1000) {\n this.handleAdPodComplete();\n return;\n }\n\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] ⬛ Showing placeholder for ${waitTime}ms while waiting for ad response`);\n }\n\n this.isShowingPlaceholder = true;\n this.adLayer.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.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] 🛑 Too many failures during placeholder wait\");\n }\n break;\n }\n\n if (this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {\n const bids = this.pendingNextAdBids;\n this.pendingNextAdBids = null;\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.currentAdIndex++;\n try {\n await this.adLayer.playAd(bids);\n this.consecutiveFailures = 0;\n } catch {\n this.consecutiveFailures++;\n await this.tryNextAvailableAdWithRateLimit();\n }\n return;\n }\n\n if (this.adLayer.isAdPlaying()) {\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n return;\n }\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[CONTINUOUS-FETCH] ⏰ Placeholder timeout, ending ad break\");\n }\n\n this.isShowingPlaceholder = false;\n this.adLayer.hidePlaceholder();\n this.handleAdPodComplete();\n }\n\n private onTimeUpdate(_currentTimeSec: number): void {\n if (this.adLayer.isAdPlaying()) return;\n }\n\n private 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 private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private ensureAdStoppedByTimer(): void {\n if (!this.inAdBreak) return;\n\n this.adStopTimerId = undefined;\n\n const adPlaying = this.adLayer.isAdPlaying();\n const pendingAds = this.adPodQueue.length > 0;\n const checkIntervalMs = Math.max(\n 250,\n Math.floor(this.config.adBreakCheckIntervalMs ?? 1000)\n );\n const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;\n const maxExtensionMs =\n typeof maxExtensionMsConfig === \"number\" && maxExtensionMsConfig > 0\n ? maxExtensionMsConfig\n : 60000;\n\n let elapsedSinceStartMs = 0;\n if (this.currentAdBreakStartWallClockMs != null) {\n elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;\n }\n const expectedDurationMs = this.expectedAdBreakDurationMs ?? 0;\n const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);\n\n const shouldExtendAdBreak =\n (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;\n\n if (shouldExtendAdBreak) {\n this.scheduleAdStopCountdown(checkIntervalMs);\n return;\n }\n\n if (adPlaying) {\n this.adLayer.stop().catch(() => {});\n }\n\n this.handleAdPodComplete();\n }\n\n private scheduleAdStartIn(delayMs: number): void {\n this.clearAdStartTimer();\n const ms = Math.max(0, Math.floor(delayMs));\n if (ms === 0) {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n return;\n }\n this.adStartTimerId = window.setTimeout(() => {\n this.handleAdStart({ type: \"start\" } as Scte35Marker).catch(() => {});\n }, ms) as unknown as number;\n }\n\n private clearAdStartTimer(): void {\n if (this.adStartTimerId != null) {\n clearTimeout(this.adStartTimerId);\n this.adStartTimerId = undefined;\n }\n }\n\n private 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 private handleAdPodComplete(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] 🏁 Ad pod complete - cleaning up\");\n }\n\n this.clearAdRequestWatchdog();\n this.clearAdFailsafeTimer();\n this.activeAdRequestToken = null;\n\n this.stopContinuousFetching();\n this.clearPendingAdBreak();\n this.pendingNextAdBids = null;\n\n if (this.isShowingPlaceholder) {\n this.adLayer.hidePlaceholder();\n this.isShowingPlaceholder = false;\n }\n\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.currentAdBreakStartWallClockMs = undefined;\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.adPodQueue = [];\n this.showAds = false;\n this.currentAdIndex = 0;\n this.totalAdsInBreak = 0;\n this.totalAdRequestsInBreak = 0;\n this.consecutiveFailures = 0;\n\n this.adLayer.stop().catch(() => {});\n\n const restoredMuted = this.adLayer.getOriginalMutedState();\n const restoredVolume = this.adLayer.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n const isTizen = detectBrowser().tizenVersion !== undefined;\n if (isTizen && this.hls) {\n this.hls.attachMedia(this.video);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Tizen: re-attached HLS to video element after ad break to restore audio\");\n }\n }\n\n if (this.shouldContinueLiveStreamDuringAds()) {\n if (this.config.debugAdTiming) {\n if (this.video.paused) {\n console.log(\"[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback\");\n } else {\n console.log(\"[StormcloudVideoPlayer] Content video already playing in live mode after ads\");\n }\n }\n this.video.play()?.catch(() => {});\n } else if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n\n if (isTizen && !restoredMuted) {\n requestAnimationFrame(() => {\n this.video.muted = false;\n this.video.volume = restoredVolume;\n });\n }\n }\n\n private handleAdFailure(): void {\n this.consecutiveFailures++;\n if (this.config.debugAdTiming) {\n console.log(\n `[CONTINUOUS-FETCH] Ad failure: consecutiveFailures=${this.consecutiveFailures}`\n );\n }\n if (this.consecutiveFailures >= this.maxConsecutiveFailures) {\n if (this.config.debugAdTiming) {\n console.log(`[CONTINUOUS-FETCH] 🛑 Max consecutive failures reached (${this.consecutiveFailures}), ending ad break gracefully`);\n }\n this.handleAdPodComplete();\n }\n }\n\n private 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.handleAdFailure();\n }, timeoutMs) as unknown as number;\n\n this.logAdState(\"ad_request_watchdog_started\", { token, timeoutMs });\n }\n\n private 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 private 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 imaAdPlaying: this.adLayer.isAdPlaying(),\n });\n\n this.handleAdFailure();\n }, failsafeMs) as unknown as number;\n\n this.logAdState(\"ad_failsafe_started\", { token, failsafeMs });\n }\n\n private 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 private logAdState(event: string, extra: Record<string, unknown> = {}): void {\n if (!this.config.debugAdTiming) {\n return;\n }\n\n console.log(\"[StormcloudVideoPlayer][AdState]\", {\n event,\n timestamp: new Date().toISOString(),\n showAds: this.showAds,\n adPlaying: this.adLayer.isAdPlaying(),\n inAdBreak: this.inAdBreak,\n activeAdRequestToken: this.activeAdRequestToken,\n ...extra,\n });\n }\n\n private getRemainingAdMs(): number {\n if (this.currentAdBreakStartWallClockMs == null) return 0;\n if (this.expectedAdBreakDurationMs == null) return Number.MAX_SAFE_INTEGER;\n const elapsed = Date.now() - this.currentAdBreakStartWallClockMs;\n return Math.max(0, this.expectedAdBreakDurationMs - elapsed);\n }\n\n toggleMute(): void {\n if (this.adLayer.isAdPlaying()) {\n const currentPerceptualState = this.isMuted();\n const newMutedState = !currentPerceptualState;\n\n this.adLayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adLayer.setAdVolume(newMutedState ? 0 : this.adLayer.getOriginalVolume());\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:\",\n newMutedState\n );\n }\n } else {\n this.video.muted = !this.video.muted;\n this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Muted:\", this.video.muted);\n }\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.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 (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Entered fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\"[StormcloudVideoPlayer] Fullscreen error:\", err);\n }\n reject(err);\n });\n } else {\n document\n .exitFullscreen()\n .then(() => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Exited fullscreen\");\n }\n resolve();\n })\n .catch((err) => {\n if (this.config.debugAdTiming) {\n console.error(\n \"[StormcloudVideoPlayer] Exit fullscreen error:\",\n err\n );\n }\n reject(err);\n });\n }\n });\n }\n\n isMuted(): boolean {\n if (this.adLayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] isMuted() override during ad playback -> false\"\n );\n }\n return false;\n }\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n const adPlaying = this.adLayer.isAdPlaying();\n\n if (adPlaying && muted === this.video.muted) {\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] setMuted reflective update during ad ignored\",\n { muted }\n );\n }\n return;\n }\n\n this.video.muted = muted;\n\n if (adPlaying) {\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n this.adLayer.setAdVolume(muted ? 0 : this.adLayer.getOriginalVolume());\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted applied during ad\", {\n muted,\n });\n }\n return;\n }\n\n this.adLayer.updateOriginalMutedState(muted, this.video.volume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setMuted called:\", muted);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n const adPlaying = this.adLayer.isAdPlaying();\n\n if (adPlaying) {\n this.adLayer.setAdVolume(clampedVolume);\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume applied during ad\", {\n volume: clampedVolume,\n });\n }\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adLayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] setVolume called:\", clampedVolume);\n }\n }\n }\n\n getVolume(): number {\n const adPlaying = this.adLayer.isAdPlaying();\n if (adPlaying) {\n return this.adLayer.getAdVolume();\n }\n return this.video.volume;\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Resizing player\");\n }\n\n if (this.adLayer && this.adLayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 480;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`\n );\n }\n\n this.adLayer.resize(width, height);\n }\n }\n\n destroy(): void {\n this.stopContinuousFetching();\n this.clearAdStartTimer();\n this.clearAdStopTimer();\n this.clearAdFailsafeTimer();\n this.clearAdRequestWatchdog();\n this.clearPendingAdBreak();\n \n if (this.placeholderContainer) {\n if (this.placeholderContainer.parentElement) {\n this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);\n }\n this.placeholderContainer = undefined;\n }\n \n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n \n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n this.hls?.destroy();\n this.adLayer?.destroy();\n this.consecutiveFailures = 0;\n }\n}\n","import type { PrebidBidResponse, PrebidManager } from \"../types\";\n\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst AUCTION_URL = \"https://sspproxy.adstorm.co/openrtb2/auction/adstorm\";\n\nexport interface PrebidManagerOptions {\n debug?: boolean;\n}\n\nexport function createPrebidManager(\n options: PrebidManagerOptions = {}\n): PrebidManager {\n let initialized = false;\n const debug = options.debug ?? false;\n\n function log(...args: any[]): void {\n if (debug) {\n console.log(\"[Prebid]\", ...args);\n }\n }\n\n function warn(...args: any[]): void {\n console.warn(\"[Prebid]\", ...args);\n }\n\n function parseResponse(data: any): PrebidBidResponse[] {\n const bids: PrebidBidResponse[] = [];\n const seatbids: any[] = data?.seatbid || [];\n const currency: string = data?.cur || \"USD\";\n\n for (const seatbid of seatbids) {\n const seat: string = seatbid.seat || \"unknown\";\n const bidArray: any[] = seatbid.bid || [];\n\n for (const bid of bidArray) {\n const cacheUrl: string | undefined =\n bid.ext?.prebid?.cache?.vastXml?.url;\n const vastXml: string | undefined = bid.adm || undefined;\n\n const bidResponse: PrebidBidResponse = {\n bidder: seat,\n cpm: bid.price || 0,\n width: bid.w || 0,\n height: bid.h || 0,\n adId: bid.id || \"\",\n impId: bid.impid || \"\",\n creativeId: bid.crid || \"\",\n currency,\n };\n if (cacheUrl) bidResponse.vastUrl = cacheUrl;\n if (vastXml) bidResponse.vastXml = vastXml;\n if (bid.adomain) bidResponse.adomain = bid.adomain;\n\n bids.push(bidResponse);\n }\n }\n\n bids.sort((a, b) => b.cpm - a.cpm);\n return bids;\n }\n\n async function initialize(): Promise<void> {\n if (initialized) return;\n initialized = true;\n log(\"Initialized, auction URL:\", AUCTION_URL);\n }\n\n async function requestBids(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n\n const timeout = DEFAULT_TIMEOUT_MS;\n\n log(\"Fetching auction response from:\", AUCTION_URL);\n\n const controller =\n typeof AbortController !== \"undefined\"\n ? new AbortController()\n : null;\n const timeoutId = setTimeout(() => {\n controller?.abort();\n }, timeout + 2000);\n\n try {\n const fetchOptions: RequestInit = {\n method: \"POST\",\n };\n if (controller) {\n fetchOptions.signal = controller.signal;\n }\n\n const response = await fetch(AUCTION_URL, fetchOptions);\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(\n `Prebid Server returned HTTP ${response.status}: ${body.slice(0, 200)}`\n );\n }\n\n const data = await response.json();\n\n if (debug && data?.ext?.responsetimemillis) {\n log(\"Bidder response times:\", data.ext.responsetimemillis);\n }\n if (debug && data?.ext?.errors) {\n warn(\"Auction errors:\", data.ext.errors);\n }\n\n const bids = parseResponse(data);\n log(`Received ${bids.length} bid(s)`);\n\n if (debug) {\n for (const b of bids) {\n log(\n ` ${b.bidder}: $${b.cpm.toFixed(2)} ${b.currency}` +\n ` ${b.width}x${b.height}` +\n (b.vastUrl ? \" [cached VAST]\" : \"\") +\n (b.vastXml && !b.vastUrl ? \" [VAST XML]\" : \"\")\n );\n }\n }\n\n return bids;\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (error?.name === \"AbortError\") {\n warn(`Auction request timed out after ${timeout + 2000}ms`);\n return [];\n }\n\n throw error;\n }\n }\n\n const REQUEST_BIDS_MAX_RETRIES = 3;\n const REQUEST_BIDS_BACKOFF_MS = 1500;\n\n async function requestBidsUntilResponse(): Promise<PrebidBidResponse[]> {\n if (!initialized) {\n throw new Error(\"Prebid not initialized. Call initialize() first.\");\n }\n let lastError: unknown;\n for (let attempt = 1; attempt <= REQUEST_BIDS_MAX_RETRIES; attempt++) {\n try {\n const bids = await requestBids();\n if (bids.length > 0) {\n log(`requestBidsUntilResponse: got ${bids.length} bid(s) on attempt ${attempt}`);\n return bids;\n }\n log(`requestBidsUntilResponse: no bids on attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES}`);\n } catch (err) {\n lastError = err;\n warn(`requestBidsUntilResponse: attempt ${attempt}/${REQUEST_BIDS_MAX_RETRIES} failed:`, err);\n }\n if (attempt < REQUEST_BIDS_MAX_RETRIES) {\n const delay = REQUEST_BIDS_BACKOFF_MS * attempt;\n log(`requestBidsUntilResponse: waiting ${delay}ms before retry`);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n if (lastError instanceof Error) {\n throw lastError;\n }\n return [];\n }\n\n function destroy(): void {\n initialized = false;\n log(\"Destroyed\");\n }\n\n return {\n initialize,\n requestBids,\n requestBidsUntilResponse,\n destroy,\n get isInitialized() {\n return initialized;\n },\n };\n}\n","export interface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nexport interface 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\nexport interface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport type MediaFileFilter = \"hls-only\" | \"mp4-first\" | \"all\";\n\nfunction isHlsType(type: string): boolean {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\n\nfunction isMp4Type(type: string): boolean {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\n\nexport function parseVastXml(\n xmlString: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): VastAd | null {\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 `${logPrefix} XML parsing error (malformed VAST XML):`,\n parserError.textContent\n );\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(`${logPrefix} No Ad element found in VAST XML`);\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\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 Math.round(parseFloat(durationParts[2] || \"0\"));\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible media files found in VAST XML`);\n }\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\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 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 const clickThrough = xmlDoc\n .querySelector(\"ClickThrough\")\n ?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\n\nexport async function fetchAndParseVastAd(\n vastTagUrl: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): Promise<VastAd | null> {\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\n const vastXml = await response.text();\n console.log(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml, filter, logPrefix);\n}\n\nexport function createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n}\n\nexport function fireTrackingPixels(\n urls: string[],\n sessionId?: string,\n logPrefix = \"[VastParser]\"\n): 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 const img = new Image(1, 1);\n img.onerror = () => {\n // 502 or other network errors are fire-and-forget; do not affect playback\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n","import type { PrebidBidResponse } from \"../types\";\nimport type { VastAd, VastMediaFile } from \"./vastParser\";\nimport {\n parseVastXml,\n fetchAndParseVastAd,\n fireTrackingPixels as fireTrackingPixelsShared,\n createEmptyTrackingState,\n} from \"./vastParser\";\nimport Hls from \"hls.js\";\n\nconst LOG = \"[PrebidAdLayer]\";\n\nexport interface PrebidAdLayerOptions {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls;\n debug?: boolean;\n}\n\nexport interface PrebidAdLayerOptionsUpdate {\n continueLiveStreamDuringAds?: boolean;\n mainHlsInstance?: Hls | null;\n}\n\nexport interface PrebidAdLayer {\n initialize: () => void;\n updateOptions: (opts: PrebidAdLayerOptionsUpdate) => void;\n playAd: (bids: PrebidBidResponse[]) => Promise<void>;\n pause: () => void;\n resume: () => void;\n stop: () => Promise<void>;\n destroy: () => void;\n isAdPlaying: () => boolean;\n resize: (width: number, height: number) => void;\n on: (event: string, listener: (payload?: any) => void) => void;\n off: (event: string, listener: (payload?: any) => void) => void;\n updateOriginalMutedState: (muted: boolean, volume?: number) => void;\n getOriginalMutedState: () => boolean;\n getOriginalVolume: () => number;\n setAdVolume: (volume: number) => void;\n getAdVolume: () => number;\n showPlaceholder: () => void;\n hidePlaceholder: () => void;\n}\n\nfunction resolveBidToVastAd(winner: PrebidBidResponse, logPrefix: string): Promise<VastAd | null> {\n if (winner.vastXml) {\n const ad = parseVastXml(winner.vastXml, \"mp4-first\", logPrefix);\n return Promise.resolve(ad);\n }\n if (winner.vastUrl) {\n return fetchAndParseVastAd(winner.vastUrl, \"mp4-first\", logPrefix);\n }\n return Promise.resolve(null);\n}\n\nexport function createPrebidAdLayer(\n contentVideo: HTMLVideoElement,\n options?: PrebidAdLayerOptions\n): PrebidAdLayer {\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 let mainHlsInstance: Hls | undefined = options?.mainHlsInstance;\n let continueLiveStreamDuringAds = options?.continueLiveStreamDuringAds ?? false;\n const debug = options?.debug ?? false;\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 let destroyed = false;\n let tornDown = false;\n let trackingFired = createEmptyTrackingState();\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(`${LOG} Error in event listener for ${event}:`, error);\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 fireTrackingPixelsShared(urls, sessionId, LOG);\n }\n\n function getMainStreamQuality(): { width: number; height: number; bitrate: number } | null {\n if (!mainHlsInstance?.levels) return null;\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 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) throw new Error(\"No media files available\");\n const firstFile = mediaFiles[0]!;\n if (mediaFiles.length === 1) return firstFile;\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n if (debug) console.log(`${LOG} No main stream quality info, using first media file`);\n return firstFile;\n }\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 const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n return { file, score };\n });\n scoredFiles.sort((a, b) => a.score - b.score);\n return scoredFiles[0]?.file ?? firstFile;\n }\n\n function isHlsMediaFile(file: VastMediaFile): boolean {\n return file.type === \"application/x-mpegURL\" || file.type.includes(\"m3u8\");\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 video.volume = 1.0;\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n const ad = currentAd;\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n const ad = currentAd;\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n if (debug) console.log(`${LOG} Ad started playing`);\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (tornDown || !currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n if (debug) console.log(`${LOG} Ad completed`);\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n if (tornDown) return;\n console.error(`${LOG} Ad video error:`, e);\n if (currentAd) fireTrackingPixels(currentAd.trackingUrls.error);\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd || !adVideoElement) 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 && !adVideoElement.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement && 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 if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad completion`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n emit(\"ad_impression\");\n emit(\"content_resume\");\n }\n\n function handleAdError(): void {\n if (tornDown) return;\n if (debug) console.log(`${LOG} Handling ad error`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n emit(\"ad_error\");\n }\n\n function teardownCurrentPlayback(): void {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n }\n\n function startNativePlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting native MP4 playback: ${mediaFile.url}`);\n adVideoElement.src = mediaFile.url;\n adVideoElement.load();\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native ad playback:`, error);\n handleAdError();\n });\n }\n\n function startHlsPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (debug) console.log(`${LOG} Starting HLS playback: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n adHls = new Hls({ enableWorker: true, lowLatencyMode: false });\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n adVideoElement!.play().catch((error) => {\n console.error(`${LOG} Error starting HLS ad playback:`, error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (_event, data) => {\n if (data.fatal) handleAdError();\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(`${LOG} Error starting native HLS ad playback:`, error);\n handleAdError();\n });\n } else {\n console.error(`${LOG} HLS not supported on this platform`);\n handleAdError();\n }\n }\n\n function startPlayback(mediaFile: VastMediaFile): void {\n if (!adVideoElement) return;\n if (isHlsMediaFile(mediaFile)) {\n startHlsPlayback(mediaFile);\n } else {\n startNativePlayback(mediaFile);\n }\n }\n\n async function playAd(bids: PrebidBidResponse[]): Promise<void> {\n if (destroyed) {\n return Promise.reject(new Error(\"Layer has been destroyed\"));\n }\n if (bids.length === 0) {\n return Promise.reject(new Error(\"No bids provided\"));\n }\n\n const winner = bids[0]!;\n if (debug) {\n console.log(`${LOG} Winning bid: ${winner.bidder} $${winner.cpm.toFixed(2)} ${winner.currency}`);\n }\n\n const ad = await resolveBidToVastAd(winner, LOG);\n if (!ad) {\n if (debug) console.warn(`${LOG} Winning bid has no VAST URL or XML`);\n emit(\"ad_error\");\n return Promise.reject(new Error(\"No VAST from bid\"));\n }\n\n if (debug) {\n console.log(`${LOG} Ad parsed: ${ad.title}, duration: ${ad.duration}s, mediaFiles: ${ad.mediaFiles.length}`);\n }\n\n sessionId = generateSessionId();\n currentAd = ad;\n trackingFired = { ...createEmptyTrackingState() };\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\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 contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl.appendChild(adVideoElement);\n setupAdEventListeners();\n } else {\n teardownCurrentPlayback();\n }\n\n const contentVolume = contentVideo.volume;\n originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));\n\n if (!continueLiveStreamDuringAds) {\n contentVideo.pause();\n }\n\n contentVideo.muted = true;\n contentVideo.volume = 0;\n adPlaying = true;\n setAdPlayingFlag(true);\n\n const adVolume = originalMutedState ? 0 : originalVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(ad.mediaFiles);\n if (debug) console.log(`${LOG} Loading ad from: ${mediaFile.url}`);\n startPlayback(mediaFile);\n }\n\n return {\n initialize() {\n if (debug) console.log(`${LOG} Initializing`);\n },\n\n updateOptions(opts: PrebidAdLayerOptionsUpdate) {\n if (opts.continueLiveStreamDuringAds !== undefined) {\n continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;\n }\n if (opts.mainHlsInstance !== undefined) {\n mainHlsInstance = opts.mainHlsInstance ?? undefined;\n }\n },\n\n playAd,\n\n pause() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (!adVideoElement.paused) adVideoElement.pause();\n } catch (error) {\n if (debug) console.warn(`${LOG} Error pausing ad:`, error);\n }\n },\n\n resume() {\n if (!adPlaying || !adVideoElement) return;\n try {\n if (adVideoElement.paused) adVideoElement.play().catch(() => {});\n } catch (error) {\n if (debug) console.warn(`${LOG} Error resuming ad:`, error);\n }\n },\n\n async stop() {\n tornDown = true;\n if (debug) console.log(`${LOG} Stopping ad`);\n adPlaying = false;\n setAdPlayingFlag(false);\n\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalMutedState ? 0 : originalVolume;\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 (continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.load();\n }\n currentAd = undefined;\n tornDown = false;\n },\n\n destroy() {\n tornDown = true;\n if (debug) console.log(`${LOG} Destroying`);\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n\n teardownCurrentPlayback();\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.removeAttribute(\"src\");\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\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\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 originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\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\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 };\n}\n","import type {\n ClientInfo,\n TrackingData,\n HeartbeatData,\n AdDetectInfo,\n AdLoadedInfo,\n AdImpressionInfo,\n} from \"../types\";\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\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n if (cachedBrowserId) {\n return cachedBrowserId;\n }\n\n const fingerprintString = JSON.stringify(clientInfo);\n\n if (typeof crypto !== \"undefined\" && crypto.subtle && 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(fingerprintString);\n } else {\n const utf8 = unescape(encodeURIComponent(fingerprintString));\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 const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n cachedBrowserId = hashHex;\n return hashHex;\n } catch (error) {\n console.warn(\n \"[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash\"\n );\n }\n }\n\n let hash = 0;\n for (let i = 0; i < fingerprintString.length; i++) {\n const char = fingerprintString.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 cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, \"0\");\n return cachedBrowserId;\n}\n\nconst TRACK_URL =\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track\";\n\nasync function sendTrackRequest(\n licenseKey: string | undefined,\n body: Record<string, unknown>\n): Promise<void> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n await response.json();\n}\n\nexport async function sendInitialTracking(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const trackingData: TrackingData = {\n browserId,\n ...clientInfo,\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(TRACK_URL, {\n method: \"POST\",\n headers,\n body: JSON.stringify(trackingData),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adDetectInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adLoadedInfo,\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): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n const trackingData: TrackingData = { browserId, ...clientInfo };\n await sendTrackRequest(licenseKey, {\n ...trackingData,\n licenseKey,\n adImpressionInfo,\n });\n } catch (error) {\n console.error(\n \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n error\n );\n }\n}\n\nexport async function sendHeartbeat(licenseKey?: string): Promise<void> {\n try {\n const clientInfo = getClientInfo();\n const browserId = await getBrowserID(clientInfo);\n\n const heartbeatData: HeartbeatData = {\n browserId,\n timestamp: new Date().toISOString(),\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (licenseKey) {\n headers[\"Authorization\"] = `Bearer ${licenseKey}`;\n }\n\n const response = await fetch(\n \"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat\",\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(heartbeatData),\n }\n );\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n await response.json();\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","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 supportsIMA: boolean;\n supportsModernJS: boolean;\n recommendedAdPlayer: 'ima' | 'hls';\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 supportsIMA = true;\n let supportsModernJS = true;\n let recommendedAdPlayer: 'ima' | 'hls' = 'ima';\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 if (webOSVersion !== undefined && webOSVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (webOSVersion !== undefined && webOSVersion >= 3) {\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\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 if (tizenVersion !== undefined && tizenVersion >= 4) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (tizenVersion !== undefined && tizenVersion >= 3 && chromeVersion >= 47) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n isLegacyTV = false;\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n if (chromeVersion >= 53) {\n supportsIMA = true;\n recommendedAdPlayer = 'ima';\n } else {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n isLegacyTV = true;\n }\n } else {\n if (chromeVersion > 0) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n\n if (chromeVersion < 50) {\n supportsIMA = false;\n supportsModernJS = false;\n recommendedAdPlayer = 'hls';\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (chromeVersion < 50) {\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\n }\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n supportsIMA = false;\n recommendedAdPlayer = 'hls';\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 supportsIMA,\n supportsModernJS,\n recommendedAdPlayer,\n webOSVersion,\n tizenVersion,\n chromeVersion: chromeVersionNum,\n };\n}\n\nexport function supportsGoogleIMA(): boolean {\n const browser = detectBrowser();\n\n if (browser.isLegacyTV) {\n return false;\n }\n\n if (typeof document === 'undefined' ||\n typeof document.createElement !== 'function') {\n return false;\n }\n\n try {\n const video = document.createElement('video');\n if (!video) {\n return false;\n }\n } catch (e) {\n return false;\n }\n\n if (typeof Promise === 'undefined') {\n return false;\n }\n\n return browser.supportsIMA;\n}\n\nexport function getRecommendedAdPlayer(): 'ima' | 'hls' {\n const browser = detectBrowser();\n return browser.recommendedAdPlayer;\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 const imaSupport = supportsGoogleIMA();\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 supportsIMA: imaSupport,\n supportsModernJS: browser.supportsModernJS,\n recommendedAdPlayer: browser.recommendedAdPlayer,\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 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 supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'ima':\n return supportsGoogleIMA();\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\n"]}