{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/player/AdConfigManager.cjs","../../src/player/AdConfigManager.ts","../../src/utils/vastEnvironmentSignals.ts","../../src/utils/vastMacros.ts","../../src/utils/mqttConfig.ts","../../src/utils/mqttClient.ts","../../src/utils/tracking.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","from","to","except","desc","call","key","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","AdConfigManager_exports","AdConfigManager","module","exports","AIRY_ANDROID_APP_ID","AIRY_WEBOS_APP_ID","AIRY_TIZEN_APP_ID","AIRY_ROKU_APP_ID","AIRY_APP_NAME","AIRY_DEFAULT_CONTENT_URL","CTV_SESSION_STORAGE_KEY","PLAYER_ID_STORAGE_KEY","LG_TEST_APP_ID","LG_TEST_APP_NAME","LG_TEST_CONTENT_URL","_lgTestDeviceId","getLgTestDeviceId","createUuid","isLgWebOS","navigator","test","userAgent","getDefaultAppId","ua","DEVICE_ID_STORAGE_KEYS","ANDROID_ID_TYPES","Set","resolveVastEnvironmentSignals","isCtv","platformLat","bridgeSignals","readNativeBridgeSignals","platformDevice","readPlatformNativeDeviceId","lg","deviceId","readStoredDeviceId","limitAdTracking","deviceIdType","readStoredString","inferDeviceIdType","readStoredLimitAdTracking","contentUrl","appId","appName","sessionId","getOrCreateCtvSessionId","deviceTypeHint","isEquivalentDeviceIdType","tagType","runtimeType","tag","toLowerCase","runtime","has","resolveNativeDeviceId","isMacroPlaceholder","isZeroedAdId","getOrCreateStoredUuid","storageKey","window","existing","id","localStorage","setItem","crypto","randomUUID","replace","char","Math","floor","random","nibble","toString","adinfo","webapis","tifa","getTIFA","lat","isLATEnabled","webOSDev","lgudid","LGUDID","roku","Roku","rida","getPublisherUniqueId","ZEROED_AD_ID_PATTERNS","t","trim","candidates","__STORMCLOUD_CTV_AD_INFO__","__STORMCLOUD_CTV__","stormcloudCtv","AiryTV","Android","webOS","tizen","amazon","filter","Boolean","source","readBridgeValue","readBridgeBoolean","keys","result","normalized","normalizeBoolean","getItem","UNEXPANDED_MACRO_PATTERN","INVALID_VAST_PARAM_KEY","EXAMPLE_COM_URL","CTV_UNSUPPORTED_PARAMS","INLINE_DEVICE_MACRO_REPLACEMENTS","pattern","getValue","ctx","buf","correlator","trimmed","Uint32Array","getRandomValues","String","Number","MAX_SAFE_INTEGER","expandInlineMacroPlaceholders","baseUrl","url","encodeURIComponent","runtimeId","applyDeviceIdentityParams","params","tagRdid","tagLat","latValue","set","tagRdidValid","tagTypeValid","delete","removeBrokenAppNameOrphans","toDelete","push","split","slice","suffix","trimStart","searchParams","normalizeVastTagUrl","raw","URL","anValue","forEach","_value","orphanFragments","length","reconstructed","trimEnd","join","prefix","val","_match","applyVastMacros","expandedUrl","replaceCorrelatorFallback","streamCorrelator","pod","optimizedPodMode","podMaxAds","podMinDurationMs","podMaxDurationMs","max","round","existingUrl","adPosition","requestUrl","pageUrl","adWillPlayMuted","adWillAutoPlay","consent","gdpr","gdprConsent","usPrivacy","adTest","staleKeys","correlatorRegex","sep","includes","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","username","password","topicPrefix","qos","mqttConfig","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","buildPlayerTopic","licenseKey","channel","import_mqtt","require","LOG","client","status","initMQTTClient","clientId","mqtt","connect","keepalive","clean","reconnectPeriod","connectTimeout","queueQoSZero","err","console","warn","on","info","message","ensureMQTTClient","publishMQTT","topic","payload","publish","JSON","stringify","cachedBrowserId","buildAnalyticsContext","config","context","debugAdTiming","isLiveStream","inputStreamType","getClientInfo","screen","platform","vendor","maxTouchPoints","memory","deviceMemory","hardwareConcurrency","width","height","availWidth","availHeight","orientation","type","pixelDepth","deviceType","brand","os","model","isSmartTV","isAndroid","isWebView","isWebApp","webosMatch","match","tizenMatch","tvMatch","androidModelMatch"],"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/player/AdConfigManager.ts\nvar AdConfigManager_exports = {};\n__export(AdConfigManager_exports, {\n  AdConfigManager: () => AdConfigManager\n});\nmodule.exports = __toCommonJS(AdConfigManager_exports);\n\n// src/utils/vastEnvironmentSignals.ts\nvar AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nvar AIRY_WEBOS_APP_ID = \"com.freeairytv.webos\";\nvar AIRY_TIZEN_APP_ID = \"com.freeairytv.samsung\";\nvar AIRY_ROKU_APP_ID = \"com.freeairytv.roku\";\nvar AIRY_APP_NAME = \"AiryTV Movies & TV\";\nvar AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nvar CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\nvar PLAYER_ID_STORAGE_KEY = \"stormcloud.player.id\";\nvar LG_TEST_APP_ID = \"com.hulu.plus\";\nvar LG_TEST_APP_NAME = \"Hulu\";\nvar LG_TEST_CONTENT_URL = \"https://www.hulu.com/live-tv\";\nvar _lgTestDeviceId;\nfunction getLgTestDeviceId() {\n  if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();\n  return _lgTestDeviceId;\n}\nfunction isLgWebOS() {\n  if (typeof navigator === \"undefined\") return false;\n  return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);\n}\nfunction getDefaultAppId() {\n  if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n  const ua = navigator.userAgent;\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n  if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;\n  if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;\n  return AIRY_ANDROID_APP_ID;\n}\nvar DEVICE_ID_STORAGE_KEYS = [\n  \"rdid\",\n  \"ifa\",\n  \"advertisingId\",\n  \"advertising_id\",\n  \"deviceAdvertisingId\",\n  \"aaid\",\n  \"adid\",\n  \"rida\",\n  \"tifa\",\n  \"lgudid\"\n];\nvar ANDROID_ID_TYPES = /* @__PURE__ */ new Set([\"aaid\", \"adid\"]);\nfunction resolveVastEnvironmentSignals(isCtv) {\n  const bridgeSignals = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const lg = isCtv && isLgWebOS();\n  const deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId || (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : void 0);\n  const deviceIdType = bridgeSignals.deviceIdType || readStoredString(\"deviceIdType\") || readStoredString(\"idtype\") || platformDevice.deviceIdType || inferDeviceIdType() || (lg ? \"lgudid\" : void 0);\n  const platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;\n  const limitAdTracking = deviceId != null ? platformLat ?? readStoredLimitAdTracking() ?? false : void 0;\n  if (isCtv) {\n    return {\n      isCtv: true,\n      contentUrl: bridgeSignals.contentUrl || readStoredString(\"contentUrl\") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),\n      appId: bridgeSignals.appId || readStoredString(\"appId\") || readStoredString(\"msid\") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),\n      appName: bridgeSignals.appName || readStoredString(\"appName\") || readStoredString(\"an\") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),\n      sessionId: getOrCreateCtvSessionId(),\n      ...deviceId ? { deviceId } : {},\n      ...deviceIdType ? { deviceIdType } : {},\n      ...limitAdTracking != null ? { limitAdTracking } : {},\n      deviceTypeHint: 5\n    };\n  }\n  return {\n    isCtv: false,\n    ...deviceId ? { deviceId } : {},\n    ...deviceIdType ? { deviceIdType } : {},\n    ...limitAdTracking != null ? { limitAdTracking } : {}\n  };\n}\nfunction inferDeviceIdType() {\n  if (typeof navigator === \"undefined\") {\n    return void 0;\n  }\n  const ua = navigator.userAgent;\n  if (/Roku/i.test(ua)) return \"rida\";\n  if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n  if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n  if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n  if (/Android|Google TV/i.test(ua)) return \"aaid\";\n  if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n  return void 0;\n}\nfunction isEquivalentDeviceIdType(tagType, runtimeType) {\n  if (!tagType || !runtimeType) return false;\n  const tag = tagType.toLowerCase();\n  const runtime = runtimeType.toLowerCase();\n  if (tag === runtime) return true;\n  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\nfunction resolveNativeDeviceId() {\n  const bridgeSignals = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;\n  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {\n    return void 0;\n  }\n  return deviceId;\n}\nfunction getOrCreateStoredUuid(storageKey) {\n  if (typeof window === \"undefined\") {\n    return void 0;\n  }\n  const existing = readStoredString(storageKey);\n  if (existing) {\n    return existing;\n  }\n  const id = createUuid();\n  try {\n    window.localStorage?.setItem(storageKey, id);\n  } catch {\n  }\n  return id;\n}\nfunction getOrCreateCtvSessionId() {\n  const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n  if (existing) {\n    return existing;\n  }\n  const sessionId = createUuid();\n  try {\n    window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n  } catch {\n  }\n  return sessionId;\n}\nfunction createUuid() {\n  if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n  return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n    const value = Math.floor(Math.random() * 16);\n    const nibble = char === \"x\" ? value : value & 3 | 8;\n    return nibble.toString(16);\n  });\n}\nfunction readPlatformNativeDeviceId() {\n  if (typeof window === \"undefined\") return {};\n  try {\n    const adinfo = window.webapis?.adinfo;\n    if (adinfo) {\n      const tifa = typeof adinfo.getTIFA === \"function\" ? adinfo.getTIFA() : adinfo.tifa;\n      if (typeof tifa === \"string\" && tifa && !isMacroPlaceholder(tifa)) {\n        const lat = typeof adinfo.isLATEnabled === \"function\" ? adinfo.isLATEnabled() : void 0;\n        return {\n          deviceId: tifa,\n          deviceIdType: \"tifa\",\n          ...typeof lat === \"boolean\" ? { limitAdTracking: lat } : {}\n        };\n      }\n    }\n  } catch {\n  }\n  try {\n    const webOSDev = window.webOSDev;\n    if (webOSDev) {\n      const lgudid = typeof webOSDev.LGUDID === \"function\" ? webOSDev.LGUDID() : webOSDev.lgudid ?? webOSDev.LGUDID;\n      if (typeof lgudid === \"string\" && lgudid) {\n        if (isZeroedAdId(lgudid)) {\n          return { deviceIdType: \"lgudid\", limitAdTracking: true };\n        }\n        if (!isMacroPlaceholder(lgudid)) {\n          return { deviceId: lgudid, deviceIdType: \"lgudid\", limitAdTracking: false };\n        }\n      }\n    }\n  } catch {\n  }\n  try {\n    const roku = window.Roku;\n    if (roku) {\n      const rida = typeof roku.getPublisherUniqueId === \"function\" ? roku.getPublisherUniqueId() : roku.rida;\n      if (typeof rida === \"string\" && rida && !isMacroPlaceholder(rida)) {\n        return { deviceId: rida, deviceIdType: \"rida\", limitAdTracking: false };\n      }\n    }\n  } catch {\n  }\n  return {};\n}\nvar ZEROED_AD_ID_PATTERNS = /* @__PURE__ */ new Set([\n  \"38400000-8cf0-11bd-b23e-10b96e40000d\",\n  \"00000000-0000-0000-0000-000000000000\"\n]);\nfunction isMacroPlaceholder(value) {\n  const t = value.trim();\n  return !t || /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());\n}\nfunction isZeroedAdId(value) {\n  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());\n}\nfunction readNativeBridgeSignals() {\n  if (typeof window === \"undefined\") {\n    return {};\n  }\n  const candidates = [\n    window.__STORMCLOUD_CTV_AD_INFO__,\n    window.__STORMCLOUD_CTV__,\n    window.stormcloudCtv,\n    window.AiryTV,\n    window.Android,\n    window.webOS,\n    window.tizen,\n    window.amazon\n  ].filter(Boolean);\n  for (const source of candidates) {\n    const contentUrl = readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) || void 0;\n    const appId = readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) || void 0;\n    const appName = readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || void 0;\n    const deviceId = readBridgeValue(source, [\n      \"rdid\",\n      \"ifa\",\n      \"advertisingId\",\n      \"adId\",\n      \"deviceId\",\n      \"lgudid\",\n      \"LGUDID\",\n      \"tifa\",\n      \"rida\",\n      \"afai\",\n      \"aaid\"\n    ]) || void 0;\n    if (!contentUrl && !deviceId && !appId && !appName) continue;\n    const deviceIdType = readBridgeValue(source, [\n      \"idtype\",\n      \"deviceIdType\",\n      \"advertisingIdType\",\n      \"idType\"\n    ]) || inferDeviceIdType();\n    const limitAdTracking = readBridgeBoolean(source, [\n      \"is_lat\",\n      \"limitAdTracking\",\n      \"limitedAdTracking\",\n      \"lat\"\n    ]);\n    return {\n      ...contentUrl ? { contentUrl } : {},\n      ...appId ? { appId } : {},\n      ...appName ? { appName } : {},\n      ...deviceId ? { deviceId } : {},\n      ...deviceId && deviceIdType ? { deviceIdType } : {},\n      ...deviceId && limitAdTracking != null ? { limitAdTracking } : {}\n    };\n  }\n  return {};\n}\nfunction readBridgeValue(source, keys) {\n  for (const key of keys) {\n    const value = source?.[key];\n    if (typeof value === \"string\" && value) {\n      return value;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = value.call(source);\n        if (typeof result === \"string\" && result) {\n          return result;\n        }\n      } catch {\n      }\n    }\n  }\n  return void 0;\n}\nfunction readBridgeBoolean(source, keys) {\n  for (const key of keys) {\n    const value = source?.[key];\n    const normalized = normalizeBoolean(value);\n    if (normalized != null) {\n      return normalized;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = normalizeBoolean(value.call(source));\n        if (result != null) {\n          return result;\n        }\n      } catch {\n      }\n    }\n  }\n  return void 0;\n}\nfunction readStoredDeviceId() {\n  for (const key of DEVICE_ID_STORAGE_KEYS) {\n    const value = readStoredString(key);\n    if (value) {\n      return value;\n    }\n  }\n  return void 0;\n}\nfunction readStoredString(key) {\n  if (typeof window === \"undefined\") {\n    return void 0;\n  }\n  try {\n    const value = window.localStorage?.getItem(key);\n    return value || void 0;\n  } catch {\n    return void 0;\n  }\n}\nfunction readStoredLimitAdTracking() {\n  return normalizeBoolean(\n    readStoredString(\"limitAdTracking\") || readStoredString(\"limitedAdTracking\") || readStoredString(\"is_lat\")\n  );\n}\nfunction normalizeBoolean(value) {\n  if (typeof value === \"boolean\") {\n    return value;\n  }\n  if (typeof value === \"number\") {\n    return value === 1;\n  }\n  if (typeof value === \"string\") {\n    const normalized = value.toLowerCase();\n    if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n      return true;\n    }\n    if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n      return false;\n    }\n  }\n  return void 0;\n}\n\n// src/utils/vastMacros.ts\nvar UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nvar INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nvar EXAMPLE_COM_URL = /example\\.com/i;\nvar CTV_UNSUPPORTED_PARAMS = [\n  \"description_url\",\n  \"tfcd\",\n  \"npa\",\n  \"min_ad_duration\",\n  \"max_ad_duration\",\n  \"unviewed_position_start\",\n  \"impl\",\n  \"vad_type\",\n  \"gdpr\",\n  \"gdpr_consent\",\n  \"us_privacy\"\n];\nvar INLINE_DEVICE_MACRO_REPLACEMENTS = [\n  { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n  { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) => ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0 },\n  { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n  { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n  { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n  { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator }\n];\nfunction isMacroPlaceholder2(value) {\n  if (value == null) return true;\n  const trimmed = value.trim();\n  if (!trimmed) return true;\n  if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n  return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\nfunction generateCorrelator() {\n  if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n    try {\n      const buf = new Uint32Array(2);\n      crypto.getRandomValues(buf);\n      const value = (buf[0] ?? 0) * 2097152 + ((buf[1] ?? 0) & 2097151);\n      if (value > 0) {\n        return String(value);\n      }\n    } catch {\n    }\n  }\n  return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\nfunction expandInlineMacroPlaceholders(baseUrl, ctx) {\n  let url = baseUrl;\n  for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n    const value = getValue(ctx);\n    if (value != null && value !== \"\") {\n      url = url.replace(pattern, encodeURIComponent(value));\n    }\n  }\n  return url;\n}\nfunction applyDeviceIdentityParams(params, ctx) {\n  const runtimeId = ctx.deviceId?.trim();\n  const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n  const tagRdid = params.get(\"rdid\");\n  const tagType = params.get(\"idtype\");\n  const tagLat = params.get(\"is_lat\");\n  const latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? \"1\" : \"0\" : void 0;\n  if (runtimeId) {\n    params.set(\"rdid\", runtimeId);\n    params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n    params.set(\"is_lat\", latValue ?? (isMacroPlaceholder2(tagLat) ? \"0\" : tagLat));\n    return;\n  }\n  const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));\n  const tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));\n  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {\n    params.delete(\"rdid\");\n    params.delete(\"idtype\");\n    params.delete(\"is_lat\");\n    return;\n  }\n  if (tagRdidValid) {\n    if (isMacroPlaceholder2(tagType) && runtimeType) {\n      params.set(\"idtype\", runtimeType);\n    }\n    if (isMacroPlaceholder2(tagLat)) {\n      params.set(\"is_lat\", latValue ?? \"0\");\n    }\n    return;\n  }\n  params.delete(\"rdid\");\n  params.delete(\"idtype\");\n  params.delete(\"is_lat\");\n}\nfunction removeBrokenAppNameOrphans(params, appName) {\n  const toDelete = [];\n  params.forEach((_value, key) => {\n    if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n      toDelete.push(key);\n    }\n  });\n  if (appName && appName.includes(\"&\")) {\n    for (const suffix of appName.split(\"&\").slice(1)) {\n      const trimmed = suffix.trimStart();\n      if (!trimmed) continue;\n      toDelete.push(suffix, ` ${trimmed}`, trimmed);\n    }\n  }\n  for (const key of new Set(toDelete)) {\n    if (key) params.delete(key);\n  }\n}\nfunction normalizeVastTagUrl(raw) {\n  if (!raw) return raw;\n  try {\n    const url = new URL(raw);\n    const anValue = url.searchParams.get(\"an\");\n    if (anValue !== null) {\n      const orphanFragments = [];\n      url.searchParams.forEach((_value, key) => {\n        if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n          orphanFragments.push(key.trim());\n        }\n      });\n      if (orphanFragments.length > 0) {\n        const reconstructed = [anValue.trimEnd(), ...orphanFragments].filter(Boolean).join(\" & \");\n        url.searchParams.forEach((_value, key) => {\n          if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n            url.searchParams.delete(key);\n          }\n        });\n        url.searchParams.set(\"an\", reconstructed);\n        return url.toString().replace(\n          /([?&]an=)([^&]*)/,\n          (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n        );\n      }\n    }\n    removeBrokenAppNameOrphans(url.searchParams);\n    return url.toString();\n  } catch {\n    return raw;\n  }\n}\nfunction applyVastMacros(baseUrl, ctx) {\n  const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n  let url;\n  try {\n    url = new URL(normalizeVastTagUrl(expandedUrl));\n  } catch {\n    return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n  }\n  const params = url.searchParams;\n  removeBrokenAppNameOrphans(params, ctx.appName);\n  params.set(\"correlator\", ctx.correlator);\n  params.set(\"scor\", ctx.streamCorrelator);\n  if (ctx.isCtv) {\n    for (const key of CTV_UNSUPPORTED_PARAMS) {\n      params.delete(key);\n    }\n  }\n  if (ctx.pod != null) {\n    params.set(\"pod\", String(ctx.pod));\n  }\n  const optimizedPodMode = ctx.podMaxAds != null || ctx.podMinDurationMs != null || ctx.podMaxDurationMs != null;\n  if (optimizedPodMode) {\n    params.delete(\"ppos\");\n    params.delete(\"lip\");\n    if (ctx.podMinDurationMs != null) {\n      params.set(\"pmnd\", String(Math.max(0, Math.round(ctx.podMinDurationMs))));\n    }\n    if (ctx.podMaxDurationMs != null) {\n      params.set(\"pmxd\", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));\n    }\n    if (ctx.podMaxAds != null) {\n      params.set(\"pmad\", String(Math.max(1, Math.round(ctx.podMaxAds))));\n    }\n  } else if (ctx.adPosition != null) {\n    params.set(\"ppos\", String(ctx.adPosition));\n  }\n  const requestUrl = ctx.contentUrl || ctx.pageUrl;\n  if (requestUrl) {\n    params.set(\"url\", requestUrl);\n    if (!ctx.isCtv) {\n      params.set(\"description_url\", requestUrl);\n    }\n  } else {\n    const existingUrl = params.get(\"url\") || \"\";\n    if (EXAMPLE_COM_URL.test(existingUrl)) {\n      params.delete(\"url\");\n      params.delete(\"description_url\");\n    }\n  }\n  if (ctx.adWillPlayMuted != null) {\n    params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n  }\n  if (ctx.adWillAutoPlay != null) {\n    params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n  }\n  if (ctx.appId) {\n    params.set(\"msid\", ctx.appId);\n  }\n  if (ctx.appName) {\n    removeBrokenAppNameOrphans(params, ctx.appName);\n    params.set(\"an\", ctx.appName);\n  }\n  if (ctx.sessionId) {\n    params.set(\"sid\", ctx.sessionId);\n  }\n  if (ctx.deviceTypeHint != null) {\n    params.set(\"dth\", String(ctx.deviceTypeHint));\n  } else if (ctx.isCtv) {\n    params.set(\"dth\", \"5\");\n  }\n  applyDeviceIdentityParams(params, ctx);\n  if (!ctx.isCtv) {\n    const consent = ctx.consent;\n    if (consent?.gdpr != null) {\n      params.set(\"gdpr\", consent.gdpr);\n    }\n    if (consent?.gdprConsent != null) {\n      params.set(\"gdpr_consent\", consent.gdprConsent);\n    }\n    if (consent?.usPrivacy != null) {\n      params.set(\"us_privacy\", consent.usPrivacy);\n    }\n  }\n  if (ctx.adTest) {\n    params.set(\"adtest\", \"on\");\n  }\n  const staleKeys = [];\n  params.forEach((value, key) => {\n    if (isMacroPlaceholder2(value)) {\n      staleKeys.push(key);\n    }\n  });\n  for (const key of staleKeys) {\n    params.delete(key);\n  }\n  removeBrokenAppNameOrphans(params, ctx.appName);\n  return url.toString();\n}\nfunction replaceCorrelatorFallback(baseUrl, correlator) {\n  const correlatorRegex = /([?&])correlator=([^&]*)/;\n  if (correlatorRegex.test(baseUrl)) {\n    return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n  }\n  const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n  return `${baseUrl}${sep}correlator=${correlator}`;\n}\n\n// src/utils/mqttConfig.ts\nvar DEFAULT_MQTT_CONFIG = {\n  enabled: true,\n  brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n  brokerPort: 8883,\n  wsPort: 8084,\n  username: \"for-sonifi\",\n  password: \"sonifi-mqtt\",\n  topicPrefix: \"adstorm/players\",\n  qos: 1\n};\nvar mqttConfig = { ...DEFAULT_MQTT_CONFIG };\nfunction isMQTTEnabled() {\n  return mqttConfig.enabled;\n}\nfunction buildMQTTBrokerUrl() {\n  if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n  return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\nfunction buildPlayerTopic(licenseKey, channel) {\n  return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n\n// src/utils/mqttClient.ts\nvar import_mqtt = __toESM(require(\"mqtt\"), 1);\nvar LOG = \"[StormcloudVideoPlayer][MQTT]\";\nvar client = null;\nvar status = \"disconnected\";\nfunction initMQTTClient() {\n  if (client || !isMQTTEnabled()) return;\n  const url = buildMQTTBrokerUrl();\n  status = \"connecting\";\n  const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n  try {\n    client = import_mqtt.default.connect(url, {\n      clientId,\n      username: mqttConfig.username,\n      password: mqttConfig.password,\n      keepalive: 60,\n      clean: true,\n      reconnectPeriod: 5e3,\n      connectTimeout: 1e4,\n      queueQoSZero: false\n    });\n  } catch (err) {\n    status = \"error\";\n    console.warn(`${LOG} connect() threw:`, err);\n    return;\n  }\n  client.on(\"connect\", () => {\n    status = \"connected\";\n    console.info(`${LOG} connected to ${url}`);\n  });\n  client.on(\"reconnect\", () => {\n    status = \"connecting\";\n    console.info(`${LOG} reconnecting\\u2026`);\n  });\n  client.on(\"offline\", () => {\n    status = \"disconnected\";\n    console.warn(`${LOG} offline`);\n  });\n  client.on(\"error\", (err) => {\n    status = \"error\";\n    console.warn(`${LOG} error:`, err.message);\n  });\n  client.on(\"close\", () => {\n    if (status === \"connected\") {\n      status = \"disconnected\";\n    }\n  });\n}\nfunction ensureMQTTClient() {\n  if (isMQTTEnabled() && !client) {\n    initMQTTClient();\n  }\n}\nfunction publishMQTT(topic, payload) {\n  if (!isMQTTEnabled()) {\n    return false;\n  }\n  ensureMQTTClient();\n  if (!client) {\n    return false;\n  }\n  try {\n    client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n    return true;\n  } catch (err) {\n    console.warn(`${LOG} publish failed on ${topic}:`, err);\n    return false;\n  }\n}\n\n// src/utils/tracking.ts\nvar cachedBrowserId = null;\nfunction buildAnalyticsContext(config) {\n  const context = {};\n  if (config.debugAdTiming) {\n    context.debugAdTiming = true;\n  }\n  if (config.isLiveStream !== void 0) {\n    context.inputStreamType = config.isLiveStream ? \"live\" : \"vod\";\n  }\n  return context;\n}\nfunction getClientInfo() {\n  const ua = navigator.userAgent;\n  const platform = navigator.platform;\n  const vendor = navigator.vendor || \"\";\n  const maxTouchPoints = navigator.maxTouchPoints || 0;\n  const memory = navigator.deviceMemory || null;\n  const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n  const screenInfo = {\n    width: screen?.width,\n    height: screen?.height,\n    availWidth: screen?.availWidth,\n    availHeight: screen?.availHeight,\n    orientation: screen?.orientation?.type || \"\",\n    pixelDepth: screen?.pixelDepth\n  };\n  let deviceType = \"desktop\";\n  let brand = \"Unknown\";\n  let os = \"Unknown\";\n  let model = \"\";\n  let isSmartTV = false;\n  let isAndroid = false;\n  let isWebView = false;\n  let isWebApp = false;\n  if (ua.includes(\"Web0S\")) {\n    brand = \"LG\";\n    os = \"webOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n    model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n  } else if (ua.includes(\"Tizen\")) {\n    brand = \"Samsung\";\n    os = \"Tizen\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n    const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n    model = tizenMatch ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim() : \"Tizen TV\";\n  } else if (ua.includes(\"Philips\")) {\n    brand = \"Philips\";\n    os = \"Saphi\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n    brand = \"Sharp\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Android\") && (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))) {\n    brand = \"Sony\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Android\") && (ua.includes(\"NetCast\") || ua.includes(\"LG\"))) {\n    brand = \"LG\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n    brand = \"Roku\";\n    os = \"Roku OS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"AppleTV\")) {\n    brand = \"Apple\";\n    os = \"tvOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  }\n  if (ua.includes(\"Android\")) {\n    isAndroid = true;\n    os = \"Android\";\n    deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n    if (ua.includes(\"Android\") && (maxTouchPoints === 0 || ua.includes(\"Google TV\") || ua.includes(\"XiaoMi\"))) {\n      deviceType = \"tv\";\n      isSmartTV = true;\n      brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n    }\n    const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n    if (androidModelMatch && androidModelMatch[1]) {\n      model = androidModelMatch[1];\n    }\n  }\n  if (/iPad|iPhone|iPod/.test(ua)) {\n    os = \"iOS\";\n    deviceType = \"mobile\";\n    brand = \"Apple\";\n    if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n      deviceType = \"tablet\";\n    }\n  }\n  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n    if (ua.includes(\"Windows\")) {\n      os = \"Windows\";\n      deviceType = \"desktop\";\n    } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n      os = \"macOS\";\n      deviceType = \"desktop\";\n      if (maxTouchPoints > 1) deviceType = \"tablet\";\n    } else if (ua.includes(\"Linux\")) {\n      os = \"Linux\";\n      deviceType = \"desktop\";\n    }\n  }\n  if (brand === \"Unknown\") {\n    if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n    if (vendor.includes(\"Apple\")) brand = \"Apple\";\n    if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n  }\n  isWebView = /wv|WebView|Linux; U;/.test(ua);\n  if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n    isWebView = true;\n  }\n  isWebApp = window.matchMedia(\"(display-mode: standalone)\").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;\n  return {\n    brand,\n    os,\n    model: model || ua.substring(0, 50) + \"...\",\n    deviceType,\n    isSmartTV,\n    isAndroid,\n    isWebView,\n    isWebApp,\n    domain: window.location.hostname,\n    origin: window.location.origin,\n    path: window.location.pathname,\n    userAgent: ua,\n    vendor,\n    platform,\n    screen: screenInfo,\n    hardwareConcurrency,\n    deviceMemory: memory,\n    maxTouchPoints,\n    language: navigator.language,\n    languages: navigator.languages?.join(\",\") || \"\",\n    cookieEnabled: navigator.cookieEnabled,\n    doNotTrack: navigator.doNotTrack || \"\",\n    referrer: document.referrer,\n    visibilityState: document.visibilityState\n  };\n}\nasync function sha256Hex(input) {\n  if (typeof crypto !== \"undefined\" && crypto.subtle?.digest) {\n    try {\n      await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n      let encodedData;\n      if (typeof TextEncoder !== \"undefined\") {\n        encodedData = new TextEncoder().encode(input);\n      } else {\n        const utf8 = unescape(encodeURIComponent(input));\n        const buffer = new Uint8Array(utf8.length);\n        for (let i = 0; i < utf8.length; i++) {\n          buffer[i] = utf8.charCodeAt(i);\n        }\n        encodedData = buffer;\n      }\n      const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n      return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n    } catch {\n      console.warn(\n        \"[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash\"\n      );\n    }\n  }\n  let hash = 0;\n  for (let i = 0; i < input.length; i++) {\n    const char = input.charCodeAt(i);\n    hash = (hash << 5) - hash + char;\n    hash = hash & hash;\n  }\n  const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n  const timestamp = Date.now().toString(16).padStart(12, \"0\");\n  const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n  return (fallbackHash + timestamp + random).padEnd(64, \"0\");\n}\nfunction resolvePlayerIdentitySeed(clientInfo) {\n  const nativeDeviceId = resolveNativeDeviceId();\n  if (nativeDeviceId) {\n    return `device:${nativeDeviceId}`;\n  }\n  const persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);\n  if (persistedId) {\n    return `persisted:${persistedId}`;\n  }\n  return `fingerprint:${JSON.stringify(clientInfo)}`;\n}\nasync function getBrowserID(clientInfo) {\n  if (cachedBrowserId) {\n    return cachedBrowserId;\n  }\n  cachedBrowserId = await sha256Hex(resolvePlayerIdentitySeed(clientInfo));\n  return cachedBrowserId;\n}\nfunction canPublish(licenseKey) {\n  return Boolean(isMQTTEnabled() && licenseKey);\n}\nasync function buildPlayerMetricEvent(context = {}, flags = {}) {\n  const clientInfo = getClientInfo();\n  const debugAdTiming = !!context.debugAdTiming;\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] clientInfo: \", JSON.stringify(clientInfo, null, 2));\n  }\n  const playerId = await getBrowserID(clientInfo);\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] playerId: \", playerId);\n  }\n  const captureAt = flags.captureAt ?? (/* @__PURE__ */ new Date()).toISOString();\n  return {\n    player_id: playerId,\n    device_type: clientInfo.deviceType,\n    os: clientInfo.os.toLowerCase(),\n    ad_loaded: flags.adLoaded ?? false,\n    ad_detect: flags.adDetect ?? false,\n    capture_at: captureAt,\n    ...context.inputStreamType ? { input_stream_type: context.inputStreamType } : {}\n  };\n}\nfunction publishTracking(licenseKey, channel, body) {\n  ensureMQTTClient();\n  publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\nasync function sendInitialTracking(licenseKey, context = {}) {\n  if (!canPublish(licenseKey)) return;\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      adLoaded: false,\n      adDetect: false\n    });\n    publishTracking(licenseKey, \"metrics\", {\n      events: [metricEvent]\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n      error\n    );\n  }\n}\nasync function sendHeartbeat(licenseKey, context = {}, flags = {}) {\n  if (!canPublish(licenseKey)) return;\n  try {\n    const heartbeatData = await buildPlayerMetricEvent(context, flags);\n    publishTracking(licenseKey, \"heartbeat\", heartbeatData);\n  } catch (error) {\n    console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n  }\n}\n\n// src/player/AdConfigManager.ts\nvar AdConfigManager = class {\n  constructor(config, video) {\n    this.vmapBreaks = [];\n    this.consumedVmapBreakIds = /* @__PURE__ */ new Set();\n    this.streamCorrelator = generateCorrelator();\n    this.consentSignals = {};\n    this.podCounter = 0;\n    this.podAssignedByPrefetch = false;\n    this.adRequestPositionInBreak = 0;\n    this.lastHeartbeatTime = 0;\n    this.defaultPodMaxAds = 6;\n    this.config = config;\n    this.video = video;\n  }\n  get debug() {\n    return !!this.config.debugAdTiming;\n  }\n  isVmapEnabled() {\n    return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n  }\n  async fetchAdConfiguration() {\n    if (this.isVmapEnabled()) {\n      await this.fetchAndParseVmap(this.config.vmapUrl);\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n      }\n      return;\n    }\n    const vastMode = this.config.vastMode || \"default\";\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n    }\n    if (vastMode === \"adstorm\") {\n      if (!this.config.licenseKey) {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n          );\n        }\n        return;\n      }\n      const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n      this.apiVastTagUrl = vastEndpoint;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n          vastEndpoint\n        );\n      }\n      return;\n    }\n    if (this.config.vastTagUrl) {\n      this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n      return;\n    }\n    const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n    if (this.debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n        apiUrl\n      );\n    }\n    const headers = {};\n    if (this.config.licenseKey) {\n      headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n    }\n    const response = await fetch(apiUrl, { headers });\n    if (!response.ok) {\n      if (this.debug) {\n        console.warn(\n          `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n        );\n      }\n      return;\n    }\n    const data = await response.json();\n    const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n    if (imaPayload) {\n      let decodedPayload = imaPayload;\n      try {\n        decodedPayload = decodeURIComponent(imaPayload);\n      } catch {\n        console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n      }\n      console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n      this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n    } else {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n        );\n      }\n    }\n    const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n    if (numberAds != null && numberAds > 0) {\n      this.apiNumberAds = numberAds;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n          this.apiNumberAds\n        );\n      }\n    }\n  }\n  async fetchAndParseVmap(vmapUrl) {\n    if (!vmapUrl.trim()) {\n      return;\n    }\n    try {\n      const response = await fetch(vmapUrl);\n      if (!response.ok) {\n        throw new Error(`Failed to fetch VMAP (${response.status})`);\n      }\n      const vmapXml = await response.text();\n      this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n      this.consumedVmapBreakIds.clear();\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n          vmapUrl\n        );\n      }\n    } catch (error) {\n      this.vmapBreaks = [];\n      this.consumedVmapBreakIds.clear();\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n      }\n    }\n  }\n  parseVmapToBreaks(vmapXml) {\n    if (typeof DOMParser === \"undefined\") {\n      return [];\n    }\n    const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n    if (doc.querySelector(\"parsererror\")) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n      }\n      return [];\n    }\n    const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n    let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(\n        doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n      );\n    }\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n        (el) => el.localName === \"AdBreak\"\n      );\n    }\n    const parsed = [];\n    adBreakNodes.forEach((node, index) => {\n      const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n      const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n      if (startTimeMs == null) {\n        return;\n      }\n      let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n      if (!adTagNode) {\n        adTagNode = node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") ?? void 0;\n      }\n      const adTagUrl = (adTagNode?.textContent || \"\").trim();\n      if (!adTagUrl) {\n        return;\n      }\n      const breakId = node.getAttribute(\"breakId\") || `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n      parsed.push({\n        id: breakId,\n        startTimeMs,\n        vastTagUrl: adTagUrl\n      });\n    });\n    parsed.sort((a, b) => {\n      const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n      const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n      return aStart - bStart;\n    });\n    return parsed;\n  }\n  parseVmapTimeOffsetToMs(timeOffset) {\n    if (!timeOffset) {\n      return void 0;\n    }\n    const normalized = timeOffset.trim().toLowerCase();\n    if (normalized === \"start\") {\n      return 0;\n    }\n    if (normalized === \"end\") {\n      return -1;\n    }\n    const hms = timeOffset.match(\n      /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n    );\n    if (hms) {\n      const [, hh, mm, ss, ms = \"0\"] = hms;\n      const hours = Number(hh);\n      const minutes = Number(mm);\n      const seconds = Number(ss);\n      const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n      return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;\n    }\n    const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n    if (percent) {\n      const ratio = Number(percent[1]) / 100;\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1e3 * ratio);\n      }\n      return void 0;\n    }\n    return void 0;\n  }\n  getAdBreakKey(adBreak) {\n    if (adBreak.id) {\n      return adBreak.id;\n    }\n    return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n  }\n  resolveBreakStartMs(adBreak) {\n    if (adBreak.startTimeMs >= 0) {\n      return adBreak.startTimeMs;\n    }\n    if (adBreak.startTimeMs === -1) {\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1e3);\n      }\n    }\n    return void 0;\n  }\n  findCurrentOrNextBreak(nowMs) {\n    const schedule = this.vmapBreaks;\n    let candidate;\n    const tol = this.config.driftToleranceMs ?? 1e3;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n      if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))) {\n        candidate = b;\n      }\n    }\n    return candidate;\n  }\n  findBreakForTime(nowMs) {\n    const schedule = this.vmapBreaks;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n      if (b.durationMs) {\n        const end = breakStartMs + b.durationMs;\n        if (nowMs >= breakStartMs && nowMs < end) {\n          return b;\n        }\n        continue;\n      }\n      if (nowMs >= breakStartMs) {\n        return b;\n      }\n    }\n    return void 0;\n  }\n  selectVastTagsForBreak(b) {\n    if (!b || !b.vastTagUrl) return void 0;\n    if (b.vastTagUrl.includes(\",\")) {\n      return b.vastTagUrl.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n    }\n    return [b.vastTagUrl];\n  }\n  beginNewAdPod() {\n    this.podCounter++;\n    this.adRequestPositionInBreak = 0;\n  }\n  generateVastUrlsWithCorrelators(baseUrl, count, adPlayer, palNonce, inAdBreak) {\n    const urls = [];\n    for (let i = 0; i < count; i++) {\n      this.adRequestPositionInBreak++;\n      const adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;\n      const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n      const urlWithMacros = applyVastMacros(baseUrl, {\n        correlator: generateCorrelator(),\n        streamCorrelator: this.streamCorrelator,\n        pod: this.podCounter > 0 ? this.podCounter : void 0,\n        adPosition: this.adRequestPositionInBreak,\n        isCtv: envSignals.isCtv,\n        contentUrl: envSignals.contentUrl,\n        pageUrl: !envSignals.isCtv && typeof window !== \"undefined\" ? window.location.href : void 0,\n        adWillPlayMuted,\n        adWillAutoPlay: !!this.config.autoplay,\n        appId: envSignals.appId,\n        appName: envSignals.appName,\n        sessionId: envSignals.sessionId,\n        deviceId: envSignals.deviceId,\n        deviceIdType: envSignals.deviceIdType,\n        limitAdTracking: envSignals.limitAdTracking,\n        deviceTypeHint: envSignals.deviceTypeHint,\n        adTest: this.config.adTest,\n        consent: this.consentSignals\n      });\n      const finalUrl = palNonce.injectNonce(urlWithMacros);\n      console.log(\n        `[StormcloudVideoPlayer] Resolved ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n        finalUrl\n      );\n      urls.push(finalUrl);\n    }\n    return urls;\n  }\n  resolvePodParams(breakDurationMs) {\n    const maxDurationMs = breakDurationMs != null && breakDurationMs > 0 ? breakDurationMs : this.config.podMaxDurationMs;\n    const maxAds = this.config.podMaxAds && this.config.podMaxAds > 0 ? this.config.podMaxAds : this.apiNumberAds && this.apiNumberAds > 0 ? this.apiNumberAds : this.defaultPodMaxAds;\n    const minDurationMs = this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;\n    return { maxAds, minDurationMs, maxDurationMs };\n  }\n  generatePodVastUrl(baseUrl, podParams, adPlayer, palNonce, inAdBreak) {\n    const adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;\n    const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n    const urlWithMacros = applyVastMacros(baseUrl, {\n      correlator: generateCorrelator(),\n      streamCorrelator: this.streamCorrelator,\n      pod: this.podCounter > 0 ? this.podCounter : void 0,\n      podMaxAds: podParams.maxAds,\n      podMinDurationMs: podParams.minDurationMs,\n      podMaxDurationMs: podParams.maxDurationMs,\n      isCtv: envSignals.isCtv,\n      contentUrl: envSignals.contentUrl,\n      pageUrl: !envSignals.isCtv && typeof window !== \"undefined\" ? window.location.href : void 0,\n      adWillPlayMuted,\n      adWillAutoPlay: !!this.config.autoplay,\n      appId: envSignals.appId,\n      appName: envSignals.appName,\n      sessionId: envSignals.sessionId,\n      deviceId: envSignals.deviceId,\n      deviceIdType: envSignals.deviceIdType,\n      limitAdTracking: envSignals.limitAdTracking,\n      deviceTypeHint: envSignals.deviceTypeHint,\n      adTest: this.config.adTest,\n      consent: this.consentSignals\n    });\n    const finalUrl = palNonce.injectNonce(urlWithMacros);\n    console.log(\n      `[StormcloudVideoPlayer] Resolved optimized-pod request URL (pod=${this.podCounter}, pmad=${podParams.maxAds}, pmnd=${podParams.minDurationMs}, pmxd=${podParams.maxDurationMs ?? \"?\"}):`,\n      finalUrl\n    );\n    return finalUrl;\n  }\n  // --- Tracking ---\n  initializeTracking() {\n    sendInitialTracking(this.config.licenseKey, buildAnalyticsContext(this.config)).then(() => {\n      this.heartbeatInterval = window.setInterval(() => {\n        this.sendHeartbeatIfNeeded();\n      }, 5e3);\n    }).catch((error) => {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n          error\n        );\n      }\n      this.heartbeatInterval = window.setInterval(() => {\n        this.sendHeartbeatIfNeeded();\n      }, 5e3);\n    });\n  }\n  sendHeartbeatIfNeeded() {\n    const now = Date.now();\n    if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {\n      this.lastHeartbeatTime = now;\n      sendHeartbeat(this.config.licenseKey, buildAnalyticsContext(this.config)).catch((error) => {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n            error\n          );\n        }\n      });\n    }\n  }\n  destroyTracking() {\n    if (this.heartbeatInterval) {\n      clearInterval(this.heartbeatInterval);\n      this.heartbeatInterval = void 0;\n    }\n  }\n};\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n  AdConfigManager\n});\n","import type {\n  StormcloudVideoPlayerConfig,\n  AdBreak,\n  StormcloudApiResponse,\n  AdController,\n} from \"../types\";\nimport type { PalNonceManager } from \"../sdk/pal\";\nimport { applyVastMacros, generateCorrelator, normalizeVastTagUrl } from \"../utils/vastMacros\";\nimport type { VastConsentSignals } from \"../utils/vastMacros\";\nimport { resolveVastEnvironmentSignals } from \"../utils/vastEnvironmentSignals\";\nimport {\n  buildAnalyticsContext,\n  sendHeartbeat,\n  sendInitialTracking,\n} from \"../utils/tracking\";\n\nexport class AdConfigManager {\n  vmapBreaks: AdBreak[] = [];\n  consumedVmapBreakIds: Set<string> = new Set();\n  apiVastTagUrl: string | undefined;\n  apiNumberAds: number | undefined;\n  readonly streamCorrelator: string = generateCorrelator();\n  consentSignals: VastConsentSignals = {};\n  podCounter: number = 0;\n  podAssignedByPrefetch: boolean = false;\n  adRequestPositionInBreak: number = 0;\n\n  private lastHeartbeatTime: number = 0;\n  private heartbeatInterval: number | undefined;\n\n  private config: StormcloudVideoPlayerConfig;\n  private video: HTMLVideoElement;\n\n  constructor(config: StormcloudVideoPlayerConfig, video: HTMLVideoElement) {\n    this.config = config;\n    this.video = video;\n  }\n\n  get debug(): boolean {\n    return !!this.config.debugAdTiming;\n  }\n\n  isVmapEnabled(): boolean {\n    return !!(this.config.isVmap && this.config.vmapUrl?.trim());\n  }\n\n  async fetchAdConfiguration(): Promise<void> {\n    if (this.isVmapEnabled()) {\n      await this.fetchAndParseVmap(this.config.vmapUrl!);\n      if (this.debug) {\n        console.log(\"[StormcloudVideoPlayer] VMAP mode enabled\");\n      }\n      return;\n    }\n\n    const vastMode = this.config.vastMode || \"default\";\n\n    if (this.debug) {\n      console.log(\"[StormcloudVideoPlayer] VAST mode:\", vastMode);\n    }\n\n    if (vastMode === \"adstorm\") {\n      if (!this.config.licenseKey) {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] AdStorm mode requires a license key\"\n          );\n        }\n        return;\n      }\n\n      const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;\n      this.apiVastTagUrl = vastEndpoint;\n\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):\",\n          vastEndpoint\n        );\n      }\n      return;\n    }\n\n    if (this.config.vastTagUrl) {\n      this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Using custom VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n      return;\n    }\n\n    const apiUrl = \"https://adstorm.co/api-adstorm-dev/adstorm/ads/web\";\n\n    if (this.debug) {\n      console.log(\n        \"[StormcloudVideoPlayer] Fetching ad configuration from:\",\n        apiUrl\n      );\n    }\n\n    const headers: Record<string, string> = {};\n    if (this.config.licenseKey) {\n      headers[\"Authorization\"] = `Bearer ${this.config.licenseKey}`;\n    }\n\n    const response = await fetch(apiUrl, { headers });\n    if (!response.ok) {\n      if (this.debug) {\n        console.warn(\n          `[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`\n        );\n      }\n      return;\n    }\n\n    const data: StormcloudApiResponse = await response.json();\n\n    const imaPayload = data.response?.ima?.[\"publisherdesk.ima\"]?.payload;\n    if (imaPayload) {\n      let decodedPayload = imaPayload;\n      try {\n        decodedPayload = decodeURIComponent(imaPayload);\n      } catch {\n        console.warn(\"[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:\", imaPayload);\n      }\n      console.log(\"[StormcloudVideoPlayer] Raw VAST tag URL (from API):\", decodedPayload);\n      this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Normalized VAST tag URL:\",\n          this.apiVastTagUrl\n        );\n      }\n    } else {\n      if (this.debug) {\n        console.warn(\n          \"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response\"\n        );\n      }\n    }\n\n    const numberAds = data.response?.options?.vast?.cue_tones?.number_ads;\n    if (numberAds != null && numberAds > 0) {\n      this.apiNumberAds = numberAds;\n      if (this.debug) {\n        console.log(\n          \"[StormcloudVideoPlayer] Number of ads per break from API:\",\n          this.apiNumberAds\n        );\n      }\n    }\n  }\n\n  private async fetchAndParseVmap(vmapUrl: string): Promise<void> {\n    if (!vmapUrl.trim()) {\n      return;\n    }\n\n    try {\n      const response = await fetch(vmapUrl);\n      if (!response.ok) {\n        throw new Error(`Failed to fetch VMAP (${response.status})`);\n      }\n\n      const vmapXml = await response.text();\n      this.vmapBreaks = this.parseVmapToBreaks(vmapXml);\n      this.consumedVmapBreakIds.clear();\n\n      if (this.debug) {\n        console.log(\n          `[StormcloudVideoPlayer] Loaded ${this.vmapBreaks.length} VMAP ad break(s) from:`,\n          vmapUrl\n        );\n      }\n    } catch (error) {\n      this.vmapBreaks = [];\n      this.consumedVmapBreakIds.clear();\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Failed to load VMAP:\", error);\n      }\n    }\n  }\n\n  private parseVmapToBreaks(vmapXml: string): AdBreak[] {\n    if (typeof DOMParser === \"undefined\") {\n      return [];\n    }\n\n    const doc = new DOMParser().parseFromString(vmapXml, \"application/xml\");\n    if (doc.querySelector(\"parsererror\")) {\n      if (this.debug) {\n        console.warn(\"[StormcloudVideoPlayer] Invalid VMAP XML received\");\n      }\n      return [];\n    }\n\n    const VMAP_NS = \"http://www.iab.net/videosuite/vmap\";\n    let adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, \"AdBreak\"));\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(\n        doc.querySelectorAll(\"AdBreak, vmap\\\\:AdBreak\")\n      );\n    }\n    if (adBreakNodes.length === 0) {\n      adBreakNodes = Array.from(doc.getElementsByTagName(\"*\")).filter(\n        (el) => el.localName === \"AdBreak\"\n      );\n    }\n    const parsed: AdBreak[] = [];\n\n    adBreakNodes.forEach((node, index) => {\n      const timeOffsetRaw = (node.getAttribute(\"timeOffset\") || \"\").trim();\n      const startTimeMs = this.parseVmapTimeOffsetToMs(timeOffsetRaw);\n      if (startTimeMs == null) {\n        return;\n      }\n\n      let adTagNode = node.getElementsByTagNameNS(VMAP_NS, \"AdTagURI\")[0];\n      if (!adTagNode) {\n        adTagNode =\n          (node.querySelector(\"AdTagURI, vmap\\\\:AdTagURI\") as Element | null) ??\n          undefined;\n      }\n      const adTagUrl = (adTagNode?.textContent || \"\").trim();\n      if (!adTagUrl) {\n        return;\n      }\n\n      const breakId =\n        node.getAttribute(\"breakId\") ||\n        `vmap-break-${index}-${timeOffsetRaw || \"unknown\"}`;\n      parsed.push({\n        id: breakId,\n        startTimeMs,\n        vastTagUrl: adTagUrl,\n      });\n    });\n\n    parsed.sort((a, b) => {\n      const aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;\n      const bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;\n      return aStart - bStart;\n    });\n\n    return parsed;\n  }\n\n  private parseVmapTimeOffsetToMs(timeOffset: string): number | undefined {\n    if (!timeOffset) {\n      return undefined;\n    }\n\n    const normalized = timeOffset.trim().toLowerCase();\n    if (normalized === \"start\") {\n      return 0;\n    }\n\n    if (normalized === \"end\") {\n      return -1;\n    }\n\n    const hms = timeOffset.match(\n      /^(\\d{1,2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,3}))?$/\n    );\n    if (hms) {\n      const [, hh, mm, ss, ms = \"0\"] = hms;\n      const hours = Number(hh);\n      const minutes = Number(mm);\n      const seconds = Number(ss);\n      const millis = Number(ms.padEnd(3, \"0\").slice(0, 3));\n      return ((hours * 3600 + minutes * 60 + seconds) * 1000) + millis;\n    }\n\n    const percent = timeOffset.match(/^(\\d+(?:\\.\\d+)?)%$/);\n    if (percent) {\n      const ratio = Number(percent[1]) / 100;\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1000 * ratio);\n      }\n      return undefined;\n    }\n\n    return undefined;\n  }\n\n  getAdBreakKey(adBreak: AdBreak): string {\n    if (adBreak.id) {\n      return adBreak.id;\n    }\n    return `${adBreak.startTimeMs}-${adBreak.vastTagUrl || \"\"}`;\n  }\n\n  resolveBreakStartMs(adBreak: AdBreak): number | undefined {\n    if (adBreak.startTimeMs >= 0) {\n      return adBreak.startTimeMs;\n    }\n\n    if (adBreak.startTimeMs === -1) {\n      const durationSec = this.video.duration;\n      if (Number.isFinite(durationSec) && durationSec > 0) {\n        return Math.floor(durationSec * 1000);\n      }\n    }\n\n    return undefined;\n  }\n\n  findCurrentOrNextBreak(nowMs: number): AdBreak | undefined {\n    const schedule: AdBreak[] = this.vmapBreaks;\n    let candidate: AdBreak | undefined;\n    const tol = this.config.driftToleranceMs ?? 1000;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n      if (\n        breakStartMs <= nowMs + tol &&\n        (candidate == null ||\n          breakStartMs > (this.resolveBreakStartMs(candidate) ?? 0))\n      ) {\n        candidate = b;\n      }\n    }\n    return candidate;\n  }\n\n  findBreakForTime(nowMs: number): AdBreak | undefined {\n    const schedule: AdBreak[] = this.vmapBreaks;\n    for (const b of schedule) {\n      if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {\n        continue;\n      }\n      const breakStartMs = this.resolveBreakStartMs(b);\n      if (breakStartMs == null) {\n        continue;\n      }\n\n      if (b.durationMs) {\n        const end = breakStartMs + b.durationMs;\n        if (nowMs >= breakStartMs && nowMs < end) {\n          return b;\n        }\n        continue;\n      }\n\n      if (nowMs >= breakStartMs) {\n        return b;\n      }\n    }\n    return undefined;\n  }\n\n  selectVastTagsForBreak(b?: AdBreak): string[] | undefined {\n    if (!b || !b.vastTagUrl) return undefined;\n    if (b.vastTagUrl.includes(\",\")) {\n      return b.vastTagUrl\n        .split(\",\")\n        .map((s) => s.trim())\n        .filter((s) => s.length > 0);\n    }\n    return [b.vastTagUrl];\n  }\n\n  beginNewAdPod(): void {\n    this.podCounter++;\n    this.adRequestPositionInBreak = 0;\n  }\n\n  generateVastUrlsWithCorrelators(\n    baseUrl: string,\n    count: number,\n    adPlayer: AdController,\n    palNonce: PalNonceManager,\n    inAdBreak: boolean\n  ): string[] {\n    const urls: string[] = [];\n\n    for (let i = 0; i < count; i++) {\n      this.adRequestPositionInBreak++;\n\n      const adWillPlayMuted = inAdBreak\n        ? adPlayer.getOriginalMutedState()\n        : this.video.muted;\n      const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n\n      const urlWithMacros = applyVastMacros(baseUrl, {\n        correlator: generateCorrelator(),\n        streamCorrelator: this.streamCorrelator,\n        pod: this.podCounter > 0 ? this.podCounter : undefined,\n        adPosition: this.adRequestPositionInBreak,\n        isCtv: envSignals.isCtv,\n        contentUrl: envSignals.contentUrl,\n        pageUrl:\n          !envSignals.isCtv && typeof window !== \"undefined\"\n            ? window.location.href\n            : undefined,\n        adWillPlayMuted,\n        adWillAutoPlay: !!this.config.autoplay,\n        appId: envSignals.appId,\n        appName: envSignals.appName,\n        sessionId: envSignals.sessionId,\n        deviceId: envSignals.deviceId,\n        deviceIdType: envSignals.deviceIdType,\n        limitAdTracking: envSignals.limitAdTracking,\n        deviceTypeHint: envSignals.deviceTypeHint,\n        adTest: this.config.adTest,\n        consent: this.consentSignals,\n      });\n\n      const finalUrl = palNonce.injectNonce(urlWithMacros);\n      console.log(\n        `[StormcloudVideoPlayer] Resolved ad request URL (pod=${this.podCounter}, pos=${this.adRequestPositionInBreak}):`,\n        finalUrl\n      );\n      urls.push(finalUrl);\n    }\n\n    return urls;\n  }\n\n  private readonly defaultPodMaxAds: number = 6;\n\n  resolvePodParams(breakDurationMs?: number): {\n    maxAds: number;\n    minDurationMs: number;\n    maxDurationMs: number | undefined;\n  } {\n    const maxDurationMs =\n      breakDurationMs != null && breakDurationMs > 0\n        ? breakDurationMs\n        : this.config.podMaxDurationMs;\n\n    const maxAds =\n      this.config.podMaxAds && this.config.podMaxAds > 0\n        ? this.config.podMaxAds\n        : this.apiNumberAds && this.apiNumberAds > 0\n          ? this.apiNumberAds\n          : this.defaultPodMaxAds;\n\n    const minDurationMs =\n      this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;\n\n    return { maxAds, minDurationMs, maxDurationMs };\n  }\n\n  generatePodVastUrl(\n    baseUrl: string,\n    podParams: { maxAds: number; minDurationMs: number; maxDurationMs: number | undefined },\n    adPlayer: AdController,\n    palNonce: PalNonceManager,\n    inAdBreak: boolean\n  ): string {\n    const adWillPlayMuted = inAdBreak\n      ? adPlayer.getOriginalMutedState()\n      : this.video.muted;\n    const envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);\n\n    const urlWithMacros = applyVastMacros(baseUrl, {\n      correlator: generateCorrelator(),\n      streamCorrelator: this.streamCorrelator,\n      pod: this.podCounter > 0 ? this.podCounter : undefined,\n      podMaxAds: podParams.maxAds,\n      podMinDurationMs: podParams.minDurationMs,\n      podMaxDurationMs: podParams.maxDurationMs,\n      isCtv: envSignals.isCtv,\n      contentUrl: envSignals.contentUrl,\n      pageUrl:\n        !envSignals.isCtv && typeof window !== \"undefined\"\n          ? window.location.href\n          : undefined,\n      adWillPlayMuted,\n      adWillAutoPlay: !!this.config.autoplay,\n      appId: envSignals.appId,\n      appName: envSignals.appName,\n      sessionId: envSignals.sessionId,\n      deviceId: envSignals.deviceId,\n      deviceIdType: envSignals.deviceIdType,\n      limitAdTracking: envSignals.limitAdTracking,\n      deviceTypeHint: envSignals.deviceTypeHint,\n      adTest: this.config.adTest,\n      consent: this.consentSignals,\n    });\n\n    const finalUrl = palNonce.injectNonce(urlWithMacros);\n    console.log(\n      `[StormcloudVideoPlayer] Resolved optimized-pod request URL (pod=${this.podCounter}, pmad=${podParams.maxAds}, pmnd=${podParams.minDurationMs}, pmxd=${podParams.maxDurationMs ?? \"?\"}):`,\n      finalUrl\n    );\n    return finalUrl;\n  }\n\n  // --- Tracking ---\n\n  initializeTracking(): void {\n    sendInitialTracking(this.config.licenseKey, buildAnalyticsContext(this.config))\n      .then(() => {\n        this.heartbeatInterval = window.setInterval(() => {\n          this.sendHeartbeatIfNeeded();\n        }, 5000);\n      })\n      .catch((error) => {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] Failed to send initial tracking:\",\n            error\n          );\n        }\n        this.heartbeatInterval = window.setInterval(() => {\n          this.sendHeartbeatIfNeeded();\n        }, 5000);\n      });\n  }\n\n  private sendHeartbeatIfNeeded(): void {\n    const now = Date.now();\n    if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 30000) {\n      this.lastHeartbeatTime = now;\n      sendHeartbeat(this.config.licenseKey, buildAnalyticsContext(this.config)).catch((error) => {\n        if (this.debug) {\n          console.warn(\n            \"[StormcloudVideoPlayer] Failed to send heartbeat:\",\n            error\n          );\n        }\n      });\n    }\n  }\n\n  destroyTracking(): void {\n    if (this.heartbeatInterval) {\n      clearInterval(this.heartbeatInterval);\n      this.heartbeatInterval = undefined;\n    }\n  }\n}\n","export interface VastEnvironmentSignals {\n  isCtv: boolean;\n  contentUrl?: string;\n  appId?: string;\n  appName?: string;\n  sessionId?: string;\n  deviceId?: string;\n  deviceIdType?: string;\n  limitAdTracking?: boolean;\n  deviceTypeHint?: number;\n}\n\nconst AIRY_ANDROID_APP_ID = \"com.freeairytv.android\";\nconst AIRY_WEBOS_APP_ID    = \"com.freeairytv.webos\";\nconst AIRY_TIZEN_APP_ID    = \"com.freeairytv.samsung\";\nconst AIRY_ROKU_APP_ID     = \"com.freeairytv.roku\";\nconst AIRY_APP_NAME = \"AiryTV Movies & TV\";\nconst AIRY_DEFAULT_CONTENT_URL = \"https://live.airy.tv\";\nconst CTV_SESSION_STORAGE_KEY = \"stormcloud.ctv.sid\";\nexport const PLAYER_ID_STORAGE_KEY = \"stormcloud.player.id\";\n\nconst LG_TEST_APP_ID      = \"com.hulu.plus\";\nconst LG_TEST_APP_NAME    = \"Hulu\";\nconst LG_TEST_CONTENT_URL = \"https://www.hulu.com/live-tv\";\n\nlet _lgTestDeviceId: string | undefined;\nfunction getLgTestDeviceId(): string {\n  if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();\n  return _lgTestDeviceId;\n}\n\nfunction isLgWebOS(): boolean {\n  if (typeof navigator === \"undefined\") return false;\n  return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);\n}\n\nfunction getDefaultAppId(): string {\n  if (typeof navigator === \"undefined\") return AIRY_ANDROID_APP_ID;\n  const ua = navigator.userAgent;\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;\n  if (/Tizen|Samsung/i.test(ua))                       return AIRY_TIZEN_APP_ID;\n  if (/Roku/i.test(ua))                                return AIRY_ROKU_APP_ID;\n  return AIRY_ANDROID_APP_ID;\n}\n\nconst DEVICE_ID_STORAGE_KEYS = [\n  \"rdid\",\n  \"ifa\",\n  \"advertisingId\",\n  \"advertising_id\",\n  \"deviceAdvertisingId\",\n  \"aaid\",\n  \"adid\",\n  \"rida\",\n  \"tifa\",\n  \"lgudid\",\n];\n\nconst ANDROID_ID_TYPES = new Set([\"aaid\", \"adid\"]);\n\nexport function resolveVastEnvironmentSignals(isCtv: boolean): VastEnvironmentSignals {\n  const bridgeSignals  = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const lg = isCtv && isLgWebOS();\n\n  const deviceId =\n    bridgeSignals.deviceId  ||\n    readStoredDeviceId()    ||\n    platformDevice.deviceId ||\n    (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : undefined);\n  const deviceIdType =\n    bridgeSignals.deviceIdType  ||\n    readStoredString(\"deviceIdType\") ||\n    readStoredString(\"idtype\") ||\n    platformDevice.deviceIdType ||\n    inferDeviceIdType() ||\n    (lg ? \"lgudid\" : undefined);\n  const platformLat = bridgeSignals.deviceId\n    ? bridgeSignals.limitAdTracking\n    : platformDevice.limitAdTracking;\n  const limitAdTracking =\n    deviceId != null\n      ? platformLat ?? readStoredLimitAdTracking() ?? false\n      : undefined;\n\n  if (isCtv) {\n    return {\n      isCtv: true,\n      contentUrl:\n        bridgeSignals.contentUrl ||\n        readStoredString(\"contentUrl\") ||\n        (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),\n      appId:\n        bridgeSignals.appId ||\n        readStoredString(\"appId\") ||\n        readStoredString(\"msid\") ||\n        (lg ? LG_TEST_APP_ID : getDefaultAppId()),\n      appName:\n        bridgeSignals.appName ||\n        readStoredString(\"appName\") ||\n        readStoredString(\"an\") ||\n        (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),\n      sessionId: getOrCreateCtvSessionId(),\n      ...(deviceId ? { deviceId } : {}),\n      ...(deviceIdType ? { deviceIdType } : {}),\n      ...(limitAdTracking != null ? { limitAdTracking } : {}),\n      deviceTypeHint: 5,\n    };\n  }\n\n  return {\n    isCtv: false,\n    ...(deviceId ? { deviceId } : {}),\n    ...(deviceIdType ? { deviceIdType } : {}),\n    ...(limitAdTracking != null ? { limitAdTracking } : {}),\n  };\n}\n\nexport function inferDeviceIdType(): string | undefined {\n  if (typeof navigator === \"undefined\") {\n    return undefined;\n  }\n\n  const ua = navigator.userAgent;\n  if (/Roku/i.test(ua)) return \"rida\";\n  if (/Tizen|Samsung/i.test(ua)) return \"tifa\";\n  if (/AppleTV|Apple TV/i.test(ua)) return \"tvOS\";\n  if (/AFT|Fire TV|Amazon/i.test(ua)) return \"afai\";\n  if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return \"lgudid\";\n  if (/Android|Google TV/i.test(ua)) return \"aaid\";\n  if (/iPhone|iPad|iPod/i.test(ua)) return \"idfa\";\n  return undefined;\n}\n\nexport function isEquivalentDeviceIdType(\n  tagType: string | undefined,\n  runtimeType: string | undefined\n): boolean {\n  if (!tagType || !runtimeType) return false;\n  const tag = tagType.toLowerCase();\n  const runtime = runtimeType.toLowerCase();\n  if (tag === runtime) return true;\n  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);\n}\n\nexport function resolveNativeDeviceId(): string | undefined {\n  const bridgeSignals = readNativeBridgeSignals();\n  const platformDevice = readPlatformNativeDeviceId();\n  const deviceId =\n    bridgeSignals.deviceId ||\n    readStoredDeviceId() ||\n    platformDevice.deviceId;\n\n  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {\n    return undefined;\n  }\n\n  return deviceId;\n}\n\nexport function getOrCreateStoredUuid(storageKey: string): string | undefined {\n  if (typeof window === \"undefined\") {\n    return undefined;\n  }\n\n  const existing = readStoredString(storageKey);\n  if (existing) {\n    return existing;\n  }\n\n  const id = createUuid();\n  try {\n    window.localStorage?.setItem(storageKey, id);\n  } catch {}\n  return id;\n}\n\nfunction getOrCreateCtvSessionId(): string {\n  const existing = readStoredString(CTV_SESSION_STORAGE_KEY);\n  if (existing) {\n    return existing;\n  }\n\n  const sessionId = createUuid();\n  try {\n    window.localStorage?.setItem(CTV_SESSION_STORAGE_KEY, sessionId);\n  } catch {}\n  return sessionId;\n}\n\nfunction createUuid(): string {\n  if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n    return crypto.randomUUID();\n  }\n\n  return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (char) => {\n    const value = Math.floor(Math.random() * 16);\n    const nibble = char === \"x\" ? value : (value & 0x3) | 0x8;\n    return nibble.toString(16);\n  });\n}\n\nfunction readPlatformNativeDeviceId(): {\n  deviceId?: string;\n  deviceIdType?: string;\n  limitAdTracking?: boolean;\n} {\n  if (typeof window === \"undefined\") return {};\n\n  try {\n    const adinfo = (window as any).webapis?.adinfo;\n    if (adinfo) {\n      const tifa: unknown =\n        typeof adinfo.getTIFA === \"function\" ? adinfo.getTIFA() : adinfo.tifa;\n      if (typeof tifa === \"string\" && tifa && !isMacroPlaceholder(tifa)) {\n        const lat: unknown =\n          typeof adinfo.isLATEnabled === \"function\"\n            ? adinfo.isLATEnabled()\n            : undefined;\n        return {\n          deviceId: tifa,\n          deviceIdType: \"tifa\",\n          ...(typeof lat === \"boolean\" ? { limitAdTracking: lat } : {}),\n        };\n      }\n    }\n  } catch {}\n\n  try {\n    const webOSDev = (window as any).webOSDev;\n    if (webOSDev) {\n      const lgudid: unknown =\n        typeof webOSDev.LGUDID === \"function\"\n          ? webOSDev.LGUDID()\n          : webOSDev.lgudid ?? webOSDev.LGUDID;\n      if (typeof lgudid === \"string\" && lgudid) {\n        if (isZeroedAdId(lgudid)) {\n          return { deviceIdType: \"lgudid\", limitAdTracking: true };\n        }\n        if (!isMacroPlaceholder(lgudid)) {\n          return { deviceId: lgudid, deviceIdType: \"lgudid\", limitAdTracking: false };\n        }\n      }\n    }\n  } catch {}\n\n  try {\n    const roku = (window as any).Roku;\n    if (roku) {\n      const rida: unknown =\n        typeof roku.getPublisherUniqueId === \"function\"\n          ? roku.getPublisherUniqueId()\n          : roku.rida;\n      if (typeof rida === \"string\" && rida && !isMacroPlaceholder(rida)) {\n        return { deviceId: rida, deviceIdType: \"rida\", limitAdTracking: false };\n      }\n    }\n  } catch {}\n\n  return {};\n}\n\nconst ZEROED_AD_ID_PATTERNS: ReadonlySet<string> = new Set([\n  \"38400000-8cf0-11bd-b23e-10b96e40000d\",\n  \"00000000-0000-0000-0000-000000000000\",\n]);\n\nfunction isMacroPlaceholder(value: string): boolean {\n  const t = value.trim();\n  return !t ||\n    /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/.test(t) ||\n    /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(t) ||\n    ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());\n}\n\nfunction isZeroedAdId(value: string): boolean {\n  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());\n}\n\nfunction readNativeBridgeSignals(): {\n  contentUrl?: string;\n  appId?: string;\n  appName?: string;\n  deviceId?: string;\n  deviceIdType?: string;\n  limitAdTracking?: boolean;\n} {\n  if (typeof window === \"undefined\") {\n    return {};\n  }\n\n  const candidates = [\n    (window as any).__STORMCLOUD_CTV_AD_INFO__,\n    (window as any).__STORMCLOUD_CTV__,\n    (window as any).stormcloudCtv,\n    (window as any).AiryTV,\n    (window as any).Android,\n    (window as any).webOS,\n    (window as any).tizen,\n    (window as any).amazon,\n  ].filter(Boolean);\n\n  for (const source of candidates) {\n    const contentUrl =\n      readBridgeValue(source, [\"contentUrl\", \"url\", \"videoUrl\", \"canonicalUrl\"]) ||\n      undefined;\n    const appId =\n      readBridgeValue(source, [\"appId\", \"msid\", \"applicationId\", \"packageName\"]) ||\n      undefined;\n    const appName =\n      readBridgeValue(source, [\"appName\", \"an\", \"applicationName\"]) || undefined;\n    const deviceId =\n      readBridgeValue(source, [\n        \"rdid\",\n        \"ifa\",\n        \"advertisingId\",\n        \"adId\",\n        \"deviceId\",\n        \"lgudid\",\n        \"LGUDID\",\n        \"tifa\",\n        \"rida\",\n        \"afai\",\n        \"aaid\",\n      ]) || undefined;\n\n    if (!contentUrl && !deviceId && !appId && !appName) continue;\n\n    const deviceIdType =\n      readBridgeValue(source, [\n        \"idtype\",\n        \"deviceIdType\",\n        \"advertisingIdType\",\n        \"idType\",\n      ]) || inferDeviceIdType();\n    const limitAdTracking = readBridgeBoolean(source, [\n      \"is_lat\",\n      \"limitAdTracking\",\n      \"limitedAdTracking\",\n      \"lat\",\n    ]);\n\n    return {\n      ...(contentUrl ? { contentUrl } : {}),\n      ...(appId ? { appId } : {}),\n      ...(appName ? { appName } : {}),\n      ...(deviceId ? { deviceId } : {}),\n      ...(deviceId && deviceIdType ? { deviceIdType } : {}),\n      ...(deviceId && limitAdTracking != null ? { limitAdTracking } : {}),\n    };\n  }\n\n  return {};\n}\n\nfunction readBridgeValue(source: any, keys: string[]): string | undefined {\n  for (const key of keys) {\n    const value = source?.[key];\n    if (typeof value === \"string\" && value) {\n      return value;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = value.call(source);\n        if (typeof result === \"string\" && result) {\n          return result;\n        }\n      } catch {}\n    }\n  }\n  return undefined;\n}\n\nfunction readBridgeBoolean(source: any, keys: string[]): boolean | undefined {\n  for (const key of keys) {\n    const value = source?.[key];\n    const normalized = normalizeBoolean(value);\n    if (normalized != null) {\n      return normalized;\n    }\n    if (typeof value === \"function\") {\n      try {\n        const result = normalizeBoolean(value.call(source));\n        if (result != null) {\n          return result;\n        }\n      } catch {}\n    }\n  }\n  return undefined;\n}\n\nfunction readStoredDeviceId(): string | undefined {\n  for (const key of DEVICE_ID_STORAGE_KEYS) {\n    const value = readStoredString(key);\n    if (value) {\n      return value;\n    }\n  }\n  return undefined;\n}\n\nfunction readStoredString(key: string): string | undefined {\n  if (typeof window === \"undefined\") {\n    return undefined;\n  }\n\n  try {\n    const value = window.localStorage?.getItem(key);\n    return value || undefined;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction readStoredLimitAdTracking(): boolean | undefined {\n  return normalizeBoolean(\n    readStoredString(\"limitAdTracking\") ||\n      readStoredString(\"limitedAdTracking\") ||\n      readStoredString(\"is_lat\")\n  );\n}\n\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n  if (typeof value === \"boolean\") {\n    return value;\n  }\n  if (typeof value === \"number\") {\n    return value === 1;\n  }\n  if (typeof value === \"string\") {\n    const normalized = value.toLowerCase();\n    if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n      return true;\n    }\n    if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n      return false;\n    }\n  }\n  return undefined;\n}\n","import {\n  inferDeviceIdType,\n  isEquivalentDeviceIdType,\n} from \"./vastEnvironmentSignals\";\n\nexport interface VastConsentSignals {\n  gdpr?: string | undefined;\n  gdprConsent?: string | undefined;\n  usPrivacy?: string | undefined;\n}\n\nexport interface VastMacroContext {\n  correlator: string;\n  streamCorrelator: string;\n  pod?: number | undefined;\n  adPosition?: number | undefined;\n  podMaxAds?: number | undefined;\n  podMinDurationMs?: number | undefined;\n  podMaxDurationMs?: number | undefined;\n  isCtv?: boolean | undefined;\n  contentUrl?: string | undefined;\n  pageUrl?: string | undefined;\n  adWillPlayMuted?: boolean | undefined;\n  adWillAutoPlay?: boolean | undefined;\n  appId?: string | undefined;\n  appName?: string | undefined;\n  sessionId?: string | undefined;\n  deviceId?: string | undefined;\n  deviceIdType?: string | undefined;\n  limitAdTracking?: boolean | undefined;\n  deviceTypeHint?: number | undefined;\n  adTest?: boolean | undefined;\n  consent?: VastConsentSignals | undefined;\n}\n\nconst UNEXPANDED_MACRO_PATTERN = /^(\\[[^\\]]*\\]|\\{[^}]*\\}|%%[^%]*%%)$/;\nconst INVALID_VAST_PARAM_KEY = /^\\s|\\s$/;\nconst EXAMPLE_COM_URL = /example\\.com/i;\nconst CTV_UNSUPPORTED_PARAMS = [\n  \"description_url\",\n  \"tfcd\",\n  \"npa\",\n  \"min_ad_duration\",\n  \"max_ad_duration\",\n  \"unviewed_position_start\",\n  \"impl\",\n  \"vad_type\",\n  \"gdpr\",\n  \"gdpr_consent\",\n  \"us_privacy\",\n];\n\nconst INLINE_DEVICE_MACRO_REPLACEMENTS: Array<{\n  pattern: RegExp;\n  getValue: (ctx: VastMacroContext) => string | undefined;\n}> = [\n  { pattern: /\\[RDID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IFA\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[ADVERTISING[_-]?ID(?:ENTIFIER)?\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[DEVICE[_-]?ID\\]/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\[IDTYPE\\]/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /\\{rdid\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{device[_-]?id\\}/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /\\{idtype\\}/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi, getValue: (ctx) =>\n      ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n  { pattern: /%%ADVERTISING_ID_TYPE%%/gi, getValue: (ctx) => ctx.deviceIdType },\n  { pattern: /%%ADVERTISING_ID%%/gi, getValue: (ctx) => ctx.deviceId },\n  { pattern: /%%LIMIT_AD_TRACKING%%/gi, getValue: (ctx) =>\n      ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined },\n  { pattern: /%%MSID%%/gi, getValue: (ctx) => ctx.appId },\n  { pattern: /%%APP_NAME%%/gi, getValue: (ctx) => ctx.appName },\n  { pattern: /%%SESSION_ID%%/gi, getValue: (ctx) => ctx.sessionId },\n  { pattern: /%%CORRELATOR%%/gi, getValue: (ctx) => ctx.correlator },\n];\n\nexport function isMacroPlaceholder(value: string | null | undefined): boolean {\n  if (value == null) return true;\n  const trimmed = value.trim();\n  if (!trimmed) return true;\n  if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;\n  return /^(unknown|null|undefined|none|n\\/a|\\$\\{[^}]+\\})$/i.test(trimmed);\n}\n\nexport function generateCorrelator(): string {\n  if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n    try {\n      const buf = new Uint32Array(2);\n      crypto.getRandomValues(buf);\n      const value = (buf[0] ?? 0) * 0x200000 + ((buf[1] ?? 0) & 0x1fffff);\n      if (value > 0) {\n        return String(value);\n      }\n    } catch {\n    }\n  }\n  return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);\n}\n\nfunction expandInlineMacroPlaceholders(baseUrl: string, ctx: VastMacroContext): string {\n  let url = baseUrl;\n  for (const { pattern, getValue } of INLINE_DEVICE_MACRO_REPLACEMENTS) {\n    const value = getValue(ctx);\n    if (value != null && value !== \"\") {\n      url = url.replace(pattern, encodeURIComponent(value));\n    }\n  }\n  return url;\n}\n\nfunction applyDeviceIdentityParams(\n  params: URLSearchParams,\n  ctx: VastMacroContext\n): void {\n  const runtimeId = ctx.deviceId?.trim();\n  const runtimeType = ctx.deviceIdType?.trim() || inferDeviceIdType();\n  const tagRdid = params.get(\"rdid\");\n  const tagType = params.get(\"idtype\");\n  const tagLat = params.get(\"is_lat\");\n  const latValue =\n    ctx.limitAdTracking != null ? (ctx.limitAdTracking ? \"1\" : \"0\") : undefined;\n\n  if (runtimeId) {\n    params.set(\"rdid\", runtimeId);\n    params.set(\"idtype\", runtimeType || tagType || \"aaid\");\n    params.set(\"is_lat\", latValue ?? (isMacroPlaceholder(tagLat) ? \"0\" : tagLat!));\n    return;\n  }\n\n  const tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));\n  const tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));\n\n  if (\n    tagRdidValid &&\n    tagTypeValid &&\n    runtimeType &&\n    !isEquivalentDeviceIdType(tagType!, runtimeType)\n  ) {\n    params.delete(\"rdid\");\n    params.delete(\"idtype\");\n    params.delete(\"is_lat\");\n    return;\n  }\n\n  if (tagRdidValid) {\n    if (isMacroPlaceholder(tagType) && runtimeType) {\n      params.set(\"idtype\", runtimeType);\n    }\n    if (isMacroPlaceholder(tagLat)) {\n      params.set(\"is_lat\", latValue ?? \"0\");\n    }\n    return;\n  }\n\n  params.delete(\"rdid\");\n  params.delete(\"idtype\");\n  params.delete(\"is_lat\");\n}\n\nfunction removeBrokenAppNameOrphans(\n  params: URLSearchParams,\n  appName?: string\n): void {\n  const toDelete: string[] = [];\n\n  params.forEach((_value, key) => {\n    if (!key || INVALID_VAST_PARAM_KEY.test(key)) {\n      toDelete.push(key);\n    }\n  });\n\n  if (appName && appName.includes(\"&\")) {\n    for (const suffix of appName.split(\"&\").slice(1)) {\n      const trimmed = suffix.trimStart();\n      if (!trimmed) continue;\n      toDelete.push(suffix, ` ${trimmed}`, trimmed);\n    }\n  }\n\n  for (const key of new Set(toDelete)) {\n    if (key) params.delete(key);\n  }\n}\n\nexport function normalizeVastTagUrl(raw: string): string {\n  if (!raw) return raw;\n\n  try {\n    const url = new URL(raw);\n\n    const anValue = url.searchParams.get(\"an\");\n    if (anValue !== null) {\n      const orphanFragments: string[] = [];\n      url.searchParams.forEach((_value, key) => {\n        if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n          orphanFragments.push(key.trim());\n        }\n      });\n      if (orphanFragments.length > 0) {\n        const reconstructed = [anValue.trimEnd(), ...orphanFragments]\n          .filter(Boolean)\n          .join(\" & \");\n\n        url.searchParams.forEach((_value, key) => {\n          if (key && INVALID_VAST_PARAM_KEY.test(key)) {\n            url.searchParams.delete(key);\n          }\n        });\n        url.searchParams.set(\"an\", reconstructed);\n\n        return url.toString().replace(\n          /([?&]an=)([^&]*)/,\n          (_match, prefix, val) => prefix + val.replace(/\\+/g, \"%20\")\n        );\n      }\n    }\n\n    removeBrokenAppNameOrphans(url.searchParams);\n    return url.toString();\n  } catch {\n    return raw;\n  }\n}\n\nexport function applyVastMacros(\n  baseUrl: string,\n  ctx: VastMacroContext\n): string {\n  const expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);\n  let url: URL;\n  try {\n    url = new URL(normalizeVastTagUrl(expandedUrl));\n  } catch {\n    return replaceCorrelatorFallback(expandedUrl, ctx.correlator);\n  }\n\n  const params = url.searchParams;\n\n  removeBrokenAppNameOrphans(params, ctx.appName);\n\n  params.set(\"correlator\", ctx.correlator);\n  params.set(\"scor\", ctx.streamCorrelator);\n  if (ctx.isCtv) {\n    for (const key of CTV_UNSUPPORTED_PARAMS) {\n      params.delete(key);\n    }\n  }\n\n  if (ctx.pod != null) {\n    params.set(\"pod\", String(ctx.pod));\n  }\n\n  const optimizedPodMode =\n    ctx.podMaxAds != null ||\n    ctx.podMinDurationMs != null ||\n    ctx.podMaxDurationMs != null;\n\n  if (optimizedPodMode) {\n    params.delete(\"ppos\");\n    params.delete(\"lip\");\n    if (ctx.podMinDurationMs != null) {\n      params.set(\"pmnd\", String(Math.max(0, Math.round(ctx.podMinDurationMs))));\n    }\n    if (ctx.podMaxDurationMs != null) {\n      params.set(\"pmxd\", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));\n    }\n    if (ctx.podMaxAds != null) {\n      params.set(\"pmad\", String(Math.max(1, Math.round(ctx.podMaxAds))));\n    }\n  } else if (ctx.adPosition != null) {\n    params.set(\"ppos\", String(ctx.adPosition));\n  }\n\n  const requestUrl = ctx.contentUrl || ctx.pageUrl;\n  if (requestUrl) {\n    params.set(\"url\", requestUrl);\n    if (!ctx.isCtv) {\n      params.set(\"description_url\", requestUrl);\n    }\n  } else {\n    const existingUrl = params.get(\"url\") || \"\";\n    if (EXAMPLE_COM_URL.test(existingUrl)) {\n      params.delete(\"url\");\n      params.delete(\"description_url\");\n    }\n  }\n\n  if (ctx.adWillPlayMuted != null) {\n    params.set(\"vpmute\", ctx.adWillPlayMuted ? \"1\" : \"0\");\n  }\n  if (ctx.adWillAutoPlay != null) {\n    params.set(\"vpa\", ctx.adWillAutoPlay ? \"auto\" : \"click\");\n  }\n\n  if (ctx.appId) {\n    params.set(\"msid\", ctx.appId);\n  }\n  if (ctx.appName) {\n    removeBrokenAppNameOrphans(params, ctx.appName);\n    params.set(\"an\", ctx.appName);\n  }\n  if (ctx.sessionId) {\n    params.set(\"sid\", ctx.sessionId);\n  }\n  if (ctx.deviceTypeHint != null) {\n    params.set(\"dth\", String(ctx.deviceTypeHint));\n  } else if (ctx.isCtv) {\n    params.set(\"dth\", \"5\");\n  }\n\n  applyDeviceIdentityParams(params, ctx);\n\n  if (!ctx.isCtv) {\n    const consent = ctx.consent;\n    if (consent?.gdpr != null) {\n      params.set(\"gdpr\", consent.gdpr);\n    }\n    if (consent?.gdprConsent != null) {\n      params.set(\"gdpr_consent\", consent.gdprConsent);\n    }\n    if (consent?.usPrivacy != null) {\n      params.set(\"us_privacy\", consent.usPrivacy);\n    }\n  }\n\n  if (ctx.adTest) {\n    params.set(\"adtest\", \"on\");\n  }\n\n  const staleKeys: string[] = [];\n  params.forEach((value, key) => {\n    if (isMacroPlaceholder(value)) {\n      staleKeys.push(key);\n    }\n  });\n  for (const key of staleKeys) {\n    params.delete(key);\n  }\n\n  removeBrokenAppNameOrphans(params, ctx.appName);\n\n  return url.toString();\n}\n\nfunction replaceCorrelatorFallback(baseUrl: string, correlator: string): string {\n  const correlatorRegex = /([?&])correlator=([^&]*)/;\n  if (correlatorRegex.test(baseUrl)) {\n    return baseUrl.replace(correlatorRegex, `$1correlator=${correlator}`);\n  }\n  const sep = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n  return `${baseUrl}${sep}correlator=${correlator}`;\n}\n\nexport function fetchConsentSignals(\n  timeoutMs: number = 1500\n): Promise<VastConsentSignals> {\n  const signals: VastConsentSignals = {};\n  if (typeof window === \"undefined\") {\n    return Promise.resolve(signals);\n  }\n\n  const tasks: Promise<void>[] = [];\n\n  const tcfApi = (window as any).__tcfapi;\n  if (typeof tcfApi === \"function\") {\n    tasks.push(\n      new Promise<void>((resolve) => {\n        let settled = false;\n        try {\n          tcfApi(\"addEventListener\", 2, (tcData: any, success: boolean) => {\n            if (settled) return;\n            if (\n              success &&\n              tcData &&\n              (tcData.eventStatus === \"tcloaded\" ||\n                tcData.eventStatus === \"useractioncomplete\")\n            ) {\n              settled = true;\n              signals.gdpr = tcData.gdprApplies ? \"1\" : \"0\";\n              if (typeof tcData.tcString === \"string\" && tcData.tcString) {\n                signals.gdprConsent = tcData.tcString;\n              }\n              try {\n                tcfApi(\"removeEventListener\", 2, () => {}, tcData.listenerId);\n              } catch {}\n              resolve();\n            }\n          });\n        } catch {\n          resolve();\n        }\n        setTimeout(() => {\n          if (!settled) {\n            settled = true;\n            resolve();\n          }\n        }, timeoutMs);\n      })\n    );\n  }\n\n  const uspApi = (window as any).__uspapi;\n  if (typeof uspApi === \"function\") {\n    tasks.push(\n      new Promise<void>((resolve) => {\n        try {\n          uspApi(\"getUSPData\", 1, (data: any, success: boolean) => {\n            if (success && typeof data?.uspString === \"string\" && data.uspString) {\n              signals.usPrivacy = data.uspString;\n            }\n            resolve();\n          });\n        } catch {\n          resolve();\n        }\n        setTimeout(resolve, timeoutMs);\n      })\n    );\n  }\n\n  if (tasks.length === 0) {\n    return Promise.resolve(signals);\n  }\n\n  return Promise.all(tasks).then(() => signals);\n}\n","export const MQTT_CA_CERT_FILE = \"src/certs/emqxsl-ca.crt\";\n\nexport type MQTTConfig = {\n  enabled: boolean;\n  brokerAddress: string;\n  brokerPort: number;\n  wsPort: number;\n  username: string;\n  password: string;\n  topicPrefix: string;\n  qos: 0 | 1 | 2;\n  brokerUrl?: string;\n};\n\nexport const DEFAULT_MQTT_CONFIG: MQTTConfig = {\n  enabled: true,\n  brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n  brokerPort: 8883,\n  wsPort: 8084,\n  username: \"for-sonifi\",\n  password: \"sonifi-mqtt\",\n  topicPrefix: \"adstorm/players\",\n  qos: 1,\n};\n\nexport const mqttConfig: MQTTConfig = { ...DEFAULT_MQTT_CONFIG };\n\nexport function applyMQTTConfig(overrides: Partial<MQTTConfig>): void {\n  Object.assign(mqttConfig, overrides);\n}\n\nexport function isMQTTEnabled(): boolean {\n  return mqttConfig.enabled;\n}\n\nexport function buildMQTTBrokerUrl(): string {\n  if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n  return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\nexport function buildPlayerTopic(\n  licenseKey: string,\n  channel: \"metrics\" | \"impressions\" | \"heartbeat\"\n): string {\n  return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n","import mqtt from \"mqtt\";\nimport type { MqttClient } from \"mqtt\";\nimport {\n  applyMQTTConfig,\n  buildMQTTBrokerUrl,\n  isMQTTEnabled,\n  mqttConfig,\n} from \"./mqttConfig\";\nimport type { MQTTConfig } from \"./mqttConfig\";\n\nconst LOG = \"[StormcloudVideoPlayer][MQTT]\";\n\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\n\nexport function getMQTTStatus(): MQTTStatus {\n  return status;\n}\n\nexport function isMQTTConnected(): boolean {\n  return status === \"connected\" && client !== null && client.connected;\n}\n\nexport function isMQTTConfigured(): boolean {\n  return isMQTTEnabled();\n}\n\nexport function configureMQTT(overrides: Partial<MQTTConfig>): void {\n  applyMQTTConfig(overrides);\n  disconnectMQTT();\n}\n\nexport function initMQTTClient(): void {\n  if (client || !isMQTTEnabled()) return;\n\n  const url = buildMQTTBrokerUrl();\n  status = \"connecting\";\n\n  const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n\n  try {\n    client = mqtt.connect(url, {\n      clientId,\n      username: mqttConfig.username,\n      password: mqttConfig.password,\n      keepalive: 60,\n      clean: true,\n      reconnectPeriod: 5000,\n      connectTimeout: 10_000,\n      queueQoSZero: false,\n    });\n  } catch (err) {\n    status = \"error\";\n    console.warn(`${LOG} connect() threw:`, err);\n    return;\n  }\n\n  client.on(\"connect\", () => {\n    status = \"connected\";\n    console.info(`${LOG} connected to ${url}`);\n  });\n\n  client.on(\"reconnect\", () => {\n    status = \"connecting\";\n    console.info(`${LOG} reconnecting…`);\n  });\n\n  client.on(\"offline\", () => {\n    status = \"disconnected\";\n    console.warn(`${LOG} offline`);\n  });\n\n  client.on(\"error\", (err) => {\n    status = \"error\";\n    console.warn(`${LOG} error:`, err.message);\n  });\n\n  client.on(\"close\", () => {\n    if (status === \"connected\") {\n      status = \"disconnected\";\n    }\n  });\n}\n\nexport function ensureMQTTClient(): void {\n  if (isMQTTEnabled() && !client) {\n    initMQTTClient();\n  }\n}\n\nexport function publishMQTT(\n  topic: string,\n  payload: Record<string, unknown>\n): boolean {\n  if (!isMQTTEnabled()) {\n    return false;\n  }\n\n  ensureMQTTClient();\n\n  if (!client) {\n    return false;\n  }\n\n  try {\n    client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n    return true;\n  } catch (err) {\n    console.warn(`${LOG} publish failed on ${topic}:`, err);\n    return false;\n  }\n}\n\nexport function disconnectMQTT(): void {\n  if (client) {\n    client.end(true);\n    client = null;\n    status = \"disconnected\";\n  }\n}\n","import type {\n  ClientInfo,\n  AdDetectInfo,\n  AdLoadedInfo,\n  AdImpressionInfo,\n  PlayerAnalyticsContext,\n  StormcloudVideoPlayerConfig,\n} from \"../types\";\n\nimport { buildPlayerTopic, isMQTTEnabled } from \"./mqttConfig\";\nimport { ensureMQTTClient, publishMQTT } from \"./mqttClient\";\nimport {\n  getOrCreateStoredUuid,\n  PLAYER_ID_STORAGE_KEY,\n  resolveNativeDeviceId,\n} from \"./vastEnvironmentSignals\";\n\nlet cachedBrowserId: string | null = null;\n\nexport function buildAnalyticsContext(\n  config: Pick<StormcloudVideoPlayerConfig, \"debugAdTiming\" | \"isLiveStream\">\n): PlayerAnalyticsContext {\n  const context: PlayerAnalyticsContext = {};\n  if (config.debugAdTiming) {\n    context.debugAdTiming = true;\n  }\n  if (config.isLiveStream !== undefined) {\n    context.inputStreamType = config.isLiveStream ? \"live\" : \"vod\";\n  }\n  return context;\n}\n\nexport function getClientInfo(): ClientInfo {\n  const ua = navigator.userAgent;\n  const platform = navigator.platform;\n  const vendor = navigator.vendor || \"\";\n  const maxTouchPoints = navigator.maxTouchPoints || 0;\n  const memory = (navigator as any).deviceMemory || null;\n  const hardwareConcurrency = navigator.hardwareConcurrency || 1;\n\n  const screenInfo = {\n    width: screen?.width,\n    height: screen?.height,\n    availWidth: screen?.availWidth,\n    availHeight: screen?.availHeight,\n    orientation: (screen?.orientation as any)?.type || \"\",\n    pixelDepth: screen?.pixelDepth,\n  };\n\n  let deviceType: \"tv\" | \"mobile\" | \"tablet\" | \"desktop\" = \"desktop\";\n  let brand = \"Unknown\";\n  let os = \"Unknown\";\n  let model = \"\";\n  let isSmartTV = false;\n  let isAndroid = false;\n  let isWebView = false;\n  let isWebApp = false;\n\n  if (ua.includes(\"Web0S\")) {\n    brand = \"LG\";\n    os = \"webOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const webosMatch = ua.match(/Web0S\\/([^\\s]+)/);\n    model = webosMatch ? `webOS ${webosMatch[1]}` : \"webOS TV\";\n  } else if (ua.includes(\"Tizen\")) {\n    brand = \"Samsung\";\n    os = \"Tizen\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n    const tizenMatch = ua.match(/Tizen\\/([^\\s]+)/);\n    const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? \"Smart TV\" : \"\";\n    model = tizenMatch\n      ? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()\n      : \"Tizen TV\";\n  } else if (ua.includes(\"Philips\")) {\n    brand = \"Philips\";\n    os = \"Saphi\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"Sharp\") || ua.includes(\"AQUOS\")) {\n    brand = \"Sharp\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (\n    ua.includes(\"Android\") &&\n    (ua.includes(\"Sony\") || vendor.includes(\"Sony\"))\n  ) {\n    brand = \"Sony\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (\n    ua.includes(\"Android\") &&\n    (ua.includes(\"NetCast\") || ua.includes(\"LG\"))\n  ) {\n    brand = \"LG\";\n    os = \"Android TV\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\" Roku\") || ua.includes(\"Roku/\")) {\n    brand = \"Roku\";\n    os = \"Roku OS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  } else if (ua.includes(\"AppleTV\")) {\n    brand = \"Apple\";\n    os = \"tvOS\";\n    isSmartTV = true;\n    deviceType = \"tv\";\n  }\n\n  if (ua.includes(\"Android\")) {\n    isAndroid = true;\n    os = \"Android\";\n    deviceType = /Mobile/.test(ua) ? \"mobile\" : \"tablet\";\n\n    if (\n      ua.includes(\"Android\") &&\n      (maxTouchPoints === 0 ||\n        ua.includes(\"Google TV\") ||\n        ua.includes(\"XiaoMi\"))\n    ) {\n      deviceType = \"tv\";\n      isSmartTV = true;\n      brand = brand === \"Unknown\" ? \"Android TV\" : brand;\n    }\n\n    const androidModelMatch = ua.match(/\\(([^)]*Android[^)]*)\\)/);\n    if (androidModelMatch && androidModelMatch[1]) {\n      model = androidModelMatch[1];\n    }\n  }\n\n  if (/iPad|iPhone|iPod/.test(ua)) {\n    os = \"iOS\";\n    deviceType = \"mobile\";\n    brand = \"Apple\";\n    if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {\n      deviceType = \"tablet\";\n    }\n  }\n\n  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {\n    if (ua.includes(\"Windows\")) {\n      os = \"Windows\";\n      deviceType = \"desktop\";\n    } else if (ua.includes(\"Mac\") && !/iPhone/.test(ua)) {\n      os = \"macOS\";\n      deviceType = \"desktop\";\n      if (maxTouchPoints > 1) deviceType = \"tablet\";\n    } else if (ua.includes(\"Linux\")) {\n      os = \"Linux\";\n      deviceType = \"desktop\";\n    }\n  }\n\n  if (brand === \"Unknown\") {\n    if (vendor.includes(\"Google\") || ua.includes(\"Chrome\")) brand = \"Google\";\n    if (vendor.includes(\"Apple\")) brand = \"Apple\";\n    if (vendor.includes(\"Samsung\") || ua.includes(\"SM-\")) brand = \"Samsung\";\n  }\n\n  isWebView = /wv|WebView|Linux; U;/.test(ua);\n\n  if (window?.outerHeight === 0 && window?.outerWidth === 0) {\n    isWebView = true;\n  }\n\n  isWebApp =\n    window.matchMedia(\"(display-mode: standalone)\").matches ||\n    (window.navigator as any).standalone === true ||\n    window.screen?.orientation?.angle !== undefined;\n\n  return {\n    brand,\n    os,\n    model: model || ua.substring(0, 50) + \"...\",\n    deviceType,\n    isSmartTV,\n    isAndroid,\n    isWebView,\n    isWebApp,\n    domain: window.location.hostname,\n    origin: window.location.origin,\n    path: window.location.pathname,\n    userAgent: ua,\n    vendor,\n    platform,\n    screen: screenInfo,\n    hardwareConcurrency,\n    deviceMemory: memory,\n    maxTouchPoints,\n    language: navigator.language,\n    languages: navigator.languages?.join(\",\") || \"\",\n    cookieEnabled: navigator.cookieEnabled,\n    doNotTrack: navigator.doNotTrack || \"\",\n    referrer: document.referrer,\n    visibilityState: document.visibilityState,\n  };\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n  if (typeof crypto !== \"undefined\" && crypto.subtle?.digest) {\n    try {\n      await crypto.subtle.digest(\"SHA-256\", new Uint8Array([1, 2, 3]));\n\n      let encodedData: BufferSource;\n      if (typeof TextEncoder !== \"undefined\") {\n        encodedData = new TextEncoder().encode(input);\n      } else {\n        const utf8 = unescape(encodeURIComponent(input));\n        const buffer = new Uint8Array(utf8.length);\n        for (let i = 0; i < utf8.length; i++) {\n          buffer[i] = utf8.charCodeAt(i);\n        }\n        encodedData = buffer;\n      }\n\n      const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encodedData);\n      return Array.from(new Uint8Array(hashBuffer))\n        .map((b) => b.toString(16).padStart(2, \"0\"))\n        .join(\"\");\n    } catch {\n      console.warn(\n        \"[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash\"\n      );\n    }\n  }\n\n  let hash = 0;\n  for (let i = 0; i < input.length; i++) {\n    const char = input.charCodeAt(i);\n    hash = (hash << 5) - hash + char;\n    hash = hash & hash;\n  }\n\n  const fallbackHash = Math.abs(hash).toString(16).padStart(8, \"0\");\n  const timestamp = Date.now().toString(16).padStart(12, \"0\");\n  const random = Math.random().toString(16).substring(2, 14).padStart(12, \"0\");\n\n  return (fallbackHash + timestamp + random).padEnd(64, \"0\");\n}\n\nfunction resolvePlayerIdentitySeed(clientInfo: ClientInfo): string {\n  const nativeDeviceId = resolveNativeDeviceId();\n  if (nativeDeviceId) {\n    return `device:${nativeDeviceId}`;\n  }\n\n  const persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);\n  if (persistedId) {\n    return `persisted:${persistedId}`;\n  }\n\n  return `fingerprint:${JSON.stringify(clientInfo)}`;\n}\n\nexport async function getBrowserID(clientInfo: ClientInfo): Promise<string> {\n  if (cachedBrowserId) {\n    return cachedBrowserId;\n  }\n\n  cachedBrowserId = await sha256Hex(resolvePlayerIdentitySeed(clientInfo));\n  return cachedBrowserId;\n}\n\ntype PlayerMetricFlags = {\n  adLoaded?: boolean;\n  adDetect?: boolean;\n  captureAt?: string;\n};\n\nfunction canPublish(licenseKey: string | undefined): licenseKey is string {\n  return Boolean(isMQTTEnabled() && licenseKey);\n}\n\nasync function buildPlayerMetricEvent(\n  context: PlayerAnalyticsContext = {},\n  flags: PlayerMetricFlags = {}\n): Promise<Record<string, unknown>> {\n  const clientInfo = getClientInfo();\n\n  const debugAdTiming = !!context.debugAdTiming;\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] clientInfo: \", JSON.stringify(clientInfo, null, 2));\n  }\n\n  const playerId = await getBrowserID(clientInfo);\n\n  if (debugAdTiming) {\n    console.log(\"[StormcloudVideoPlayer] playerId: \", playerId);\n  }\n\n  const captureAt = flags.captureAt ?? new Date().toISOString();\n\n  return {\n    player_id: playerId,\n    device_type: clientInfo.deviceType,\n    os: clientInfo.os.toLowerCase(),\n    ad_loaded: flags.adLoaded ?? false,\n    ad_detect: flags.adDetect ?? false,\n    capture_at: captureAt,\n    ...(context.inputStreamType\n      ? { input_stream_type: context.inputStreamType }\n      : {}),\n  };\n}\n\nfunction publishTracking(\n  licenseKey: string,\n  channel: \"metrics\" | \"impressions\" | \"heartbeat\",\n  body: Record<string, unknown>\n): void {\n  ensureMQTTClient();\n  publishMQTT(buildPlayerTopic(licenseKey, channel), body);\n}\n\nexport async function sendInitialTracking(\n  licenseKey?: string,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  if (!canPublish(licenseKey)) return;\n\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      adLoaded: false,\n      adDetect: false,\n    });\n\n    publishTracking(licenseKey, \"metrics\", {\n      events: [metricEvent],\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending initial tracking data:\",\n      error\n    );\n  }\n}\n\nexport async function sendAdDetectTracking(\n  licenseKey: string | undefined,\n  adDetectInfo: AdDetectInfo,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  try {\n    await sendHeartbeat(licenseKey, context, {\n      adDetect: true,\n      captureAt: adDetectInfo.timestamp,\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad detect tracking:\",\n      error\n    );\n  }\n}\n\nexport async function sendAdLoadedTracking(\n  licenseKey: string | undefined,\n  adLoadedInfo: AdLoadedInfo,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  try {\n    await sendHeartbeat(licenseKey, context, {\n      adLoaded: true,\n      captureAt: adLoadedInfo.timestamp,\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad loaded tracking:\",\n      error\n    );\n  }\n}\n\nexport async function sendAdImpressionTracking(\n  licenseKey: string | undefined,\n  adImpressionInfo: AdImpressionInfo,\n  context: PlayerAnalyticsContext = {}\n): Promise<void> {\n  if (!canPublish(licenseKey)) return;\n\n  try {\n    const metricEvent = await buildPlayerMetricEvent(context, {\n      captureAt: adImpressionInfo.timestamp,\n    });\n\n    publishTracking(licenseKey, \"heartbeat\", metricEvent);\n    publishTracking(licenseKey, \"impressions\", {\n      events: [\n        {\n          player_id: metricEvent.player_id,\n          ad_played_count: 1,\n          ad_url: adImpressionInfo.adUrl,\n          capture_at: adImpressionInfo.timestamp,\n        },\n      ],\n    });\n  } catch (error) {\n    console.error(\n      \"[StormcloudVideoPlayer] Error sending ad impression tracking:\",\n      error\n    );\n  }\n}\n\nexport async function sendHeartbeat(\n  licenseKey?: string,\n  context: PlayerAnalyticsContext = {},\n  flags: PlayerMetricFlags = {}\n): Promise<void> {\n  if (!canPublish(licenseKey)) return;\n\n  try {\n    const heartbeatData = await buildPlayerMetricEvent(context, flags);\n    publishTracking(licenseKey, \"heartbeat\", heartbeatData);\n  } catch (error) {\n    console.error(\"[StormcloudVideoPlayer] Error sending heartbeat:\", error);\n  }\n}\n"]}