@encorekit/web-sdk 0.1.1 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +94 -9
  2. package/dist/cjs/index.cjs +1 -1
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/esm/index.js +1 -1
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/umd/encore.min.js +1 -1
  7. package/dist/umd/encore.min.js.map +1 -1
  8. package/embed/README.md +409 -0
  9. package/embed/index.html +57 -0
  10. package/embed/styles.css +154 -0
  11. package/examples/README.md +149 -0
  12. package/examples/angular/README.md +210 -0
  13. package/examples/angular/angular.json +73 -0
  14. package/examples/angular/package.json +32 -0
  15. package/examples/angular/src/app/app.component.html +56 -0
  16. package/examples/angular/src/app/app.component.ts +114 -0
  17. package/examples/angular/src/app/encore.service.ts +83 -0
  18. package/examples/angular/src/index.html +13 -0
  19. package/examples/angular/src/main.ts +7 -0
  20. package/examples/angular/src/styles.css +225 -0
  21. package/examples/angular/tsconfig.json +33 -0
  22. package/examples/ios-webview/EncoreURLBuilder.swift +87 -0
  23. package/examples/ios-webview/EncoreWebViewBridge.swift +426 -0
  24. package/examples/ios-webview/ExampleViewController.swift +233 -0
  25. package/examples/ios-webview/README.md +416 -0
  26. package/examples/ios-webview/SimpleEncoreView.swift +94 -0
  27. package/examples/ios-webview/SimpleExample.swift +131 -0
  28. package/examples/react/README.md +186 -0
  29. package/examples/react/index.html +13 -0
  30. package/examples/react/package.json +24 -0
  31. package/examples/react/src/App.tsx +173 -0
  32. package/examples/react/src/index.css +227 -0
  33. package/examples/react/src/main.tsx +11 -0
  34. package/examples/react/src/vite-env.d.ts +2 -0
  35. package/examples/react/tsconfig.json +25 -0
  36. package/examples/react/vite.config.ts +8 -0
  37. package/examples/svelte/README.md +233 -0
  38. package/examples/svelte/index.html +13 -0
  39. package/examples/svelte/package.json +25 -0
  40. package/examples/svelte/src/App.svelte +164 -0
  41. package/examples/svelte/src/app.css +224 -0
  42. package/examples/svelte/src/main.ts +9 -0
  43. package/examples/svelte/src/vite-env.d.ts +3 -0
  44. package/examples/svelte/svelte.config.js +8 -0
  45. package/examples/svelte/tsconfig.json +16 -0
  46. package/examples/svelte/tsconfig.node.json +11 -0
  47. package/examples/svelte/vite.config.ts +8 -0
  48. package/examples/vanilla-js/README.md +271 -0
  49. package/examples/vanilla-js/index.html +421 -0
  50. package/examples/vue/README.md +212 -0
  51. package/examples/vue/index.html +13 -0
  52. package/examples/vue/package.json +22 -0
  53. package/examples/vue/src/App.vue +170 -0
  54. package/examples/vue/src/main.ts +6 -0
  55. package/examples/vue/src/style.css +224 -0
  56. package/examples/vue/src/vite-env.d.ts +2 -0
  57. package/examples/vue/tsconfig.json +25 -0
  58. package/examples/vue/vite.config.ts +8 -0
  59. package/package.json +22 -3
  60. package/types/analytics/AnalyticsClient.d.ts +14 -0
  61. package/types/analytics/AnalyticsClient.d.ts.map +1 -0
  62. package/types/analytics/events.d.ts +63 -0
  63. package/types/analytics/events.d.ts.map +1 -0
  64. package/types/analytics/models.d.ts +17 -0
  65. package/types/analytics/models.d.ts.map +1 -0
  66. package/types/api/APIClient.d.ts +44 -8
  67. package/types/api/APIClient.d.ts.map +1 -1
  68. package/types/api/endpoints.d.ts +11 -7
  69. package/types/api/endpoints.d.ts.map +1 -1
  70. package/types/api/models.d.ts +134 -68
  71. package/types/api/models.d.ts.map +1 -1
  72. package/types/core/Configuration.d.ts +4 -0
  73. package/types/core/Configuration.d.ts.map +1 -1
  74. package/types/core/Encore.d.ts +16 -12
  75. package/types/core/Encore.d.ts.map +1 -1
  76. package/types/core/EntitlementManager.d.ts +9 -0
  77. package/types/core/EntitlementManager.d.ts.map +1 -1
  78. package/types/core/OfferManager.d.ts +27 -7
  79. package/types/core/OfferManager.d.ts.map +1 -1
  80. package/types/types.d.ts +1 -1
  81. package/types/types.d.ts.map +1 -1
  82. package/types/ui/OfferCard.d.ts.map +1 -1
  83. package/types/ui/OfferCarousel.d.ts.map +1 -1
  84. package/types/ui/Tooltip.d.ts +22 -0
  85. package/types/ui/Tooltip.d.ts.map +1 -0
  86. package/types/ui/styles.d.ts.map +1 -1
  87. package/dist/cjs/index.js +0 -2
  88. package/dist/cjs/index.js.map +0 -1
  89. package/types/src/api/APIClient.d.ts +0 -63
  90. package/types/src/api/APIClient.d.ts.map +0 -1
  91. package/types/src/api/endpoints.d.ts +0 -35
  92. package/types/src/api/endpoints.d.ts.map +0 -1
  93. package/types/src/api/models.d.ts +0 -156
  94. package/types/src/api/models.d.ts.map +0 -1
  95. package/types/src/core/Configuration.d.ts +0 -42
  96. package/types/src/core/Configuration.d.ts.map +0 -1
  97. package/types/src/core/Encore.d.ts +0 -81
  98. package/types/src/core/Encore.d.ts.map +0 -1
  99. package/types/src/core/EntitlementManager.d.ts +0 -65
  100. package/types/src/core/EntitlementManager.d.ts.map +0 -1
  101. package/types/src/core/OfferManager.d.ts +0 -35
  102. package/types/src/core/OfferManager.d.ts.map +0 -1
  103. package/types/src/core/PlacementBuilder.d.ts +0 -27
  104. package/types/src/core/PlacementBuilder.d.ts.map +0 -1
  105. package/types/src/core/SignalManager.d.ts +0 -51
  106. package/types/src/core/SignalManager.d.ts.map +0 -1
  107. package/types/src/core/StorageManager.d.ts +0 -34
  108. package/types/src/core/StorageManager.d.ts.map +0 -1
  109. package/types/src/core/VerificationPoller.d.ts +0 -27
  110. package/types/src/core/VerificationPoller.d.ts.map +0 -1
  111. package/types/src/index.d.ts +0 -7
  112. package/types/src/index.d.ts.map +0 -1
  113. package/types/src/types.d.ts +0 -156
  114. package/types/src/types.d.ts.map +0 -1
  115. package/types/src/ui/OfferCard.d.ts +0 -29
  116. package/types/src/ui/OfferCard.d.ts.map +0 -1
  117. package/types/src/ui/OfferCarousel.d.ts +0 -55
  118. package/types/src/ui/OfferCarousel.d.ts.map +0 -1
  119. package/types/src/ui/OfferModal.d.ts +0 -41
  120. package/types/src/ui/OfferModal.d.ts.map +0 -1
  121. package/types/src/ui/SuccessScreen.d.ts +0 -33
  122. package/types/src/ui/SuccessScreen.d.ts.map +0 -1
  123. package/types/src/ui/styles.d.ts +0 -44
  124. package/types/src/ui/styles.d.ts.map +0 -1
  125. package/types/src/utils/eventEmitter.d.ts +0 -50
  126. package/types/src/utils/eventEmitter.d.ts.map +0 -1
  127. package/types/src/utils/focusDetection.d.ts +0 -21
  128. package/types/src/utils/focusDetection.d.ts.map +0 -1
  129. package/types/src/utils/logger.d.ts +0 -21
  130. package/types/src/utils/logger.d.ts.map +0 -1
  131. package/types/src/utils/network.d.ts +0 -57
  132. package/types/src/utils/network.d.ts.map +0 -1
  133. package/types/src/utils/uuid.d.ts +0 -10
  134. package/types/src/utils/uuid.d.ts.map +0 -1
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Encore={})}(this,function(e){"use strict";var t;!function(e){e.NETWORK_ERROR="NETWORK_ERROR",e.API_ERROR="API_ERROR",e.CONFIGURATION_ERROR="CONFIGURATION_ERROR",e.INITIALIZATION_ERROR="INITIALIZATION_ERROR",e.STORAGE_ERROR="STORAGE_ERROR",e.INVALID_REQUEST="INVALID_REQUEST",e.UNAUTHORIZED="UNAUTHORIZED",e.NOT_FOUND="NOT_FOUND",e.TIMEOUT="TIMEOUT",e.UNKNOWN_ERROR="UNKNOWN_ERROR"}(t||(t={}));const n="[Encore SDK]",i=new class{#e="none";setLogLevel(e){this.#e=e}getLogLevel(){return this.#e}debug(...e){"debug"===this.#e&&console.debug(n,...e)}info(...e){"debug"===this.#e&&console.info(n,...e)}warn(...e){"debug"===this.#e&&console.warn(n,...e)}error(...e){"debug"===this.#e&&console.error(n,...e)}critical(...e){console.error(n,"[CRITICAL]",...e)}};class r{#t=null;#n=!1;configure(e){if(this.#n)return i.warn("SDK already configured. Ignoring subsequent configure() call."),!1;const t=this.#i(e);if(t)return i.error("Invalid configuration:",t),!1;const n=e.logLevel??"none",r=e.environment??"production";return this.#t={apiKey:e.apiKey,userId:e.userId,environment:r,baseURL:this.#r(r),logLevel:n,uiConfiguration:e.uiConfiguration??{}},i.setLogLevel(n),this.#n=!0,i.debug("SDK configured successfully",this.#t),!0}#i(e){return e.apiKey&&"string"==typeof e.apiKey&&""!==e.apiKey.trim()?e.environment&&!["production","localhost"].includes(e.environment)?"environment must be 'production' or 'localhost'":e.logLevel&&!["none","debug"].includes(e.logLevel)?"logLevel must be 'none' or 'debug'":null:"apiKey is required and must be a non-empty string"}#r(e){return"localhost"===e?"http://localhost:8080/encore/v1":"https://svc.joinyaw.com/product/encore/v1"}getConfig(){return this.#t}isConfigured(){return this.#n}getApiKey(){return this.#t?.apiKey??null}getBaseURL(){return this.#t?.baseURL??null}getEnvironment(){return this.#t?.environment??null}getUIConfiguration(){return this.#t?.uiConfiguration??{}}reset(){this.#t=null,this.#n=!1,i.debug("Configuration reset")}}const s="encore_";class o{#s;#o;constructor(){this.#o=new Map,this.#s=this.#a(),i.debug(`StorageManager initialized with ${this.#s}`)}#a(){return this.#l("localStorage")?"localStorage":this.#l("sessionStorage")?"sessionStorage":(i.warn("Neither localStorage nor sessionStorage available, using in-memory storage"),"memory")}#l(e){try{const t="localStorage"===e?localStorage:sessionStorage,n="__encore_test__";return t.setItem(n,"test"),t.removeItem(n),!0}catch{return!1}}#c(){return"localStorage"===this.#s?localStorage:"sessionStorage"===this.#s?sessionStorage:this.#o}#d(e){return`${s}${e}`}set(e,t){if(void 0===t)return void i.warn(`Attempted to store undefined value for key: ${e}`);const n=this.#d(e),r=JSON.stringify(t);try{const t=this.#c();t instanceof Map?t.set(n,r):t.setItem(n,r),i.debug(`Stored ${e} in ${this.#s}`)}catch(e){e instanceof Error&&"QuotaExceededError"===e.name?i.error("Storage quota exceeded:",e):i.error("Failed to store item:",e),"memory"!==this.#s&&(i.warn("Falling back to memory storage for this item"),this.#o.set(n,r))}}get(e){const t=this.#d(e);try{const n=this.#c();let r=null;return r=n instanceof Map?n.get(t)??null:n.getItem(t),null===r||"undefined"===r?("undefined"===r&&(i.warn(`Found corrupted value "undefined" for key: ${e}, cleaning up`),this.remove(e)),null):JSON.parse(r)}catch(t){return i.error(`Failed to retrieve ${e}:`,t),this.remove(e),null}}remove(e){const t=this.#d(e);try{const n=this.#c();n instanceof Map?n.delete(t):n.removeItem(t),i.debug(`Removed ${e} from ${this.#s}`)}catch(t){i.error(`Failed to remove ${e}:`,t)}}clear(){try{const e=this.#c();if(e instanceof Map)for(const t of e.keys())t.startsWith(s)&&e.delete(t);else{const t=[];for(let n=0;n<e.length;n++){const i=e.key(n);i?.startsWith(s)&&t.push(i)}t.forEach(t=>e.removeItem(t))}i.debug(`Cleared all Encore data from ${this.#s}`)}catch(e){i.error("Failed to clear storage:",e)}}getStorageType(){return this.#s}}class a{#u;constructor(){this.#u=new Map}on(e,t){this.#u.has(e)||this.#u.set(e,new Set);const n=this.#u.get(e);if(!n)throw new Error(`Failed to get handlers for event '${String(e)}'`);return n.add(t),i.debug(`Event listener added for '${String(e)}'`),()=>{this.off(e,t)}}off(e,t){const n=this.#u.get(e);n&&(n.delete(t),i.debug(`Event listener removed for '${String(e)}'`),0===n.size&&this.#u.delete(e))}emit(e,t){const n=this.#u.get(e);if(n&&0!==n.size){i.debug(`Emitting event '${String(e)}'`,{listenerCount:n.size});for(const r of n)try{r(t)}catch(t){i.error(`Error in event handler for '${String(e)}':`,t)}}}removeAllListeners(e){e?(this.#u.delete(e),i.debug(`All listeners removed for '${String(e)}'`)):(this.#u.clear(),i.debug("All event listeners removed"))}listenerCount(e){return this.#u.get(e)?.size??0}hasListeners(e){const t=this.#u.get(e);return void 0!==t&&t.size>0}}const l="entitlements",c="entitlements_timestamp";class d{#h;#f;#g;#m=null;#p=null;#b;constructor(e,t,n){this.#h=e,this.#f=t,this.#g=n,this.#b=new a,this.#v()}getEventEmitter(){return this.#b}setUserId(e){this.#g!==e&&(i.debug("EntitlementManager: User ID changed, clearing cache"),this.#g=e,this.#m=null,this.#v())}#v(){try{const e=`${this.#g}_${l}`,t=`${this.#g}_${c}`,n=this.#h.get(e),r=this.#h.get(t);n&&r&&(this.#m={entitlements:n,timestamp:r},i.debug("Loaded entitlements from storage",{count:n.length,age:Date.now()-r}))}catch(e){i.error("Failed to load entitlements from storage:",e)}}saveEntitlements(e){try{Array.isArray(e)||(i.warn("saveEntitlements called with non-array value, defaulting to empty array"),e=[]);const t=this.loadEntitlements(),n=Date.now(),r=`${this.#g}_${l}`,s=`${this.#g}_${c}`;this.#h.set(r,e),this.#h.set(s,n),this.#m={entitlements:e,timestamp:n},i.debug("Saved entitlements to storage",{count:e.length}),this.#y(t,e)}catch(e){i.error("Failed to save entitlements to storage:",e)}}#y(e,t){Array.isArray(e)||(e=[]),Array.isArray(t)||(t=[]);const n=new Map;for(const t of e){const e=`${String(t.type)}_${t.scope}`;n.set(e,t)}const i=new Map;for(const e of t){const t=`${String(e.type)}_${e.scope}`;i.set(t,e)}for(const[e,t]of i){const i=n.get(e);i&&JSON.stringify(i)===JSON.stringify(t)||this.#b.emit("entitlementChanged",{entitlementType:this.#x(t),scope:t.scope,isActive:this.#w(t),entitlement:t})}for(const[e,t]of n)i.has(e)||this.#b.emit("entitlementChanged",{entitlementType:this.#x(t),scope:t.scope,isActive:!1})}#x(e){const{scope:t,expiresAt:n,grantedAt:i,transactionId:r,...s}=e;return s}#w(e){return!e.expiresAt||new Date(e.expiresAt)>new Date}loadEntitlements(){return this.#m?.entitlements??[]}isCacheStale(){return!this.#m||Date.now()-this.#m.timestamp>3e5}getCacheAge(){return this.#m?Date.now()-this.#m.timestamp:null}clearCache(){this.#m=null,this.#b.removeAllListeners();const e=`${this.#g}_${l}`,t=`${this.#g}_${c}`;this.#h.remove(e),this.#h.remove(t),i.debug("Cleared entitlement cache")}isActive(e,t="all"){const n=this.loadEntitlements();for(const i of n){const n=this.#x(i);if(this.#I(n,e)&&("verified"!==t||"verified"===i.scope)){if(i.expiresAt&&new Date(i.expiresAt)<=new Date)continue;return!0}}return!1}#I(e,t){return JSON.stringify(e)===JSON.stringify(t)}getActiveEntitlements(e="all"){const t=this.loadEntitlements(),n=new Date;return t.filter(t=>("verified"!==e||"verified"===t.scope)&&!(t.expiresAt&&new Date(t.expiresAt)<=n))}async refreshEntitlements(){if(this.#p)return i.debug("Refresh already in progress, waiting..."),this.#p;this.#p=this.#E();try{await this.#p}finally{this.#p=null}}async#E(){try{i.debug("Refreshing entitlements from API");const e=await this.#f.fetchEntitlements(this.#g);if(!Array.isArray(e))return i.warn("Received non-array entitlements from API, defaulting to empty array"),void this.saveEntitlements([]);this.saveEntitlements(e),i.info("Entitlements refreshed successfully",{count:e.length})}catch(e){i.error("Failed to refresh entitlements, keeping cached version:",e)}}}const u="signal_queue";class h{#h;#f;#g;#C=[];#$=!1;#k;constructor(e,t,n){this.#h=e,this.#f=t,this.#g=n,this.#A(),this.#T(),this.processQueue()}setUserId(e){this.#g!==e&&(i.debug("SignalManager: User ID changed, clearing queue"),this.#g=e,this.#C=[],this.#A())}#A(){try{const e=`${this.#g}_${u}`,t=this.#h.get(e);t&&Array.isArray(t)&&(this.#C=t,i.debug("Loaded grant signal queue from storage",{count:t.length}))}catch(e){i.error("Failed to load grant signal queue from storage:",e)}}#N(){try{const e=`${this.#g}_${u}`;this.#h.set(e,this.#C),i.debug("Saved grant signal queue to storage",{count:this.#C.length})}catch(e){i.error("Failed to save grant signal queue to storage:",e)}}enqueue(e,t){const n=this.#C.some(n=>n.transactionId===e&&n.grantType===t);if(n)return void i.debug("Grant signal already in queue, skipping",{transactionId:e,grantType:t});const r={transactionId:e,grantType:t,timestamp:(new Date).toISOString(),attempts:0};this.#C.push(r),this.#N(),i.info("Grant signal added to queue",{transactionId:e,grantType:t})}dequeue(e){const t=this.#C.findIndex(t=>t.transactionId===e.transactionId&&t.grantType===e.grantType);-1!==t&&(this.#C.splice(t,1),this.#N(),i.debug("Grant signal removed from queue",{transactionId:e.transactionId,grantType:e.grantType}))}getQueue(){return[...this.#C]}clearQueue(){this.#C=[],this.#N(),i.debug("Grant signal queue cleared")}async sendGrantSignal(e,t){try{if(i.debug("Sending grant signal",{transactionId:e,grantType:t}),!await this.#f.sendGrantSignal(e,t))throw new Error("Grant signal failed (returned false)");i.info("Grant signal sent successfully",{transactionId:e,grantType:t})}catch{i.warn("Failed to send grant signal, adding to queue",{transactionId:e,grantType:t}),this.enqueue(e,t)}}async processQueue(){if(this.#$)i.debug("Queue processing already in progress, skipping");else if(0!==this.#C.length){this.#$=!0,i.info("Processing grant signal queue",{count:this.#C.length});try{for(const e of[...this.#C])await this.#S(e),this.#C.length>1&&await this.#R(100)}finally{this.#$=!1}}}async#S(e){if(e.attempts>=3)return i.error("Grant signal max attempts reached, removing from queue",{transactionId:e.transactionId,grantType:e.grantType,attempts:e.attempts}),void this.dequeue(e);if(e.lastAttemptAt){const t=new Date(e.lastAttemptAt).getTime(),n=Date.now(),r=1e3*Math.pow(2,e.attempts-1),s=n-t;if(s<r)return void i.debug("Skipping signal, waiting for backoff period",{transactionId:e.transactionId,remainingWait:r-s})}e.attempts++,e.lastAttemptAt=(new Date).toISOString(),this.#N();try{i.debug("Attempting to send queued grant signal",{transactionId:e.transactionId,grantType:e.grantType,attempt:e.attempts}),await this.#f.sendGrantSignal(e.transactionId,e.grantType)?(i.info("Queued grant signal sent successfully",{transactionId:e.transactionId,grantType:e.grantType}),this.dequeue(e)):i.warn("Grant signal failed, will retry",{transactionId:e.transactionId,attempt:e.attempts})}catch(t){i.warn("Failed to send queued grant signal, will retry",{transactionId:e.transactionId,attempt:e.attempts,error:t})}}#T(){this.#k=function(e){const t=()=>{i.debug("Network status: online"),e()};return window.addEventListener("online",t),()=>{window.removeEventListener("online",t)}}(()=>{i.debug("Network came online, processing grant signal queue"),this.processQueue()})}destroy(){this.#k&&(this.#k(),this.#k=void 0)}#R(e){return new Promise(t=>setTimeout(t,e))}}class f{#f;#g;#L=[];#M=null;#O=null;constructor(e,t){this.#f=e,this.#g=t}async fetchOffers(e,t=!0){if(t&&this.#L.length>0&&this.#O)return i.debug("Using cached offers",{count:this.#L.length}),{offers:[...this.#L],uiConfiguration:this.#M??void 0};try{i.debug("Fetching offers from API",{userId:this.#g});const t=await this.#f.fetchOffers(this.#g,e);return 0===t.offers?.length?(i.info("No offers available for user"),this.#L=[],this.#M=t.uiConfiguration??null,this.#O=Date.now(),{offers:[],uiConfiguration:t.uiConfiguration}):(this.#L=t.offers,this.#M=t.uiConfiguration??null,this.#O=Date.now(),i.info("Offers fetched successfully",{count:t.offers.length,offerIds:t.offers.map(e=>e.id)}),{offers:[...t.offers],uiConfiguration:t.uiConfiguration})}catch(e){throw i.error("Failed to fetch offers",e),e}}logImpression(e,t){try{const n=window.location.hostname;i.debug("Logging impression",{impressionId:e,campaignId:t.campaignId,creativeId:t.creativeId,appBundleId:n}),this.#f.logImpression(e,this.#g,t.campaignId,t.creativeId,n).then(t=>{t&&i.debug("Impression logged successfully",{impressionId:e})}).catch(t=>{i.error("Failed to log impression (non-blocking)",{impressionId:e,error:t})})}catch(t){i.error("Failed to log impression (non-blocking)",{impressionId:e,error:t})}}async startTransaction(e,t,n){try{i.debug("Starting transaction",{campaignId:e,creativeId:t,impressionId:n});const r=await this.#f.startTransaction(e,this.#g,t,n);return i.info("Transaction started",{transactionId:r,campaignId:e,creativeId:t}),r}catch(n){throw i.error("Failed to start transaction",{campaignId:e,creativeId:t,error:n}),n}}clearCache(){this.#L=[],this.#O=null,i.debug("Offer cache cleared")}setUserId(e){this.#g=e,this.clearCache(),i.debug("OfferManager user ID updated",{userId:e})}}class g{#f;#F;#U;#D=0;#B=1e3;#q=8e3;#K=null;#P=!1;constructor(e,t){this.#f=e,this.#F=t.transactionId,this.#U=t.timeout??3e4}async poll(){return this.#P?(i.warn("Verification polling already in progress",{transactionId:this.#F}),"pending"):(this.#P=!0,this.#D=Date.now(),i.debug("Starting verification polling",{transactionId:this.#F,timeout:this.#U}),this.#_())}stop(){this.#P=!1,null!==this.#K&&(clearTimeout(this.#K),this.#K=null),i.debug("Verification polling stopped",{transactionId:this.#F})}async#_(){for(;this.#P;){const e=Date.now()-this.#D;if(e>=this.#U)return i.warn("Verification polling timeout",{transactionId:this.#F,elapsed:e}),this.stop(),"pending";try{const e=await this.#f.checkVerificationStatus(this.#F);if(i.debug("Verification status checked",{transactionId:this.#F,status:e.status}),"verified"===e.status)return i.info("Transaction verified",{transactionId:this.#F,verifiedAt:e.verifiedAt}),this.stop(),"verified";if("failed"===e.status)return i.warn("Transaction failed verification",{transactionId:this.#F}),this.stop(),"failed";await this.#R(this.#B),this.#B=Math.min(2*this.#B,this.#q)}catch(e){i.error("Error checking verification status",{transactionId:this.#F,error:e}),await this.#R(this.#B)}}return"pending"}async#R(e){return new Promise(t=>{this.#K=window.setTimeout(()=>{this.#K=null,t()},e)})}}class m{#z=null;#G=null;#j=null;#H;constructor(e){this.#H=e}onGranted(e){return this.#z=e,this}onNotGranted(e){return this.#G=e,this}onLoadingStateChange(e){return this.#j=e,this}async show(){try{this.#j&&this.#j(!0),i.debug("PlacementBuilder: Executing presentation");const e=await this.#H();return this.#j&&this.#j(!1),e.granted&&e.entitlement&&this.#z?this.#z(e.entitlement):!e.granted&&this.#G&&e.reason&&this.#G(e.reason),e}catch(e){this.#j&&this.#j(!1),i.error("PlacementBuilder: Error during presentation",e);const n={type:"error",error:{code:t.UNKNOWN_ERROR,message:e instanceof Error?e.message:"Unknown error"}};return this.#G&&this.#G(n),{granted:!1,reason:n}}}}function p(e,t){let n=e;for(const[e,i]of Object.entries(t))n=n.replace(`:${e}`,encodeURIComponent(i));return n}class b{#V;#Q;#W;constructor(e,t){this.#V=e,this.#Q=t,this.#W=new Map}setApiKey(e){this.#V=e}setBaseURL(e){this.#Q=e}async get(e,t){return this.#J({url:`${this.#Q}${e}`,options:{method:"GET",...t},apiKey:this.#V})}async post(e,t,n){return this.#J({url:`${this.#Q}${e}`,options:{method:"POST",body:t,...n},apiKey:this.#V})}async#J(e){const{url:t,options:n,apiKey:r}=e,s=this.#Y(t,n),o=this.#W.get(s);if(o)return i.debug("Deduplicating request:",t),o;const a=this.#Z(t,n,r);this.#W.set(s,a);try{return await a}finally{this.#W.delete(s)}}async#Z(e,t,n){const r=t.retries??3;let s=null;for(let o=0;o<=r;o++)try{if(o>0){const e=1e3*Math.pow(2,o-1);i.debug(`Retrying request (attempt ${o}/${r}) after ${e}ms`),await this.#R(e)}return await this.#X(e,t,n)}catch(e){if(s=e,this.#ee(e))throw e;if(o===r)throw i.error(`Request failed after ${r} retries:`,e),e;i.warn("Request failed, will retry:",e)}throw s??new Error("Request failed")}async#X(e,t,n){const r=t.timeout??3e4,s=new AbortController,o=setTimeout(()=>s.abort(),r);try{const r={"X-API-Key":n,"Content-Type":"application/json","User-Agent":"Encore-Web-SDK/0.1.0",...t.headers},o={method:t.method,headers:r,signal:s.signal};t.body&&(o.body=JSON.stringify(t.body)),i.debug(`${t.method} ${e}`);const a=await fetch(e,o);return a.ok||await this.#te(a),await a.json()}catch(e){if(e instanceof Error){if("AbortError"===e.name)throw new Error("Request timeout");if(this.#ne(e))throw new Error(`Network error: ${e.message}`)}if(e instanceof Error)throw e;throw new Error(String(e))}finally{clearTimeout(o)}}async#te(e){let n,i=`HTTP ${e.status}: ${e.statusText}`;try{const t=await e.json();if("object"==typeof t&&null!==t&&"error"in t&&"object"==typeof t.error&&null!==t.error){const e=t.error;i=("string"==typeof e.message?e.message:void 0)??i,n="string"==typeof e.code?e.code:void 0}}catch{}const r=n?{code:n,message:i}:{code:t.API_ERROR,statusCode:e.status,message:i},s=new Error(i);throw Object.assign(s,r),s}#ee(e){if("object"==typeof e&&null!==e&&"statusCode"in e&&void 0!==e.statusCode){const t=e.statusCode;return t>=400&&t<500}return!1}#ne(e){return e.message.includes("fetch")||e.message.includes("network")||e.message.includes("ECONNREFUSED")||e.message.includes("ETIMEDOUT")}#Y(e,t){const n=t.body?JSON.stringify(t.body):"";return`${t.method}:${e}:${n}`}#R(e){return new Promise(t=>setTimeout(t,e))}async fetchOffers(e,t){try{const n=await this.post("/offers/show",{userId:e,attributes:t}),i=[];for(const e of n.offers){const t=e.campaign;for(const e of t.creatives){const n={id:e.id,title:e.title,description:e.quickInstructions||e.subtitle||e.description||"",imageUrl:e.primaryImageUrl,ctaText:e.ctaText,advertiserUrl:e.destinationUrl,campaignId:t.id,creativeId:e.id,entitlement:{type:"credit",value:100,unit:"dollars"},...t.merchantName&&{merchantName:t.merchantName},...e.logoUrl&&{logoUrl:e.logoUrl},...e.instructions&&{instructions:e.instructions},...e.quickInstructions&&{quickInstructions:e.quickInstructions},...e.trackingParameters&&{trackingParameters:e.trackingParameters}};i.push(n)}}return{offers:i,uiConfiguration:n.uiConfiguration}}catch(e){throw i.error("Failed to fetch offers:",e),e}}async startTransaction(e,t,n,r){try{return(await this.post("/transactions/start",{campaignId:e,userId:t,creativeId:n,...r&&{impressionId:r}})).transactionId}catch(e){throw i.error("Failed to start transaction:",e),e}}async sendGrantSignal(e,t){try{const n=function(e){return p("/transactions/:id/grant",{id:e})}(e);return(await this.post(n,{transactionId:e,grantType:t,timestamp:(new Date).toISOString()})).success}catch(e){throw i.error("Failed to send grant signal:",e),e}}#ie(e){switch(e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase())){case"freeTrial":return{type:"freeTrial"};case"discount":return{type:"discount"};case"credit":return{type:"credit"};default:return i.warn(`Unknown entitlement type: ${e}, treating as freeTrial`),{type:"freeTrial"}}}async fetchEntitlements(e){try{const t=await this.get(`/entitlements?userId=${encodeURIComponent(e)}`),n=[];if(t.provisional)for(const[e,i]of Object.entries(t.provisional)){const t=this.#ie(e);n.push({...t,transactionId:"",scope:"provisional",grantedAt:i.started_at,expiresAt:i.expires_at})}if(t.verified)for(const[e,i]of Object.entries(t.verified)){const t=this.#ie(e);n.push({...t,transactionId:"",scope:"verified",grantedAt:i.started_at,expiresAt:i.expires_at})}return i.debug("Transformed entitlements response",{provisionalCount:Object.keys(t.provisional||{}).length,verifiedCount:Object.keys(t.verified||{}).length,totalCount:n.length}),n}catch(e){throw i.error("Failed to fetch entitlements:",e),e}}async checkVerificationStatus(e){try{const t=function(e){return p("/verification/status/:id",{id:e})}(e);return await this.get(t)}catch(e){throw i.error("Failed to check verification status:",e),e}}async logImpression(e,t,n,r,s){try{return(await this.post("/impressions/log",{impressionId:e,userId:t,campaignId:n,creativeId:r,appBundleId:s})).success}catch(e){return i.warn("Failed to log impression (non-blocking):",e),!1}}}const v="encore-sdk-styles",y="encore-";function x(e={}){if(document.getElementById(v))i.debug("Encore styles already injected");else try{const t=document.createElement("style");t.id=v,t.textContent=function(e={}){const t=function(e){const t=[];return e.primaryColor&&t.push(`--encore-primary-color: ${e.primaryColor};`),e.backgroundColor&&t.push(`--encore-bg-color: ${e.backgroundColor};`),e.textColor&&t.push(`--encore-text-color: ${e.textColor};`),e.borderRadius&&t.push(`--encore-border-radius: ${e.borderRadius};`),e.fontFamily&&t.push(`--encore-font-family: ${e.fontFamily};`),t.join("\n ")}(e);return`\n /* CSS Custom Properties (Theme Variables) */\n :root {\n ${t||"/* No custom theme variables */"}\n --encore-primary-color: ${e.primaryColor??"#4F46E5"};\n --encore-bg-color: ${e.backgroundColor??"#ffffff"};\n --encore-text-color: ${e.textColor??"#1F2937"};\n --encore-border-radius: ${e.borderRadius??"12px"};\n --encore-font-family: ${e.fontFamily??'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'};\n }\n\n /* Backdrop */\n .${y}backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.55);\n backdrop-filter: blur(2px);\n z-index: 9998;\n opacity: 0;\n transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .${y}backdrop.${y}visible {\n opacity: 1;\n }\n\n /* Modal Container */\n .${y}modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 9999;\n background-color: var(--encore-bg-color);\n border-radius: 20px;\n box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.18), 0 12px 24px -8px rgba(0, 0, 0, 0.08);\n max-width: 800px;\n max-height: 90vh;\n width: calc(100% - 32px);\n overflow-x: hidden;\n overflow-y: auto;\n opacity: 0;\n transform: translate(-50%, -50%) scale(0.96);\n transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms cubic-bezier(0.4, 0, 0.2, 1);\n font-family: var(--encore-font-family);\n color: var(--encore-text-color);\n }\n\n .${y}modal.${y}visible {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n\n /* Close Button */\n .${y}close-button {\n position: absolute;\n top: 20px;\n right: 20px;\n width: 40px;\n height: 40px;\n border: none;\n background-color: rgba(255, 255, 255, 0.9);\n cursor: pointer;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #9CA3AF;\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n z-index: 10;\n }\n\n .${y}close-button:hover {\n background-color: #FFFFFF;\n color: #6B7280;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n transform: scale(1.05);\n }\n\n .${y}close-button:active {\n transform: scale(0.98);\n }\n\n .${y}close-button:focus {\n outline: 2px solid var(--encore-primary-color);\n outline-offset: 2px;\n }\n\n .${y}close-button svg {\n width: 18px;\n height: 18px;\n }\n\n /* Body scroll lock */\n body.${y}no-scroll {\n overflow: hidden;\n }\n\n /* Modal Header */\n .${y}modal-header {\n padding: 24px 24px 16px;\n border-bottom: 1px solid #E5E7EB;\n }\n\n .${y}modal-title {\n margin: 0;\n font-size: 24px;\n font-weight: 700;\n line-height: 1.25;\n color: var(--encore-text-color);\n }\n\n .${y}modal-subtitle {\n margin: 8px 0 0;\n font-size: 14px;\n color: #6B7280;\n line-height: 1.5;\n }\n\n /* Modal Body */\n .${y}modal-body {\n padding: 0;\n position: relative;\n isolation: isolate;\n }\n\n /* Carousel Container */\n .${y}carousel {\n display: flex;\n flex-direction: column;\n overflow: visible;\n }\n\n /* Carousel Header */\n .${y}carousel-header {\n padding: 40px 68px 28px;\n text-align: center;\n }\n\n .${y}carousel-title {\n font-size: 32px;\n font-weight: 510;\n line-height: 1.1;\n color: #181417;\n margin: 0 0 8px 0;\n letter-spacing: -0.3px;\n }\n\n .${y}carousel-subtitle {\n font-size: 16px;\n line-height: 1.2;\n color: #181417;\n margin: 0;\n font-weight: 400;\n }\n\n /* Carousel Cards Container - Horizontal Scroll */\n .${y}carousel-cards {\n display: flex;\n flex-direction: row;\n overflow-x: auto;\n overflow-y: hidden;\n scroll-behavior: smooth;\n scroll-snap-type: x mandatory;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n gap: 24px;\n padding: 24px 78px;\n position: relative;\n }\n\n .${y}carousel-cards::-webkit-scrollbar {\n display: none;\n }\n\n /* Carousel Item Wrapper */\n .${y}carousel-item {\n flex: 0 0 426px;\n width: 426px;\n scroll-snap-align: center;\n scroll-snap-stop: always;\n opacity: 0.5;\n transition: all 400ms cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: auto;\n }\n\n /* Active carousel item */\n .${y}carousel-item.${y}active {\n opacity: 1;\n z-index: 1;\n }\n\n /* Offer Card */\n .${y}offer-card {\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: 16px;\n box-shadow: 0 2px 12px rgba(116, 112, 133, 0.16);\n height: 370px;\n overflow: hidden;\n }\n\n /* Offer Banner */\n .${y}offer-banner {\n width: 100%;\n background-color: transparent;\n position: relative;\n padding: 0;\n height: 180px;\n overflow: hidden;\n border-radius: 16px 16px 0 0;\n }\n\n .${y}offer-banner-image {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n background-color: #F9FAFB;\n opacity: 0;\n transition: opacity 200ms ease-out;\n }\n\n .${y}offer-banner-image.${y}loaded {\n opacity: 1;\n }\n\n /* Info button on banner */\n .${y}banner-info-button {\n position: absolute;\n top: 20px;\n right: 20px;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background-color: rgba(242, 242, 242, 0.95);\n backdrop-filter: blur(6px);\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 150ms ease;\n z-index: 3;\n padding: 0;\n }\n\n .${y}banner-info-button:hover {\n background-color: #F2F2F2;\n transform: scale(1.05);\n }\n\n .${y}banner-info-button:focus {\n outline: 2px solid #5671FF;\n outline-offset: 2px;\n }\n\n .${y}banner-info-button svg {\n width: 14px;\n height: 14px;\n color: #181417;\n stroke-width: 2;\n }\n\n /* Offer Details */\n .${y}offer-details {\n padding: 16px 20px;\n flex: 1;\n overflow-y: auto;\n }\n\n .${y}offer-details-heading {\n font-size: 14px;\n font-weight: 400;\n color: #6A6D81;\n margin: 0 0 8px 0;\n letter-spacing: -1px;\n line-height: 1.2;\n }\n\n .${y}offer-details-list {\n list-style: disc;\n margin: 0;\n padding: 0 0 0 21px;\n }\n\n .${y}offer-details-list li {\n font-size: 14px;\n line-height: 1.2;\n color: #181417;\n margin-bottom: 4px;\n padding-left: 0;\n letter-spacing: -1px;\n }\n\n .${y}offer-details-list li:last-child {\n margin-bottom: 0;\n }\n\n .${y}offer-details-list li::marker {\n color: #6A6D81;\n }\n\n /* Offer Footer */\n .${y}offer-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-top: 1px solid #F2F2F2;\n gap: 12px;\n min-height: 74px;\n }\n\n /* Offer Merchant */\n .${y}offer-merchant {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n }\n\n .${y}offer-logo {\n width: 42px;\n height: 42px;\n border-radius: 8px;\n object-fit: contain;\n background-color: #F3F4F6;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 200ms ease-out;\n }\n\n .${y}offer-logo.${y}loaded {\n opacity: 1;\n }\n\n .${y}offer-merchant-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex: 1;\n min-width: 0;\n }\n\n .${y}offer-merchant-name {\n font-size: 16px;\n font-weight: 590;\n color: #181417;\n line-height: 1.1;\n letter-spacing: -1px;\n }\n\n .${y}offer-merchant-desc {\n font-size: 14px;\n color: #6A6D81;\n line-height: 1.2;\n letter-spacing: -1px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* Claim Button */\n .${y}button-claim {\n padding: 10px 16px;\n height: 34px;\n min-width: 78px;\n font-size: 14px;\n font-weight: 590;\n border-radius: 999px;\n border: none;\n background: #5671FF;\n color: white;\n cursor: pointer;\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n font-family: var(--encore-font-family);\n white-space: nowrap;\n line-height: 1.2;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .${y}button-claim:hover:not(:disabled) {\n background: #4560E6;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(86, 113, 255, 0.3);\n }\n\n .${y}button-claim:active {\n transform: translateY(0);\n background: #3A52CC;\n }\n\n .${y}button-claim:focus {\n outline: 2px solid #5671FF;\n outline-offset: 2px;\n }\n\n .${y}button-claim:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n\n /* Carousel Navigation */\n .${y}carousel-navigation {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 40px;\n padding: 28px 32px 32px;\n }\n\n .${y}nav-button {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 1px solid #BBBBBB;\n background-color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #BBBBBB;\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n }\n\n .${y}nav-button:hover:not(:disabled) {\n border-color: #5671FF;\n color: #5671FF;\n transform: scale(1.05);\n }\n\n .${y}nav-button:active:not(:disabled) {\n transform: scale(0.95);\n }\n\n .${y}nav-button:focus {\n outline: 2px solid #5671FF;\n outline-offset: 2px;\n }\n\n .${y}nav-button svg {\n width: 20px;\n height: 20px;\n stroke-width: 2;\n }\n\n .${y}nav-button:not(:disabled) {\n border-color: #5671FF;\n color: #5671FF;\n }\n\n .${y}nav-button:disabled,\n .${y}nav-button.${y}disabled {\n opacity: 1;\n cursor: not-allowed;\n border-color: #BBBBBB;\n color: #BBBBBB;\n }\n\n .${y}nav-button:disabled:hover,\n .${y}nav-button.${y}disabled:hover {\n border-color: #BBBBBB;\n color: #BBBBBB;\n transform: none;\n }\n\n /* Loading State */\n .${y}loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px;\n }\n\n .${y}spinner {\n width: 40px;\n height: 40px;\n border: 3px solid #E5E7EB;\n border-top-color: var(--encore-primary-color);\n border-radius: 50%;\n animation: ${y}spin 0.8s linear infinite;\n }\n\n @keyframes ${y}spin {\n to { transform: rotate(360deg); }\n }\n\n /* Responsive: Mobile (0-767px) */\n @media (max-width: 767px) {\n .${y}modal {\n width: calc(100% - 24px);\n max-width: 100%;\n margin: 12px;\n }\n\n .${y}carousel-header {\n padding: 24px 20px 20px;\n }\n\n .${y}carousel-title {\n font-size: 22px;\n }\n\n .${y}carousel-subtitle {\n font-size: 14px;\n }\n\n .${y}carousel-cards {\n padding: 20px 40px;\n }\n\n .${y}carousel-item {\n flex: 0 0 calc(100% - 80px);\n }\n\n .${y}offer-banner {\n padding: 16px 16px 0;\n }\n\n .${y}offer-details {\n padding: 20px 20px;\n }\n\n .${y}offer-footer {\n padding: 16px 20px 24px;\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .${y}offer-merchant {\n flex: 1 1 100%;\n }\n\n .${y}button-claim {\n flex: 1 1 100%;\n }\n\n .${y}carousel-navigation {\n padding: 20px 20px 24px;\n }\n }\n\n /* Responsive: Tablet (768-1023px) */\n @media (min-width: 768px) and (max-width: 1023px) {\n .${y}modal {\n max-width: 600px;\n }\n }\n\n /* Responsive: Desktop (1024px+) */\n @media (min-width: 1024px) {\n .${y}modal {\n max-width: 600px;\n }\n }\n\n /* Accessibility: High Contrast Mode */\n @media (prefers-contrast: high) {\n .${y}button {\n border: 2px solid currentColor;\n }\n }\n\n /* Accessibility: Reduced Motion */\n @media (prefers-reduced-motion: reduce) {\n .${y}backdrop,\n .${y}modal,\n .${y}button,\n .${y}close-button {\n transition: none;\n }\n\n .${y}spinner {\n animation: none;\n }\n }\n\n /* Focus Visible (for keyboard navigation) */\n .${y}button:focus-visible,\n .${y}close-button:focus-visible {\n outline: 2px solid var(--encore-primary-color);\n outline-offset: 2px;\n }\n\n /* ===== Success Screen ===== */\n .${y}success-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem 2rem;\n text-align: center;\n min-height: 400px;\n animation: ${y}fade-in 0.3s ease-out;\n }\n\n .${y}success-icon {\n width: 80px;\n height: 80px;\n background: linear-gradient(135deg, var(--encore-primary-color), #10b981);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 48px;\n color: white;\n margin-bottom: 1.5rem;\n animation: ${y}scale-in 0.5s ease-out;\n }\n\n .${y}success-title {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--encore-text-color);\n margin: 0 0 0.75rem 0;\n }\n\n .${y}success-subtitle {\n font-size: 1.125rem;\n color: var(--encore-text-muted);\n margin: 0 0 2rem 0;\n line-height: 1.6;\n }\n\n .${y}success-details {\n background: rgba(79, 70, 229, 0.05);\n border-radius: 12px;\n padding: 1.5rem;\n margin-bottom: 2rem;\n min-width: 280px;\n }\n\n .${y}success-detail {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.5rem 0;\n }\n\n .${y}success-detail:not(:last-child) {\n border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n }\n\n .${y}success-detail-label {\n font-size: 0.875rem;\n color: var(--encore-text-muted);\n font-weight: 500;\n }\n\n .${y}success-detail-value {\n font-size: 1rem;\n color: var(--encore-text-color);\n font-weight: 600;\n }\n\n .${y}success-button {\n background: linear-gradient(135deg, var(--encore-primary-color), #10b981);\n color: white;\n border: none;\n border-radius: var(--encore-border-radius);\n padding: 0.875rem 2.5rem;\n font-size: 1rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n }\n\n .${y}success-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);\n }\n\n .${y}success-button:active {\n transform: translateY(0);\n }\n\n .${y}success-button:focus-visible {\n outline: 2px solid var(--encore-primary-color);\n outline-offset: 2px;\n }\n\n @keyframes ${y}scale-in {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n `}(e),document.head.appendChild(t),i.debug("Encore styles injected successfully")}catch(e){i.error("Failed to inject Encore styles:",e)}}function w(e){return`${y}${e}`}class I{#b;#re=null;#se=null;#oe=null;#ae=null;#le=!1;#ce=null;#de=[];#ue=null;constructor(e={}){this.#b=new a,x(e)}show(){this.#le?i.warn("Modal is already visible"):(this.#ce=document.activeElement,this.#he(),this.#re&&document.body.appendChild(this.#re),this.#se&&document.body.appendChild(this.#se),document.body.classList.add(w("no-scroll")),requestAnimationFrame(()=>{this.#re?.classList.add(w("visible")),this.#se?.classList.add(w("visible"))}),this.#fe(),this.#ge(),this.#me(),this.#le=!0,this.#b.emit("show",void 0),i.debug("Modal shown"))}hide(){this.#le&&(this.#re?.classList.remove(w("visible")),this.#se?.classList.remove(w("visible")),setTimeout(()=>{this.#pe(),document.body.classList.remove(w("no-scroll")),this.#ce instanceof HTMLElement&&this.#ce.focus(),this.#le=!1,this.#b.emit("hide",void 0),i.debug("Modal hidden")},200))}isVisible(){return this.#le}setContent(e){this.#ae?(this.#ae.innerHTML="",this.#ae.appendChild(e),this.#ge()):i.error("Modal body not initialized")}on(e,t){return this.#b.on(e,t)}#he(){this.#re=document.createElement("div"),this.#re.className=w("backdrop"),this.#re.setAttribute("aria-hidden","true"),this.#se=document.createElement("div"),this.#se.className=w("modal"),this.#se.setAttribute("role","dialog"),this.#se.setAttribute("aria-modal","true"),this.#se.setAttribute("aria-labelledby",w("modal-title")),this.#oe=document.createElement("button"),this.#oe.className=w("close-button"),this.#oe.setAttribute("aria-label","Close modal"),this.#oe.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">\n <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />\n </svg>\n ',this.#ae=document.createElement("div"),this.#ae.className=w("modal-body"),this.#se.appendChild(this.#oe),this.#se.appendChild(this.#ae)}#pe(){this.#re?.remove(),this.#se?.remove(),this.#re=null,this.#se=null,this.#oe=null,this.#ae=null}#fe(){this.#oe?.addEventListener("click",()=>{this.#b.emit("close",void 0),this.hide()}),this.#re?.addEventListener("click",()=>{this.#b.emit("backdropClick",void 0),this.hide()}),this.#ue=this.#be.bind(this),document.addEventListener("keydown",this.#ue)}#be(e){if(this.#le)switch(e.key){case"Escape":e.preventDefault(),this.#b.emit("close",void 0),this.hide();break;case"Tab":e.preventDefault(),this.#ve(e.shiftKey)}}#ve(e){if(0===this.#de.length)return;const t=this.#de.findIndex(e=>e===document.activeElement);let n;n=e?t<=0?this.#de.length-1:t-1:t>=this.#de.length-1?0:t+1,this.#de[n]?.focus()}#ge(){if(!this.#se)return;const e=["button:not([disabled])","a[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(", ");this.#de=Array.from(this.#se.querySelectorAll(e))}#me(){this.#de.length>0&&this.#de[0]?.focus()}destroy(){this.#ue&&document.removeEventListener("keydown",this.#ue),this.#b.removeAllListeners(),this.hide()}}class E{#b;#ye=null;#xe=null;constructor(){this.#b=new a}render(e){this.#ye=e,this.#xe=document.createElement("div"),this.#xe.className=w("offer-card");const t=this.#we(e.imageUrl,e.title);this.#xe.appendChild(t);const n=this.#Ie(e);this.#xe.appendChild(n);const i=this.#Ee(e);return this.#xe.appendChild(i),this.#xe}on(e,t){return this.#b.on(e,t)}#we(e,t){const n=document.createElement("div");n.className=w("offer-banner");const r=document.createElement("img");r.className=w("offer-banner-image"),r.alt=t??"Offer image",e?(r.src=e,r.complete?r.classList.add(w("loaded")):r.onload=()=>{r.classList.add(w("loaded"))},r.onerror=()=>{i.warn("Failed to load offer image, using fallback"),r.src=this.#Ce(),r.classList.add(w("loaded"))}):(r.src=this.#Ce(),r.classList.add(w("loaded"))),n.appendChild(r);const s=document.createElement("button");return s.className=w("banner-info-button"),s.setAttribute("aria-label","More information"),s.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">\n <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />\n </svg>\n ',s.addEventListener("click",e=>{e.stopPropagation(),i.debug("Info button clicked for offer",{title:t})}),n.appendChild(s),n}#Ce(){return`data:image/svg+xml;base64,${btoa('\n <svg xmlns="http://www.w3.org/2000/svg" width="600" height="240" viewBox="0 0 600 240">\n <rect width="600" height="240" fill="#E5E7EB"/>\n <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#9CA3AF" font-family="sans-serif" font-size="18">\n Offer Image\n </text>\n </svg>\n ')}`}#Ie(e){const t=document.createElement("div");t.className=w("offer-details");const n=document.createElement("h3");n.className=w("offer-details-heading"),n.textContent="Offer details";const i=document.createElement("ul");if(i.className=w("offer-details-list"),e.instructions&&e.instructions.length>0)e.instructions.forEach(e=>{const t=document.createElement("li");t.textContent=e.subtitle||e.title,i.appendChild(t)});else if(e.description){const t=document.createElement("li");t.textContent=e.description,i.appendChild(t)}return t.appendChild(n),t.appendChild(i),t}#Ee(e){const t=document.createElement("div");t.className=w("offer-footer");const n=document.createElement("div");if(n.className=w("offer-merchant"),e.logoUrl){const t=document.createElement("img");t.className=w("offer-logo"),t.src=e.logoUrl,t.alt=`${e.merchantName??"Merchant"} logo`,t.complete?t.classList.add(w("loaded")):t.onload=()=>{t.classList.add(w("loaded"))},t.onerror=()=>{i.warn("Failed to load merchant logo",{merchantName:e.merchantName}),t.style.display="none"},n.appendChild(t)}const r=document.createElement("div");if(r.className=w("offer-merchant-text"),e.merchantName){const t=document.createElement("div");t.className=w("offer-merchant-name"),t.textContent=e.merchantName,r.appendChild(t)}if(e.quickInstructions){const t=document.createElement("div");t.className=w("offer-merchant-desc"),t.textContent=e.quickInstructions,r.appendChild(t)}n.appendChild(r);const s=document.createElement("button");return s.className=`${w("button")} ${w("button-claim")}`,s.textContent=e.ctaText??"Claim",s.setAttribute("aria-label",`Claim offer: ${e.title??"offer"}`),s.addEventListener("click",()=>{this.#ye&&this.#b.emit("claim",{offer:this.#ye})}),t.appendChild(n),t.appendChild(s),t}destroy(){this.#b.removeAllListeners(),this.#xe=null,this.#ye=null}}class C{#b;#$e;#ke=0;#xe=null;#Ae=null;#Te=null;#Ne=[];#Se=null;#Re=null;constructor(e){if(this.#b=new a,this.#$e=e,0===e.length)throw new Error("OfferCarousel requires at least one offer");this.#Le()}render(){this.#xe=document.createElement("div"),this.#xe.className=w("carousel"),this.#Se=document.createElement("div"),this.#Se.setAttribute("role","status"),this.#Se.setAttribute("aria-live","polite"),this.#Se.setAttribute("aria-atomic","true"),this.#Se.className="sr-only",this.#Se.style.position="absolute",this.#Se.style.width="1px",this.#Se.style.height="1px",this.#Se.style.padding="0",this.#Se.style.margin="-1px",this.#Se.style.overflow="hidden",this.#Se.style.clip="rect(0, 0, 0, 0)",this.#Se.style.whiteSpace="nowrap",this.#Se.style.border="0";const e=this.#Me();if(this.#xe.appendChild(e),this.#Ae=document.createElement("div"),this.#Ae.className=w("carousel-cards"),this.#xe.appendChild(this.#Se),this.#xe.appendChild(this.#Ae),this.#$e.length>1){const e=this.#Oe();this.#xe.appendChild(e)}return this.#Fe(),this.#Ue(),this.#De(0,!1),this.#xe}on(e,t){return this.#b.on(e,t)}getCurrentIndex(){return this.#ke}getTotalOffers(){return this.#$e.length}next(){this.#ke<this.#$e.length-1&&(this.#ke++,this.#De(this.#ke),this.#Be(),this.#qe(`Showing offer ${this.#ke+1} of ${this.#$e.length}`),i.debug(`Navigated to offer ${this.#ke+1}`))}previous(){this.#ke>0&&(this.#ke--,this.#De(this.#ke),this.#Be(),this.#qe(`Showing offer ${this.#ke+1} of ${this.#$e.length}`),i.debug(`Navigated to offer ${this.#ke+1}`))}#Fe(){if(!this.#Ae)return;const e=this.#Ae;this.#$e.forEach((t,n)=>{const i=new E,r=i.render(t),s=document.createElement("div");s.className=w("carousel-item"),s.setAttribute("data-index",n.toString()),s.appendChild(r),i.on("claim",()=>{this.#b.emit("offerClaim",{offer:t,index:n})}),this.#Ne.push(i),e.appendChild(s)}),requestAnimationFrame(()=>{e.classList.add(w("cards-ready"))})}#De(e,t=!0){if(!this.#Ae)return;const n=this.#Ae.querySelectorAll(`.${w("carousel-item")}`),i=n[e];if(i){i.scrollIntoView({behavior:t?"smooth":"auto",block:"nearest",inline:"center"}),n.forEach((t,n)=>{n===e?t.classList.add(w("active")):t.classList.remove(w("active"))});const r=this.#$e[e];r&&this.#b.emit("offerView",{offer:r,index:e})}}#Me(){const e=document.createElement("div");e.className=w("carousel-header");const t=document.createElement("h2");t.className=w("carousel-title"),t.id=w("modal-title"),t.textContent="Unlock 10 free articles – choose an offer below";const n=document.createElement("p");return n.className=w("carousel-subtitle"),n.textContent="Activate one of these partner offers and get 10 free articles. No credit card required.",e.appendChild(t),e.appendChild(n),e}#Oe(){const e=document.createElement("div");e.className=w("carousel-navigation");const t=document.createElement("button");t.className=w("nav-button"),t.setAttribute("aria-label","Previous offer"),t.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="transform: rotate(90deg);">\n <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />\n </svg>\n ',t.addEventListener("click",()=>this.previous());const n=document.createElement("button");return n.className=w("nav-button"),n.setAttribute("aria-label","Next offer"),n.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="transform: rotate(270deg);">\n <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />\n </svg>\n ',n.addEventListener("click",()=>this.next()),e.appendChild(t),e.appendChild(n),this.#Te=e,this.#Be(t,n),e}#Be(e,t){if(!this.#Te)return;const n=this.#Te.querySelectorAll(`.${w("nav-button")}`),i=e??n[0],r=t??n[1];i&&(i.disabled=0===this.#ke,i.classList.toggle(w("disabled"),0===this.#ke)),r&&(r.disabled=this.#ke===this.#$e.length-1,r.classList.toggle(w("disabled"),this.#ke===this.#$e.length-1))}#Ue(){this.#Re=this.#Ke.bind(this),document.addEventListener("keydown",this.#Re)}#Ke(e){if(this.#xe)switch(e.key){case"ArrowLeft":e.preventDefault(),this.previous();break;case"ArrowRight":e.preventDefault(),this.next()}}#qe(e){this.#Se&&(this.#Se.textContent=e)}#Le(){this.#$e.forEach(e=>{e.imageUrl&&((new Image).src=e.imageUrl,i.debug("Preloading offer image",{offerId:e.id,url:e.imageUrl})),e.logoUrl&&((new Image).src=e.logoUrl,i.debug("Preloading merchant logo",{offerId:e.id,url:e.logoUrl}))})}destroy(){this.#Re&&document.removeEventListener("keydown",this.#Re),this.#Ne.forEach(e=>e.destroy()),this.#Ne=[],this.#b.removeAllListeners(),this.#xe=null,this.#Ae=null,this.#Te=null,this.#Se=null}}const $=e=>`encore-success-${e}`;class k{#xe=null;#b;#t;#Pe=null;constructor(e){this.#t=e,this.#b=new a}render(){this.#xe=document.createElement("div"),this.#xe.className=$("container");const e=document.createElement("div");e.className=$("icon"),e.innerHTML="✓";const t=document.createElement("h2");t.className=$("title"),t.textContent=this.#t.titleText??"Success!";const n=document.createElement("p");n.className=$("subtitle"),n.textContent=this.#t.subtitleText??this.#_e(this.#t.entitlement);const r=document.createElement("div");r.className=$("details"),r.innerHTML=this.#ze(this.#t.entitlement);const s=document.createElement("button");return s.className=$("button"),s.textContent=this.#t.buttonText??"Continue",s.setAttribute("type","button"),s.addEventListener("click",()=>this.#Ge()),this.#xe.appendChild(e),this.#xe.appendChild(t),this.#xe.appendChild(n),this.#xe.appendChild(r),this.#xe.appendChild(s),this.#t.autoDismissMs&&this.#t.autoDismissMs>0&&this.#je(this.#t.autoDismissMs),i.debug("Success screen rendered"),this.#xe}on(e,t){return this.#b.on(e,t)}destroy(){null!==this.#Pe&&(clearTimeout(this.#Pe),this.#Pe=null),this.#xe&&(this.#xe.remove(),this.#xe=null),this.#b.removeAllListeners(),i.debug("Success screen destroyed")}#Ge(){i.debug("User clicked continue on success screen"),this.#b.emit("continue",void 0)}#je(e){this.#Pe=window.setTimeout(()=>{i.debug("Success screen auto-dismissing"),this.#b.emit("continue",void 0)},e)}#_e(e){switch(e.type){case"freeTrial":return`You've unlocked a ${e.value??""} ${e.unit??"day"} free trial!`;case"discount":return`You've received a ${e.value??""}${"percent"===e.unit?"%":""} discount!`;case"credit":return`You've earned $${e.value??"0"} in credits!`;default:return"You've unlocked a special offer!"}}#ze(e){const t=[];if("freeTrial"===e.type)t.push(`<div class="${$("detail")}">\n <span class="${$("detail-label")}">Type:</span>\n <span class="${$("detail-value")}">Free Trial</span>\n </div>`),e.value&&e.unit&&t.push(`<div class="${$("detail")}">\n <span class="${$("detail-label")}">Duration:</span>\n <span class="${$("detail-value")}">${e.value} ${e.unit}</span>\n </div>`);else if("discount"===e.type){if(t.push(`<div class="${$("detail")}">\n <span class="${$("detail-label")}">Type:</span>\n <span class="${$("detail-value")}">Discount</span>\n </div>`),e.value&&e.unit){const n="percent"===e.unit?`${e.value}%`:`$${e.value}`;t.push(`<div class="${$("detail")}">\n <span class="${$("detail-label")}">Amount:</span>\n <span class="${$("detail-value")}">${n}</span>\n </div>`)}}else"credit"===e.type&&(t.push(`<div class="${$("detail")}">\n <span class="${$("detail-label")}">Type:</span>\n <span class="${$("detail-value")}">Credit</span>\n </div>`),e.value&&t.push(`<div class="${$("detail")}">\n <span class="${$("detail-label")}">Amount:</span>\n <span class="${$("detail-value")}}">$${e.value}</span>\n </div>`));return t.join("")}}class A{#He=null;#Ve=null;#Qe=!1;start(e){this.#Qe?i.warn("FocusDetector already active"):(this.#He=()=>{i.debug("Window focused"),e()},this.#Ve=()=>{"visible"===document.visibilityState&&(i.debug("Document became visible"),e())},window.addEventListener("focus",this.#He),document.addEventListener("visibilitychange",this.#Ve),this.#Qe=!0,i.debug("FocusDetector started"))}stop(){this.#Qe&&(this.#He&&(window.removeEventListener("focus",this.#He),this.#He=null),this.#Ve&&(document.removeEventListener("visibilitychange",this.#Ve),this.#Ve=null),this.#Qe=!1,i.debug("FocusDetector stopped"))}isActive(){return this.#Qe}}function T(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=15&(crypto.getRandomValues(new Uint8Array(1))[0]??0);return("x"===e?t:3&t|8).toString(16)})}const N="0.1.0",S="user_id",R="user_attributes",L=new class{#We;#h;#f=null;#Je=null;#Ye=null;#Ze=null;#Xe=null;#g=null;#et={};#tt=!1;#nt=!1;constructor(){this.#We=new r,this.#h=new o}configure(e){if(this.#We.configure(e)){this.#it();const e=this.#We.getBaseURL();e&&(this.#f=new b(this.#We.getApiKey()??"",e),this.#g&&(this.#Je=new d(this.#h,this.#f,this.#g),this.#Ye=new h(this.#h,this.#f,this.#g),this.#Ze=new f(this.#f,this.#g)),this.#Xe=new A),i.info("Encore SDK initialized successfully",{version:N})}}#it(){const e=this.#h.get(S);e?(this.#g=e,i.debug("Loaded existing user ID:",e)):(this.#g=T(),this.#h.set(S,this.#g),i.debug("Generated new user ID:",this.#g));const t=this.#h.get(R);t&&(this.#et=t,i.debug("Loaded user attributes"))}#rt(){return!!this.#We.isConfigured()||(i.error("SDK not configured. Call Encore.configure() first."),!1)}identify(e,t){if(!this.#rt())return;if(!e||"string"!=typeof e)return void i.error("identify() requires a valid user ID string");const n=this.#g;this.#g=e,this.#h.set(S,e),t&&this.setUserAttributes(t),n!==e&&(i.info("User identified:",e),this.#Je&&this.#Je.setUserId(e),this.#Ye&&this.#Ye.setUserId(e),this.#Ze&&this.#Ze.setUserId(e))}getCurrentUserId(){return this.#g}reset(){this.#rt()&&(i.info("Resetting SDK"),this.#h.clear(),this.#g=T(),this.#h.set(S,this.#g),this.#et={},this.#Je&&(this.#Je.clearCache(),this.#f&&this.#g&&(this.#Je=new d(this.#h,this.#f,this.#g))),this.#Ye&&(this.#Ye.clearQueue(),this.#Ye.destroy(),this.#f&&this.#g&&(this.#Ye=new h(this.#h,this.#f,this.#g))),this.#Ze&&(this.#Ze.clearCache(),this.#f&&this.#g&&(this.#Ze=new f(this.#f,this.#g))),this.#Xe?.isActive()&&this.#Xe.stop(),i.debug("SDK reset complete",{newUserId:this.#g}))}getVersion(){return N}setLogLevel(e){i.setLogLevel(e)}setUserAttributes(e){this.#rt()&&(e&&"object"==typeof e?(this.#et={...this.#et,...e,custom:{...this.#et.custom,...e.custom}},this.#h.set(R,this.#et),i.debug("User attributes updated",this.#et)):i.error("setUserAttributes() requires a valid UserAttributes object"))}getUserAttributes(){return{...this.#et}}async presentOffer(e){if(!this.#rt()){const n={type:"error",error:{code:t.INITIALIZATION_ERROR,message:"SDK not configured"}};return e?.onNotGranted&&e.onNotGranted(n),e?.onError&&e.onError({code:t.INITIALIZATION_ERROR,message:"SDK not configured"}),{granted:!1,reason:n}}if(this.#tt){i.warn("Presentation already in progress");const n={type:"error",error:{code:t.UNKNOWN_ERROR,message:"Presentation already in progress"}};return e?.onNotGranted&&e.onNotGranted(n),{granted:!1,reason:n}}this.#tt=!0;try{const t=await this.#st(e);return t.granted&&t.entitlement&&e?.onGranted?e.onGranted(t.entitlement):!t.granted&&t.reason&&e?.onNotGranted&&e.onNotGranted(t.reason),t}catch(n){i.error("Error during presentation",n);const r={type:"error",error:{code:t.UNKNOWN_ERROR,message:n instanceof Error?n.message:"Unknown error"}};return e?.onError&&"string"!=typeof r&&"error"===r.type&&e.onError(r.error),e?.onNotGranted&&e.onNotGranted(r),{granted:!1,reason:r}}finally{this.#tt=!1}}isActive(e,t){return!!this.#rt()&&(this.#Je?this.#Je.isActive(e,t):(i.error("EntitlementManager not initialized"),!1))}async refreshEntitlements(){this.#rt()&&(this.#Je?await this.#Je.refreshEntitlements():i.error("EntitlementManager not initialized"))}didGrant(e,t){this.#rt()&&(this.#Ye?t&&"string"==typeof t?this.#Ye.sendGrantSignal(t,e):i.error("didGrant() requires a valid transaction ID"):i.error("SignalManager not initialized"))}async waitForVerification(e,t){if(!this.#rt())return i.error("SDK not configured"),"failed";if(!this.#f)return i.error("API client not initialized"),"failed";if(!e)return i.error("waitForVerification() requires a transaction ID"),"failed";try{i.debug("Starting verification wait",{transactionId:e,timeout:t});const n={transactionId:e};void 0!==t&&(n.timeout=t);const r=new g(this.#f,n),s=await r.poll();return"verified"===s&&await this.refreshEntitlements(),s}catch(t){return i.error("Error during verification wait",{transactionId:e,error:t}),"failed"}}on(e,t){return this.#rt()?this.#Je?this.#Je.getEventEmitter().on(e,t):(i.error("EntitlementManager not initialized"),()=>{}):()=>{}}observeEntitlement(e,t){return{subscribe:n=>{if(!this.#rt())return()=>{};if(!this.#Je)return i.error("EntitlementManager not initialized"),()=>{};const r=this.#Je.isActive(e,t);return n(r),this.on("entitlementChanged",i=>{const r=i.scope;JSON.stringify(i.entitlementType)===JSON.stringify(e)&&("verified"===t&&"verified"!==r||n(i.isActive))})}}}placement(){return new m(async()=>this.presentOffer())}async#st(e){if(!this.#Ze||!this.#f)return i.error("Managers not initialized"),{granted:!1,reason:{type:"error",error:{code:t.INITIALIZATION_ERROR,message:"Managers not initialized"}}};try{this.#nt||(x({}),this.#nt=!0),i.debug("Fetching offers");const{offers:e,uiConfiguration:n}=await this.#Ze.fetchOffers(this.#et);if(0===e.length)return i.info("No offers available"),{granted:!1,reason:"noOffersAvailable"};const r={...this.#We.getUIConfiguration(),...n},s=new Map,o=new Set;e.forEach(e=>{s.set(e.id,T())});const a=new I,l=new C(e),c=await new Promise(e=>{l.on("offerClaim",n=>{const o=n.offer;i.debug("User claimed offer",{offerId:o.id}),(async()=>{try{if(!this.#Ze)throw new Error("OfferManager not initialized");const t=s.get(o.id),n=await this.#Ze.startTransaction(o.campaignId,o.creativeId,t);this.#ot(o.advertiserUrl)||i.warn("Failed to open advertiser URL (popup blocked?)"),this.didGrant("provisional",n),await this.refreshEntitlements(),this.#Xe&&!this.#Xe.isActive()&&this.#Xe.start(()=>{(async()=>{i.debug("User returned to app, refreshing entitlements"),await this.refreshEntitlements()})()}),this.#at(a,o.entitlement,()=>{a.hide(),e({granted:!0,entitlement:o.entitlement})},r)}catch(n){i.error("Error starting transaction",{offerId:o.id,error:n}),a.hide(),e({granted:!1,reason:{type:"error",error:{code:t.UNKNOWN_ERROR,message:n instanceof Error?n.message:"Transaction failed"}}})}})()}),l.on("complete",t=>{t.claimed||(i.debug("User declined last offer"),l.destroy(),a.hide(),e({granted:!1,reason:"userDeclinedLastOffer"}))}),a.on("close",()=>{i.debug("User closed modal"),l.destroy(),e({granted:!1,reason:"userClosedModal"})}),a.on("backdropClick",()=>{i.debug("User clicked outside modal"),l.destroy(),a.hide(),e({granted:!1,reason:"userClickedOutside"})}),l.on("offerView",e=>{const{offer:t}=e;if(o.has(t.id))return void i.debug("Impression already logged for this modal session",{offerId:t.id});const n=s.get(t.id);n&&this.#Ze&&(this.#Ze.logImpression(n,t),o.add(t.id))}),a.show();const n=l.render();a.setContent(n)});return a.destroy(),l.destroy(),c}catch(e){return i.error("Error in presentation flow",e),{granted:!1,reason:{type:"error",error:{code:t.UNKNOWN_ERROR,message:e instanceof Error?e.message:"Unknown error"}}}}}#ot(e){try{const t=window.open(e,"_blank","noopener,noreferrer");return!!t&&(t.focus(),!0)}catch(t){return i.error("Failed to open advertiser URL",{url:e,error:t}),!1}}#at(e,t,n,r){try{const s={entitlement:t,autoDismissMs:0};r?.creditClaimedTitleText&&(s.titleText=r.creditClaimedTitleText),r?.creditClaimedSubtitleText&&(s.subtitleText=r.creditClaimedSubtitleText),r?.applyCreditsButtonText&&(s.buttonText=r.applyCreditsButtonText);const o=new k(s);o.on("continue",()=>{o.destroy(),n()});const a=o.render();e.setContent(a),i.debug("Success screen displayed")}catch(e){i.error("Failed to show success screen",e),n()}}};e.Encore=L,e.default=L,Object.defineProperty(e,"__esModule",{value:!0})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Encore={})}(this,function(e){"use strict";var t;!function(e){e.NETWORK_ERROR="NETWORK_ERROR",e.API_ERROR="API_ERROR",e.CONFIGURATION_ERROR="CONFIGURATION_ERROR",e.INITIALIZATION_ERROR="INITIALIZATION_ERROR",e.STORAGE_ERROR="STORAGE_ERROR",e.INVALID_REQUEST="INVALID_REQUEST",e.UNAUTHORIZED="UNAUTHORIZED",e.NOT_FOUND="NOT_FOUND",e.TIMEOUT="TIMEOUT",e.UNKNOWN_ERROR="UNKNOWN_ERROR"}(t||(t={}));const n="[Encore SDK]",i=new class{#e="none";setLogLevel(e){this.#e=e}getLogLevel(){return this.#e}debug(...e){"debug"===this.#e&&console.debug(n,...e)}info(...e){"debug"===this.#e&&console.info(n,...e)}warn(...e){"debug"===this.#e&&console.warn(n,...e)}error(...e){"debug"===this.#e&&console.error(n,...e)}critical(...e){console.error(n,"[CRITICAL]",...e)}};class r{#t=null;#n=!1;configure(e){if(this.#n)return i.warn("SDK already configured. Ignoring subsequent configure() call."),!1;const t=this.#i(e);if(t)return i.error("Invalid configuration:",t),!1;const n=e.logLevel??"none",r=e.environment??"production";return this.#t={apiKey:e.apiKey,userId:e.userId,environment:r,baseURL:this.#r(r),analyticsBaseURL:this.#s(r),logLevel:n,uiConfiguration:e.uiConfiguration??{}},i.setLogLevel(n),this.#n=!0,i.debug("SDK configured successfully",this.#t),!0}#i(e){return e.apiKey&&"string"==typeof e.apiKey&&""!==e.apiKey.trim()?e.environment&&!["production","development","staging","localhost"].includes(e.environment)?"environment must be 'production', 'development', 'staging', or 'localhost'":e.logLevel&&!["none","debug"].includes(e.logLevel)?"logLevel must be 'none' or 'debug'":null:"apiKey is required and must be a non-empty string"}#r(e){switch(e){case"localhost":return"http://localhost:4000/publisher/sdk/v1";case"development":return"https://api.dev.encorekit.com/encore/publisher/sdk/v1";case"staging":return"https://api.staging.encorekit.com/encore/publisher/sdk/v1";default:return"https://api.encorekit.com/encore/publisher/sdk/v1"}}#s(e){switch(e){case"localhost":return"http://localhost:8081/v1";case"development":return"https://api.dev.encorekit.com/analytics/v1";case"staging":return"https://api.staging.encorekit.com/analytics/v1";default:return"https://api.encorekit.com/analytics/v1"}}getConfig(){return this.#t}isConfigured(){return this.#n}getApiKey(){return this.#t?.apiKey??null}getBaseURL(){return this.#t?.baseURL??null}getAnalyticsBaseURL(){return this.#t?.analyticsBaseURL??null}getEnvironment(){return this.#t?.environment??null}getUIConfiguration(){return this.#t?.uiConfiguration??{}}reset(){this.#t=null,this.#n=!1,i.debug("Configuration reset")}}const s="encore_";class o{#o;#a;constructor(){this.#a=new Map,this.#o=this.#l(),i.debug(`StorageManager initialized with ${this.#o}`)}#l(){return this.#c("localStorage")?"localStorage":this.#c("sessionStorage")?"sessionStorage":(i.warn("Neither localStorage nor sessionStorage available, using in-memory storage"),"memory")}#c(e){try{const t="localStorage"===e?localStorage:sessionStorage,n="__encore_test__";return t.setItem(n,"test"),t.removeItem(n),!0}catch{return!1}}#d(){return"localStorage"===this.#o?localStorage:"sessionStorage"===this.#o?sessionStorage:this.#a}#u(e){return`${s}${e}`}set(e,t){if(void 0===t)return void i.warn(`Attempted to store undefined value for key: ${e}`);const n=this.#u(e),r=JSON.stringify(t);try{const t=this.#d();t instanceof Map?t.set(n,r):t.setItem(n,r),i.debug(`Stored ${e} in ${this.#o}`)}catch(e){e instanceof Error&&"QuotaExceededError"===e.name?i.error("Storage quota exceeded:",e):i.error("Failed to store item:",e),"memory"!==this.#o&&(i.warn("Falling back to memory storage for this item"),this.#a.set(n,r))}}get(e){const t=this.#u(e);try{const n=this.#d();let r=null;return r=n instanceof Map?n.get(t)??null:n.getItem(t),null===r||"undefined"===r?("undefined"===r&&(i.warn(`Found corrupted value "undefined" for key: ${e}, cleaning up`),this.remove(e)),null):JSON.parse(r)}catch(t){return i.error(`Failed to retrieve ${e}:`,t),this.remove(e),null}}remove(e){const t=this.#u(e);try{const n=this.#d();n instanceof Map?n.delete(t):n.removeItem(t),i.debug(`Removed ${e} from ${this.#o}`)}catch(t){i.error(`Failed to remove ${e}:`,t)}}clear(){try{const e=this.#d();if(e instanceof Map)for(const t of e.keys())t.startsWith(s)&&e.delete(t);else{const t=[];for(let n=0;n<e.length;n++){const i=e.key(n);i?.startsWith(s)&&t.push(i)}t.forEach(t=>e.removeItem(t))}i.debug(`Cleared all Encore data from ${this.#o}`)}catch(e){i.error("Failed to clear storage:",e)}}getStorageType(){return this.#o}}const a="signal_queue";class l{#h;#p;#f;#m=[];#g=!1;#b;constructor(e,t,n){this.#h=e,this.#p=t,this.#f=n,this.#v(),this.#y(),this.processQueue()}setUserId(e){this.#f!==e&&(i.debug("SignalManager: User ID changed, clearing queue"),this.#f=e,this.#m=[],this.#v())}#v(){try{const e=`${this.#f}_${a}`,t=this.#h.get(e);t&&Array.isArray(t)&&(this.#m=t,i.debug("Loaded grant signal queue from storage",{count:t.length}))}catch(e){i.error("Failed to load grant signal queue from storage:",e)}}#w(){try{const e=`${this.#f}_${a}`;this.#h.set(e,this.#m),i.debug("Saved grant signal queue to storage",{count:this.#m.length})}catch(e){i.error("Failed to save grant signal queue to storage:",e)}}enqueue(e,t){const n=this.#m.some(n=>n.transactionId===e&&n.grantType===t);if(n)return void i.debug("Grant signal already in queue, skipping",{transactionId:e,grantType:t});const r={transactionId:e,grantType:t,timestamp:(new Date).toISOString(),attempts:0};this.#m.push(r),this.#w(),i.info("Grant signal added to queue",{transactionId:e,grantType:t})}dequeue(e){const t=this.#m.findIndex(t=>t.transactionId===e.transactionId&&t.grantType===e.grantType);-1!==t&&(this.#m.splice(t,1),this.#w(),i.debug("Grant signal removed from queue",{transactionId:e.transactionId,grantType:e.grantType}))}getQueue(){return[...this.#m]}clearQueue(){this.#m=[],this.#w(),i.debug("Grant signal queue cleared")}async sendGrantSignal(e,t){try{if(i.debug("Sending grant signal",{transactionId:e,grantType:t}),!await this.#p.sendGrantSignal(e,t))throw new Error("Grant signal failed (returned false)");i.info("Grant signal sent successfully",{transactionId:e,grantType:t})}catch{i.warn("Failed to send grant signal, adding to queue",{transactionId:e,grantType:t}),this.enqueue(e,t)}}async processQueue(){if(this.#g)i.debug("Queue processing already in progress, skipping");else if(0!==this.#m.length){this.#g=!0,i.info("Processing grant signal queue",{count:this.#m.length});try{for(const e of[...this.#m])await this.#x(e),this.#m.length>1&&await this.#I(100)}finally{this.#g=!1}}}async#x(e){if(e.attempts>=3)return i.error("Grant signal max attempts reached, removing from queue",{transactionId:e.transactionId,grantType:e.grantType,attempts:e.attempts}),void this.dequeue(e);if(e.lastAttemptAt){const t=new Date(e.lastAttemptAt).getTime(),n=Date.now(),r=1e3*Math.pow(2,e.attempts-1),s=n-t;if(s<r)return void i.debug("Skipping signal, waiting for backoff period",{transactionId:e.transactionId,remainingWait:r-s})}e.attempts++,e.lastAttemptAt=(new Date).toISOString(),this.#w();try{i.debug("Attempting to send queued grant signal",{transactionId:e.transactionId,grantType:e.grantType,attempt:e.attempts}),await this.#p.sendGrantSignal(e.transactionId,e.grantType)?(i.info("Queued grant signal sent successfully",{transactionId:e.transactionId,grantType:e.grantType}),this.dequeue(e)):i.warn("Grant signal failed, will retry",{transactionId:e.transactionId,attempt:e.attempts})}catch(t){i.warn("Failed to send queued grant signal, will retry",{transactionId:e.transactionId,attempt:e.attempts,error:t})}}#y(){this.#b=function(e){const t=()=>{i.debug("Network status: online"),e()};return window.addEventListener("online",t),()=>{window.removeEventListener("online",t)}}(()=>{i.debug("Network came online, processing grant signal queue"),this.processQueue()})}destroy(){this.#b&&(this.#b(),this.#b=void 0)}#I(e){return new Promise(t=>setTimeout(t,e))}}function c(e,t){return{name:"sdk_offer_time_spent",distinctId:e,properties:{...t}}}function d(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=15&(crypto.getRandomValues(new Uint8Array(1))[0]??0);return("x"===e?t:3&t|8).toString(16)})}class u{#p;#E;#f;#C=[];#k=null;#$=null;#T=null;#A=new Map;#L=0;constructor(e,t,n){this.#p=e,this.#f=t,this.#E=n??null}async fetchOffers(e,t=!0){if(t&&this.#C.length>0&&this.#k)return i.debug("Using cached offers",{count:this.#C.length}),{offers:[...this.#C]};try{i.debug("Fetching offers from API",{userId:this.#f});const t=await this.#p.fetchOffers(this.#f,e);return 0===t.offers?.length?(i.info("No offers available for user"),this.#C=[],this.#k=Date.now(),{offers:[]}):(this.#C=t.offers,this.#k=Date.now(),i.info("Offers fetched successfully",{count:t.offers.length,offerIds:t.offers.map(e=>e.id)}),{offers:[...t.offers]})}catch(e){throw i.error("Failed to fetch offers",e),e}}beginPresentation(){return this.#$=d(),this.#T=Date.now(),this.#A.clear(),this.#L=0,this.#$}trackOfferPresented(e,t,n,i){if(!this.#E||!this.#$)return;this.#L++;const r=this.#A.get(e.id);var s,o;r?(r.viewCount++,r.startTime=Date.now()):this.#A.set(e.id,{startTime:Date.now(),totalTime:0,viewCount:1}),this.#E.track((s=this.#f,o={campaignId:e.campaignId,creativeId:e.creativeId,...null!=e.merchantName&&{advertiserName:e.merchantName},impressionId:t,offerIndex:n,totalOffers:i,presentationId:this.#$},{name:"sdk_offer_presented",distinctId:s,properties:{...o}}))}trackOfferViewEnd(e){const t=this.#A.get(e);t&&t.startTime>0&&(t.totalTime+=(Date.now()-t.startTime)/1e3,t.startTime=0)}trackOfferClaimed(e,t,n,i,r){var s,o;this.#E&&this.#$&&this.#E.track((s=this.#f,o={campaignId:e.campaignId,creativeId:e.creativeId,...null!=e.merchantName&&{advertiserName:e.merchantName},impressionId:t,transactionId:n,offerIndex:i,totalOffers:r,presentationId:this.#$},{name:"sdk_offer_claimed",distinctId:s,properties:{...o}}))}trackOfferDeclined(e,t,n,i,r){var s,o;this.#E&&this.#$&&this.#E.track((s=this.#f,o={campaignId:e.campaignId,creativeId:e.creativeId,...null!=e.merchantName&&{advertiserName:e.merchantName},impressionId:t,offerIndex:n,totalOffers:i,...null!=r&&{declineReason:r},presentationId:this.#$},{name:"sdk_offer_declined",distinctId:s,properties:{...o}}))}endPresentation(e){if(!this.#E||!this.#$||!this.#T)return;const t=(Date.now()-this.#T)/1e3;for(const[e,t]of this.#A){let n=t.totalTime;t.startTime>0&&(n+=(Date.now()-t.startTime)/1e3);const i=this.#C.find(t=>t.id===e),r=i?this.#C.indexOf(i):0;this.#E.track(c(this.#f,{campaignId:i?.campaignId??"",offerIndex:r,timeSpentSeconds:n,viewCount:t.viewCount,totalOffers:this.#C.length,presentationId:this.#$}))}var n,i;this.#E.track((n=this.#f,i={presentationId:this.#$,totalTimeSpentSeconds:t,totalOffers:this.#C.length,offersViewed:this.#L,...null!=e&&{declineReason:e}},{name:"sdk_offer_sheet_dismissed",distinctId:n,properties:{...i}})),this.#$=null,this.#T=null,this.#A.clear(),this.#L=0}async startTransaction(e){try{i.debug("Starting transaction",{campaignId:e});const t=await this.#p.startTransaction(e,this.#f);if(!t.transactionId)throw new Error(t.error??"No transactionId in response");return i.info("Transaction started",{transactionId:t.transactionId,campaignId:e}),t.transactionId}catch(t){throw i.error("Failed to start transaction",{campaignId:e,error:t}),t}}clearCache(){this.#C=[],this.#k=null,i.debug("Offer cache cleared")}setUserId(e){this.#f=e,this.clearCache(),i.debug("OfferManager user ID updated",{userId:e})}}class h{#p;#N;#S;#R=0;#U=1e3;#O=8e3;#M=null;#B=!1;constructor(e,t){this.#p=e,this.#N=t.transactionId,this.#S=t.timeout??3e4}async poll(){return this.#B?(i.warn("Verification polling already in progress",{transactionId:this.#N}),"pending"):(this.#B=!0,this.#R=Date.now(),i.debug("Starting verification polling",{transactionId:this.#N,timeout:this.#S}),this.#F())}stop(){this.#B=!1,null!==this.#M&&(clearTimeout(this.#M),this.#M=null),i.debug("Verification polling stopped",{transactionId:this.#N})}async#F(){for(;this.#B;){const e=Date.now()-this.#R;if(e>=this.#S)return i.warn("Verification polling timeout",{transactionId:this.#N,elapsed:e}),this.stop(),"pending";try{const e=await this.#p.checkVerificationStatus(this.#N);if(i.debug("Verification status checked",{transactionId:this.#N,status:e.status,rawStatus:e.raw}),"verified"===e.status)return i.info("Transaction verified",{transactionId:this.#N}),this.stop(),"verified";if("failed"===e.status)return i.warn("Transaction failed verification",{transactionId:this.#N}),this.stop(),"failed";await this.#I(this.#U),this.#U=Math.min(2*this.#U,this.#O)}catch(e){i.error("Error checking verification status",{transactionId:this.#N,error:e}),await this.#I(this.#U)}}return"pending"}async#I(e){return new Promise(t=>{this.#M=window.setTimeout(()=>{this.#M=null,t()},e)})}}class p{#D=null;#P=null;#_=null;#q;constructor(e){this.#q=e}onGranted(e){return this.#D=e,this}onNotGranted(e){return this.#P=e,this}onLoadingStateChange(e){return this.#_=e,this}async show(){try{this.#_&&this.#_(!0),i.debug("PlacementBuilder: Executing presentation");const e=await this.#q();return this.#_&&this.#_(!1),e.granted&&e.entitlement&&this.#D?this.#D(e.entitlement):!e.granted&&this.#P&&e.reason&&this.#P(e.reason),e}catch(e){this.#_&&this.#_(!1),i.error("PlacementBuilder: Error during presentation",e);const n={type:"error",error:{code:t.UNKNOWN_ERROR,message:e instanceof Error?e.message:"Unknown error"}};return this.#P&&this.#P(n),{granted:!1,reason:n}}}}function f(e,t){let n=e;for(const[e,i]of Object.entries(t))n=n.replace(`:${e}`,encodeURIComponent(i));return n}const m="0.1.5";class g{#K;#z;#V;constructor(e,t){this.#K=e,this.#z=t,this.#V=new Map}setApiKey(e){this.#K=e}setBaseURL(e){this.#z=e}async get(e,t){return this.#H({url:`${this.#z}${e}`,options:{method:"GET",...t},apiKey:this.#K})}async post(e,t,n){return this.#H({url:`${this.#z}${e}`,options:{method:"POST",body:t,...n},apiKey:this.#K})}async patch(e,t,n){return this.#H({url:`${this.#z}${e}`,options:{method:"PATCH",body:t,...n},apiKey:this.#K})}async#H(e){const{url:t,options:n,apiKey:r}=e,s=this.#G(t,n),o=this.#V.get(s);if(o)return i.debug("Deduplicating request:",t),o;const a=this.#j(t,n,r);this.#V.set(s,a);try{return await a}finally{this.#V.delete(s)}}async#j(e,t,n){const r=t.retries??3;let s=null;for(let o=0;o<=r;o++)try{if(o>0){const e=1e3*Math.pow(2,o-1);i.debug(`Retrying request (attempt ${o}/${r}) after ${e}ms`),await this.#I(e)}return await this.#W(e,t,n)}catch(e){if(s=e,this.#Q(e))throw e;if(o===r)throw i.error(`Request failed after ${r} retries:`,e),e;i.warn("Request failed, will retry:",e)}throw s??new Error("Request failed")}async#W(e,t,n){const r=t.timeout??3e4,s=new AbortController,o=setTimeout(()=>s.abort(),r);try{const r={"X-API-Key":n,"Content-Type":"application/json","User-Agent":`Encore-Web-SDK/${m}`,...t.headers},o={method:t.method,headers:r,signal:s.signal};t.body&&(o.body=JSON.stringify(t.body)),i.debug(`${t.method} ${e}`);const a=await fetch(e,o);return a.ok||await this.#Y(a),await a.json()}catch(e){if(e instanceof Error){if("AbortError"===e.name)throw new Error("Request timeout");if(this.#Z(e))throw new Error(`Network error: ${e.message}`)}if(e instanceof Error)throw e;throw new Error(String(e))}finally{clearTimeout(o)}}async#Y(e){let n,i=`HTTP ${e.status}: ${e.statusText}`;try{const t=await e.json();"object"==typeof t&&null!==t&&"string"==typeof t.error&&(i=t.error,n="string"==typeof t.code?t.code:void 0)}catch{}const r=n?{code:n,message:i}:{code:t.API_ERROR,statusCode:e.status,message:i},s=new Error(i);throw Object.assign(s,r),s}#Q(e){if("object"==typeof e&&null!==e&&"statusCode"in e&&void 0!==e.statusCode){const t=e.statusCode;return t>=400&&t<500}return!1}#Z(e){return e.message.includes("fetch")||e.message.includes("network")||e.message.includes("ECONNREFUSED")||e.message.includes("ETIMEDOUT")}#G(e,t){const n=t.body?JSON.stringify(t.body):"";return`${t.method}:${e}:${n}`}#I(e){return new Promise(t=>setTimeout(t,e))}#J(e){switch(e){case"pending_conversion":case"provisional_granted":default:return"pending";case"verified":case"final_granted":return"verified";case"expired":case"failed":return"failed"}}async fetchOffers(e,t){try{const n=await this.post("/offers/search",{userId:e,attributes:t,platform:"web",sdkVersion:m}),i=[];for(const e of n.offers){const t=e.creatives??[];for(const n of t){const t={id:n.id,title:n.title,description:n.quickInstructions??n.subtitle??n.description??"",imageUrl:n.primaryImageUrl,ctaText:n.ctaText,advertiserUrl:n.destinationUrl,campaignId:e.id,creativeId:n.id,quickInstructions:n.quickInstructions??"",instructions:n.instructions??[],tooltipText:n.tooltipText??"",entitlement:{type:"credit",value:100,unit:"dollars"},...e.organization?.name&&{merchantName:e.organization.name},...n.logoUrl&&{logoUrl:n.logoUrl},...n.trackingParameters&&{trackingParameters:n.trackingParameters}};i.push(t)}}return{offers:i}}catch(e){throw i.error("Failed to fetch offers:",e),e}}async startTransaction(e,t){try{return await this.post("/transactions",{campaignId:e,userId:t})}catch(e){throw i.error("Failed to start transaction:",e),e}}async sendGrantSignal(e,t){try{const n=function(e){return f("/transactions/:transactionId/signals",{transactionId:e})}(e);return(await this.post(n,{grantType:t})).success}catch(e){throw i.error("Failed to send grant signal:",e),e}}async fetchEntitlements(e){try{const t=await this.get(`/entitlements?userId=${encodeURIComponent(e)}`),n=[],r=[{details:t.provisional,scope:"provisional"},{details:t.verified,scope:"verified"}];for(const{details:e,scope:t}of r)if(e){if(e.freeTrial&&n.push({type:"freeTrial",transactionId:"",scope:t,grantedAt:e.freeTrial.startedAt,expiresAt:e.freeTrial.expiresAt}),e.discounts)for(const i of e.discounts)n.push({type:"discount",value:i.value,unit:i.unit,transactionId:"",scope:t,grantedAt:"",expiresAt:i.expiresAt});e.credits&&n.push({type:"credit",value:e.credits.totalAmount,unit:"dollars",transactionId:"",scope:t,grantedAt:"",expiresAt:e.credits.expiresAt})}return i.debug("Transformed entitlements response",{totalCount:n.length}),n}catch(e){throw i.error("Failed to fetch entitlements:",e),e}}async checkVerificationStatus(e){try{const t=function(e){return f("/transactions/:transactionId/status",{transactionId:e})}(e),n=await this.get(t);return{status:this.#J(n.status),raw:n.status}}catch(e){throw i.error("Failed to check verification status:",e),e}}async initUser(e,t){try{return await this.post("/users",{userId:e,...t&&{attributes:t}})}catch(e){throw i.error("Failed to init user:",e),e}}async identifyUser(e,t,n){try{return await this.patch("/users/identify",{currentUserId:e,newUserId:t,...n&&{attributes:n}})}catch(e){throw i.error("Failed to identify user:",e),e}}async fetchConfig(e,t){try{return await this.get(`/config?userId=${encodeURIComponent(e)}&sdkVersion=${encodeURIComponent(t)}`)}catch(e){throw i.error("Failed to fetch config:",e),e}}async reportError(e){try{const t="undefined"!=typeof window?window.location.hostname:"unknown";await this.post("/errors",{errorType:e.errorType,message:e.message,context:e.context,severity:e.severity??"error",timestamp:(new Date).toISOString(),platform:"web",sdkVersion:m,appBundleId:t,...e.stackTrace&&{stackTrace:e.stackTrace},...e.userId&&{userId:e.userId},...e.metadata&&{metadata:e.metadata}})}catch(e){i.warn("Failed to report error (non-blocking):",e)}}async revokeEntitlements(e){try{return(await this.post("/entitlements/revoke",{userId:e})).success}catch(e){throw i.error("Failed to revoke entitlements:",e),e}}}class b{#K;#X;constructor(e,t){this.#K=e,this.#X=t}track(e){try{const t=this.#ee(e),n=`${this.#X}/events`;fetch(n,{method:"POST",headers:{"X-API-Key":this.#K,"Content-Type":"application/json"},body:JSON.stringify(t)}).catch(t=>{i.warn("Analytics event dispatch failed",{eventName:e.name,error:t})})}catch{}}#ee(e){const t=new Date,n=1e3*t.getTime(),i=this.#te(e.name,e.distinctId,n),r="undefined"!=typeof window?window.location.hostname:"unknown";return{event_id:i,event_name:e.name,event_timestamp:t.toISOString(),distinct_id:e.distinctId,properties:{...e.properties,platform:"web",sdk_version:"0.1.5",app_bundle_id:r}}}#te(e,t,n){const i=`${e}_${t}_${n}`;let r=0;for(let e=0;e<i.length;e++)r=(r<<5)-r+i.charCodeAt(e)|0;const s=Math.abs(r).toString(16).padStart(8,"0"),o=n.toString(16).padStart(12,"0");return`${s}-${o.slice(0,4)}-4${o.slice(4,7)}-a${o.slice(7,10)}-${o.slice(10)}${s.slice(0,6)}`}}class v{#ne;constructor(){this.#ne=new Map}on(e,t){this.#ne.has(e)||this.#ne.set(e,new Set);const n=this.#ne.get(e);if(!n)throw new Error(`Failed to get handlers for event '${String(e)}'`);return n.add(t),i.debug(`Event listener added for '${String(e)}'`),()=>{this.off(e,t)}}off(e,t){const n=this.#ne.get(e);n&&(n.delete(t),i.debug(`Event listener removed for '${String(e)}'`),0===n.size&&this.#ne.delete(e))}emit(e,t){const n=this.#ne.get(e);if(n&&0!==n.size){i.debug(`Emitting event '${String(e)}'`,{listenerCount:n.size});for(const r of n)try{r(t)}catch(t){i.error(`Error in event handler for '${String(e)}':`,t)}}}removeAllListeners(e){e?(this.#ne.delete(e),i.debug(`All listeners removed for '${String(e)}'`)):(this.#ne.clear(),i.debug("All event listeners removed"))}listenerCount(e){return this.#ne.get(e)?.size??0}hasListeners(e){const t=this.#ne.get(e);return void 0!==t&&t.size>0}}const y="encore-sdk-styles",w="encore-";function x(e={}){if(document.getElementById(y))i.debug("Encore styles already injected");else try{const t=document.createElement("style");t.id=y,t.textContent=function(e={}){const t=function(e){const t=[];return e.primaryColor&&t.push(`--encore-primary-color: ${e.primaryColor};`),e.backgroundColor&&t.push(`--encore-bg-color: ${e.backgroundColor};`),e.textColor&&t.push(`--encore-text-color: ${e.textColor};`),e.borderRadius&&t.push(`--encore-border-radius: ${e.borderRadius};`),e.fontFamily&&t.push(`--encore-font-family: ${e.fontFamily};`),t.join("\n ")}(e);return`\n /* CSS Custom Properties (Theme Variables) */\n :root {\n ${t||"/* No custom theme variables */"}\n --encore-primary-color: ${e.primaryColor??"#4F46E5"};\n --encore-bg-color: ${e.backgroundColor??"#ffffff"};\n --encore-text-color: ${e.textColor??"#1F2937"};\n --encore-border-radius: ${e.borderRadius??"12px"};\n --encore-font-family: ${e.fontFamily??'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'};\n }\n\n /* Backdrop */\n .${w}backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.55);\n backdrop-filter: blur(2px);\n z-index: 9998;\n opacity: 0;\n transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .${w}backdrop.${w}visible {\n opacity: 1;\n }\n\n /* Modal Container */\n .${w}modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 9999;\n background-color: var(--encore-bg-color);\n border-radius: 20px;\n box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.18), 0 12px 24px -8px rgba(0, 0, 0, 0.08);\n max-width: 800px;\n max-height: 90vh;\n width: calc(100% - 32px);\n overflow-x: hidden;\n overflow-y: auto;\n opacity: 0;\n transform: translate(-50%, -50%) scale(0.96);\n transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1), transform 250ms cubic-bezier(0.4, 0, 0.2, 1);\n font-family: var(--encore-font-family);\n color: var(--encore-text-color);\n }\n\n .${w}modal.${w}visible {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n\n /* Close Button */\n .${w}close-button {\n position: absolute;\n top: 20px;\n right: 20px;\n width: 40px;\n height: 40px;\n border: none;\n background-color: rgba(255, 255, 255, 0.9);\n cursor: pointer;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #9CA3AF;\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n z-index: 10;\n }\n\n .${w}close-button:hover {\n background-color: #FFFFFF;\n color: #6B7280;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n transform: scale(1.05);\n }\n\n .${w}close-button:active {\n transform: scale(0.98);\n }\n\n .${w}close-button:focus {\n outline: 2px solid var(--encore-primary-color);\n outline-offset: 2px;\n }\n\n .${w}close-button svg {\n width: 18px;\n height: 18px;\n }\n\n /* Body scroll lock */\n body.${w}no-scroll {\n overflow: hidden;\n }\n\n /* Modal Header */\n .${w}modal-header {\n padding: 24px 24px 16px;\n border-bottom: 1px solid #E5E7EB;\n }\n\n .${w}modal-title {\n margin: 0;\n font-size: 24px;\n font-weight: 700;\n line-height: 1.25;\n color: var(--encore-text-color);\n }\n\n .${w}modal-subtitle {\n margin: 8px 0 0;\n font-size: 14px;\n color: #6B7280;\n line-height: 1.5;\n }\n\n /* Modal Body */\n .${w}modal-body {\n padding: 0;\n position: relative;\n isolation: isolate;\n }\n\n /* Carousel Container */\n .${w}carousel {\n display: flex;\n flex-direction: column;\n overflow: visible;\n }\n\n /* Carousel Header */\n .${w}carousel-header {\n padding: 40px 68px 28px;\n text-align: center;\n }\n\n .${w}carousel-title {\n font-size: 32px;\n font-weight: 510;\n line-height: 1.1;\n color: #181417;\n margin: 0 0 8px 0;\n letter-spacing: -0.3px;\n }\n\n .${w}carousel-subtitle {\n font-size: 16px;\n line-height: 1.2;\n color: #181417;\n margin: 0;\n font-weight: 400;\n }\n\n /* Carousel Cards Container - Horizontal Scroll */\n .${w}carousel-cards {\n display: flex;\n flex-direction: row;\n overflow-x: auto;\n overflow-y: hidden;\n scroll-behavior: smooth;\n scroll-snap-type: x mandatory;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n gap: 24px;\n padding: 24px 78px;\n position: relative;\n }\n\n .${w}carousel-cards::-webkit-scrollbar {\n display: none;\n }\n\n /* Carousel Item Wrapper */\n .${w}carousel-item {\n flex: 0 0 426px;\n width: 426px;\n scroll-snap-align: center;\n scroll-snap-stop: always;\n opacity: 0.5;\n transition: all 400ms cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: auto;\n }\n\n /* Active carousel item */\n .${w}carousel-item.${w}active {\n opacity: 1;\n z-index: 1;\n }\n\n /* Offer Card */\n .${w}offer-card {\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: 16px;\n box-shadow: 0 2px 12px rgba(116, 112, 133, 0.16);\n height: 370px;\n overflow: hidden;\n }\n\n /* Offer Banner */\n .${w}offer-banner {\n width: 100%;\n background-color: transparent;\n position: relative;\n padding: 0;\n height: 180px;\n overflow: hidden;\n border-radius: 16px 16px 0 0;\n }\n\n .${w}offer-banner-image {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n background-color: #F9FAFB;\n opacity: 0;\n transition: opacity 200ms ease-out;\n }\n\n .${w}offer-banner-image.${w}loaded {\n opacity: 1;\n }\n\n /* Info button on banner */\n .${w}banner-info-button {\n position: absolute;\n top: 20px;\n right: 20px;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background-color: rgba(242, 242, 242, 0.95);\n backdrop-filter: blur(6px);\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 150ms ease;\n z-index: 3;\n padding: 0;\n }\n\n .${w}banner-info-button:hover {\n background-color: #F2F2F2;\n transform: scale(1.05);\n }\n\n .${w}banner-info-button:focus {\n outline: 2px solid #5671FF;\n outline-offset: 2px;\n }\n\n .${w}banner-info-button svg {\n width: 14px;\n height: 14px;\n color: #181417;\n stroke-width: 2;\n }\n\n /* Tooltip */\n .${w}tooltip {\n position: fixed;\n background-color: rgba(28, 28, 32, 0.95);\n color: #ffffff;\n padding: 8px 12px;\n border-radius: 8px;\n font-size: 12px;\n line-height: 1.4;\n font-weight: 500;\n z-index: 10000;\n pointer-events: none;\n opacity: 0;\n transform: translateY(4px);\n transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n white-space: normal;\n word-wrap: break-word;\n }\n\n .${w}tooltip-visible {\n opacity: 1;\n transform: translateY(0);\n }\n\n /* Tooltip arrow (optional - using pseudo-element) */\n .${w}tooltip::after {\n content: '';\n position: absolute;\n width: 0;\n height: 0;\n border-style: solid;\n }\n\n .${w}tooltip-top::after {\n bottom: -4px;\n left: 50%;\n transform: translateX(-50%);\n border-width: 4px 4px 0 4px;\n border-color: rgba(28, 28, 32, 0.95) transparent transparent transparent;\n }\n\n .${w}tooltip-bottom::after {\n top: -4px;\n left: 50%;\n transform: translateX(-50%);\n border-width: 0 4px 4px 4px;\n border-color: transparent transparent rgba(28, 28, 32, 0.95) transparent;\n }\n\n .${w}tooltip-left::after {\n right: -4px;\n top: 50%;\n transform: translateY(-50%);\n border-width: 4px 0 4px 4px;\n border-color: transparent transparent transparent rgba(28, 28, 32, 0.95);\n }\n\n .${w}tooltip-right::after {\n left: -4px;\n top: 50%;\n transform: translateY(-50%);\n border-width: 4px 4px 4px 0;\n border-color: transparent rgba(28, 28, 32, 0.95) transparent transparent;\n }\n\n /* Offer Details */\n .${w}offer-details {\n padding: 16px 20px;\n flex: 1;\n overflow-y: auto;\n }\n\n .${w}offer-details-heading {\n font-size: 14px;\n font-weight: 400;\n color: #6A6D81;\n margin: 0 0 8px 0;\n letter-spacing: -1px;\n line-height: 1.2;\n }\n\n .${w}offer-details-list {\n list-style: disc;\n margin: 0;\n padding: 0 0 0 21px;\n }\n\n .${w}offer-details-list li {\n font-size: 14px;\n line-height: 1.2;\n color: #181417;\n margin-bottom: 4px;\n padding-left: 0;\n letter-spacing: -1px;\n }\n\n .${w}offer-details-list li:last-child {\n margin-bottom: 0;\n }\n\n .${w}offer-details-list li::marker {\n color: #6A6D81;\n }\n\n /* Offer Footer */\n .${w}offer-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-top: 1px solid #F2F2F2;\n gap: 12px;\n min-height: 74px;\n }\n\n /* Offer Merchant */\n .${w}offer-merchant {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n }\n\n .${w}offer-logo {\n width: 42px;\n height: 42px;\n border-radius: 8px;\n object-fit: contain;\n background-color: #F3F4F6;\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 200ms ease-out;\n }\n\n .${w}offer-logo.${w}loaded {\n opacity: 1;\n }\n\n .${w}offer-merchant-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex: 1;\n min-width: 0;\n }\n\n .${w}offer-merchant-name {\n font-size: 16px;\n font-weight: 590;\n color: #181417;\n line-height: 1.1;\n letter-spacing: -1px;\n }\n\n .${w}offer-merchant-desc {\n font-size: 14px;\n color: #6A6D81;\n line-height: 1.2;\n letter-spacing: -1px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* Claim Button */\n .${w}button-claim {\n padding: 10px 16px;\n height: 34px;\n min-width: 78px;\n font-size: 14px;\n font-weight: 590;\n border-radius: 999px;\n border: none;\n background: #5671FF;\n color: white;\n cursor: pointer;\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n font-family: var(--encore-font-family);\n white-space: nowrap;\n line-height: 1.2;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .${w}button-claim:hover:not(:disabled) {\n background: #4560E6;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(86, 113, 255, 0.3);\n }\n\n .${w}button-claim:active {\n transform: translateY(0);\n background: #3A52CC;\n }\n\n .${w}button-claim:focus {\n outline: 2px solid #5671FF;\n outline-offset: 2px;\n }\n\n .${w}button-claim:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n\n /* Carousel Navigation */\n .${w}carousel-navigation {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 40px;\n padding: 28px 32px 32px;\n }\n\n .${w}nav-button {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 1px solid #BBBBBB;\n background-color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #BBBBBB;\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n }\n\n .${w}nav-button:hover:not(:disabled) {\n border-color: #5671FF;\n color: #5671FF;\n transform: scale(1.05);\n }\n\n .${w}nav-button:active:not(:disabled) {\n transform: scale(0.95);\n }\n\n .${w}nav-button:focus {\n outline: 2px solid #5671FF;\n outline-offset: 2px;\n }\n\n .${w}nav-button svg {\n width: 20px;\n height: 20px;\n stroke-width: 2;\n }\n\n .${w}nav-button:not(:disabled) {\n border-color: #5671FF;\n color: #5671FF;\n }\n\n .${w}nav-button:disabled,\n .${w}nav-button.${w}disabled {\n opacity: 1;\n cursor: not-allowed;\n border-color: #BBBBBB;\n color: #BBBBBB;\n }\n\n .${w}nav-button:disabled:hover,\n .${w}nav-button.${w}disabled:hover {\n border-color: #BBBBBB;\n color: #BBBBBB;\n transform: none;\n }\n\n /* Loading State */\n .${w}loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px;\n }\n\n .${w}spinner {\n width: 40px;\n height: 40px;\n border: 3px solid #E5E7EB;\n border-top-color: var(--encore-primary-color);\n border-radius: 50%;\n animation: ${w}spin 0.8s linear infinite;\n }\n\n @keyframes ${w}spin {\n to { transform: rotate(360deg); }\n }\n\n /* Responsive: Mobile (0-767px) */\n @media (max-width: 767px) {\n .${w}modal {\n width: calc(100% - 24px);\n max-width: 100%;\n margin: 12px;\n }\n\n .${w}carousel-header {\n padding: 24px 20px 20px;\n }\n\n .${w}carousel-title {\n font-size: 22px;\n }\n\n .${w}carousel-subtitle {\n font-size: 14px;\n }\n\n .${w}carousel-cards {\n padding: 20px 40px;\n }\n\n .${w}carousel-item {\n flex: 0 0 calc(100% - 80px);\n }\n\n .${w}offer-banner {\n padding: 16px 16px 0;\n }\n\n .${w}offer-details {\n padding: 20px 20px;\n }\n\n .${w}offer-footer {\n padding: 16px 20px 24px;\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .${w}offer-merchant {\n flex: 1 1 100%;\n }\n\n .${w}button-claim {\n flex: 1 1 100%;\n }\n\n .${w}carousel-navigation {\n padding: 20px 20px 24px;\n }\n }\n\n /* Responsive: Tablet (768-1023px) */\n @media (min-width: 768px) and (max-width: 1023px) {\n .${w}modal {\n max-width: 600px;\n }\n }\n\n /* Responsive: Desktop (1024px+) */\n @media (min-width: 1024px) {\n .${w}modal {\n max-width: 600px;\n }\n }\n\n /* Accessibility: High Contrast Mode */\n @media (prefers-contrast: high) {\n .${w}button {\n border: 2px solid currentColor;\n }\n }\n\n /* Accessibility: Reduced Motion */\n @media (prefers-reduced-motion: reduce) {\n .${w}backdrop,\n .${w}modal,\n .${w}button,\n .${w}close-button {\n transition: none;\n }\n\n .${w}spinner {\n animation: none;\n }\n }\n\n /* Focus Visible (for keyboard navigation) */\n .${w}button:focus-visible,\n .${w}close-button:focus-visible {\n outline: 2px solid var(--encore-primary-color);\n outline-offset: 2px;\n }\n\n /* ===== Success Screen ===== */\n .${w}success-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem 2rem;\n text-align: center;\n min-height: 400px;\n animation: ${w}fade-in 0.3s ease-out;\n }\n\n .${w}success-icon {\n width: 80px;\n height: 80px;\n background: linear-gradient(135deg, var(--encore-primary-color), #10b981);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 48px;\n color: white;\n margin-bottom: 1.5rem;\n animation: ${w}scale-in 0.5s ease-out;\n }\n\n .${w}success-title {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--encore-text-color);\n margin: 0 0 0.75rem 0;\n }\n\n .${w}success-subtitle {\n font-size: 1.125rem;\n color: var(--encore-text-muted);\n margin: 0 0 2rem 0;\n line-height: 1.6;\n }\n\n .${w}success-details {\n background: rgba(79, 70, 229, 0.05);\n border-radius: 12px;\n padding: 1.5rem;\n margin-bottom: 2rem;\n min-width: 280px;\n }\n\n .${w}success-detail {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.5rem 0;\n }\n\n .${w}success-detail:not(:last-child) {\n border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n }\n\n .${w}success-detail-label {\n font-size: 0.875rem;\n color: var(--encore-text-muted);\n font-weight: 500;\n }\n\n .${w}success-detail-value {\n font-size: 1rem;\n color: var(--encore-text-color);\n font-weight: 600;\n }\n\n .${w}success-button {\n background: linear-gradient(135deg, var(--encore-primary-color), #10b981);\n color: white;\n border: none;\n border-radius: var(--encore-border-radius);\n padding: 0.875rem 2.5rem;\n font-size: 1rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n }\n\n .${w}success-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);\n }\n\n .${w}success-button:active {\n transform: translateY(0);\n }\n\n .${w}success-button:focus-visible {\n outline: 2px solid var(--encore-primary-color);\n outline-offset: 2px;\n }\n\n @keyframes ${w}scale-in {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n }\n `}(e),document.head.appendChild(t),i.debug("Encore styles injected successfully")}catch(e){i.error("Failed to inject Encore styles:",e)}}function I(e){return`${w}${e}`}class E{#ie;#re=null;#se=null;#oe=null;#ae=null;#le=!1;#ce=null;#de=[];#ue=null;constructor(e={}){this.#ie=new v,x(e)}show(){this.#le?i.warn("Modal is already visible"):(this.#ce=document.activeElement,this.#he(),this.#re&&document.body.appendChild(this.#re),this.#se&&document.body.appendChild(this.#se),document.body.classList.add(I("no-scroll")),requestAnimationFrame(()=>{this.#re?.classList.add(I("visible")),this.#se?.classList.add(I("visible"))}),this.#pe(),this.#fe(),this.#me(),this.#le=!0,this.#ie.emit("show",void 0),i.debug("Modal shown"))}hide(){this.#le&&(this.#re?.classList.remove(I("visible")),this.#se?.classList.remove(I("visible")),setTimeout(()=>{this.#ge(),document.body.classList.remove(I("no-scroll")),this.#ce instanceof HTMLElement&&this.#ce.focus(),this.#le=!1,this.#ie.emit("hide",void 0),i.debug("Modal hidden")},200))}isVisible(){return this.#le}setContent(e){this.#ae?(this.#ae.innerHTML="",this.#ae.appendChild(e),this.#fe()):i.error("Modal body not initialized")}on(e,t){return this.#ie.on(e,t)}#he(){this.#re=document.createElement("div"),this.#re.className=I("backdrop"),this.#re.setAttribute("aria-hidden","true"),this.#se=document.createElement("div"),this.#se.className=I("modal"),this.#se.setAttribute("role","dialog"),this.#se.setAttribute("aria-modal","true"),this.#se.setAttribute("aria-labelledby",I("modal-title")),this.#oe=document.createElement("button"),this.#oe.className=I("close-button"),this.#oe.setAttribute("aria-label","Close modal"),this.#oe.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">\n <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />\n </svg>\n ',this.#ae=document.createElement("div"),this.#ae.className=I("modal-body"),this.#se.appendChild(this.#oe),this.#se.appendChild(this.#ae)}#ge(){this.#re?.remove(),this.#se?.remove(),this.#re=null,this.#se=null,this.#oe=null,this.#ae=null}#pe(){this.#oe?.addEventListener("click",()=>{this.#ie.emit("close",void 0),this.hide()}),this.#re?.addEventListener("click",()=>{this.#ie.emit("backdropClick",void 0),this.hide()}),this.#ue=this.#be.bind(this),document.addEventListener("keydown",this.#ue)}#be(e){if(this.#le)switch(e.key){case"Escape":e.preventDefault(),this.#ie.emit("close",void 0),this.hide();break;case"Tab":e.preventDefault(),this.#ve(e.shiftKey)}}#ve(e){if(0===this.#de.length)return;const t=this.#de.findIndex(e=>e===document.activeElement);let n;n=e?t<=0?this.#de.length-1:t-1:t>=this.#de.length-1?0:t+1,this.#de[n]?.focus()}#fe(){if(!this.#se)return;const e=["button:not([disabled])","a[href]","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(", ");this.#de=Array.from(this.#se.querySelectorAll(e))}#me(){this.#de.length>0&&this.#de[0]?.focus()}destroy(){this.#ue&&document.removeEventListener("keydown",this.#ue),this.#ie.removeAllListeners(),this.hide()}}class C{#ye=null;#we;#xe;#le=!1;#Ie=null;#Ee=null;#Ce=null;#ke=null;#$e=null;constructor(e,t){this.#we=e,this.#xe={position:"top",maxWidth:200,...t},this.#Te()}#Te(){this.#Ce=this.#Ae.bind(this),this.#ke=this.#Le.bind(this),this.#$e=this.#Ne.bind(this),this.#we.addEventListener("mouseenter",this.#Ce),this.#we.addEventListener("mouseleave",this.#ke)}#Ae(){this.#Ee&&(clearTimeout(this.#Ee),this.#Ee=null),this.#Ie=window.setTimeout(()=>{this.#Se()},50)}#Le(){this.#Ie&&(clearTimeout(this.#Ie),this.#Ie=null),this.#Ee=window.setTimeout(()=>{this.#Re()},100)}#Se(){if(this.#le)return;this.#ye=document.createElement("div"),this.#ye.className=I("tooltip"),this.#ye.setAttribute("role","tooltip"),this.#ye.textContent=this.#xe.content,this.#xe.maxWidth&&(this.#ye.style.maxWidth=`${this.#xe.maxWidth}px`),this.#xe.position&&this.#ye.classList.add(I(`tooltip-${this.#xe.position}`));const e=this.#we.getBoundingClientRect();this.#ye.style.top=`${e.top}px`,this.#ye.style.left=`${e.left}px`,document.body.appendChild(this.#ye),this.#$e&&(window.addEventListener("scroll",this.#$e,!0),window.addEventListener("resize",this.#$e)),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.#ye&&(this.#Ne(),this.#ye.classList.add(I("tooltip-visible")))})}),this.#le=!0}#Re(){this.#le&&this.#ye&&(this.#$e&&(window.removeEventListener("scroll",this.#$e,!0),window.removeEventListener("resize",this.#$e)),this.#ye.classList.remove(I("tooltip-visible")),setTimeout(()=>{this.#ye&&this.#ye.parentNode&&this.#ye.parentNode.removeChild(this.#ye),this.#ye=null},200),this.#le=!1)}#Ne(){if(!this.#ye||!this.#le)return;const e=this.#we.getBoundingClientRect(),t=this.#ye.getBoundingClientRect();let n=0,i=0;switch(this.#xe.position??"top"){case"top":n=e.top-t.height-8,i=e.left+e.width/2-t.width/2;break;case"bottom":n=e.bottom+8,i=e.left+e.width/2-t.width/2;break;case"left":n=e.top+e.height/2-t.height/2,i=e.left-t.width-8;break;case"right":n=e.top+e.height/2-t.height/2,i=e.right+8}i=Math.max(8,Math.min(i,window.innerWidth-t.width-8)),n=Math.max(8,Math.min(n,window.innerHeight-t.height-8)),this.#ye.style.top=`${n}px`,this.#ye.style.left=`${i}px`}updateContent(e){this.#xe.content=e,this.#ye&&(this.#ye.textContent=e,this.#Ne())}destroy(){this.#Ie&&(clearTimeout(this.#Ie),this.#Ie=null),this.#Ee&&(clearTimeout(this.#Ee),this.#Ee=null),this.#le&&this.#Re(),this.#Ce&&this.#we.removeEventListener("mouseenter",this.#Ce),this.#ke&&this.#we.removeEventListener("mouseleave",this.#ke),this.#$e&&(window.removeEventListener("scroll",this.#$e,!0),window.removeEventListener("resize",this.#$e))}}class k{#ie;#Ue=null;#Oe=null;#Me=null;constructor(){this.#ie=new v}render(e){this.#Ue=e,this.#Oe=document.createElement("div"),this.#Oe.className=I("offer-card");const t=this.#Be(e.imageUrl,e.title,e.tooltipText);this.#Oe.appendChild(t);const n=this.#Fe(e);this.#Oe.appendChild(n);const i=this.#De(e);return this.#Oe.appendChild(i),this.#Oe}on(e,t){return this.#ie.on(e,t)}#Be(e,t,n){const r=document.createElement("div");r.className=I("offer-banner");const s=document.createElement("img");s.className=I("offer-banner-image"),s.alt=t??"Offer image",e?(s.src=e,s.complete?s.classList.add(I("loaded")):s.onload=()=>{s.classList.add(I("loaded"))},s.onerror=()=>{i.warn("Failed to load offer image, using fallback"),s.src=this.#Pe(),s.classList.add(I("loaded"))}):(s.src=this.#Pe(),s.classList.add(I("loaded"))),r.appendChild(s);const o=document.createElement("button");return o.className=I("banner-info-button"),o.setAttribute("aria-label","More information"),o.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">\n <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />\n </svg>\n ',o.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),i.debug("Info button clicked for offer",{title:t,tooltipText:n})}),n&&(this.#Me=new C(o,{content:n,position:"bottom",maxWidth:200}),r.appendChild(o)),r}#Pe(){return`data:image/svg+xml;base64,${btoa('\n <svg xmlns="http://www.w3.org/2000/svg" width="600" height="240" viewBox="0 0 600 240">\n <rect width="600" height="240" fill="#E5E7EB"/>\n <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#9CA3AF" font-family="sans-serif" font-size="18">\n Offer Image\n </text>\n </svg>\n ')}`}#Fe(e){const t=document.createElement("div");t.className=I("offer-details");const n=document.createElement("h3");n.className=I("offer-details-heading"),n.textContent="Offer details";const i=document.createElement("ul");if(i.className=I("offer-details-list"),e.instructions&&e.instructions.length>0)e.instructions.forEach(e=>{const t=document.createElement("li");t.textContent=e.subtitle||e.title,i.appendChild(t)});else if(e.description){const t=document.createElement("li");t.textContent=e.description,i.appendChild(t)}return t.appendChild(n),t.appendChild(i),t}#De(e){const t=document.createElement("div");t.className=I("offer-footer");const n=document.createElement("div");if(n.className=I("offer-merchant"),e.logoUrl){const t=document.createElement("img");t.className=I("offer-logo"),t.src=e.logoUrl,t.alt=`${e.merchantName??"Merchant"} logo`,t.complete?t.classList.add(I("loaded")):t.onload=()=>{t.classList.add(I("loaded"))},t.onerror=()=>{i.warn("Failed to load merchant logo",{merchantName:e.merchantName}),t.style.display="none"},n.appendChild(t)}const r=document.createElement("div");if(r.className=I("offer-merchant-text"),e.merchantName){const t=document.createElement("div");t.className=I("offer-merchant-name"),t.textContent=e.merchantName,r.appendChild(t)}if(e.quickInstructions){const t=document.createElement("div");t.className=I("offer-merchant-desc"),t.textContent=e.quickInstructions,r.appendChild(t)}n.appendChild(r);const s=document.createElement("button");return s.className=`${I("button")} ${I("button-claim")}`,s.textContent=e.ctaText??"Claim",s.setAttribute("aria-label",`Claim offer: ${e.title??"offer"}`),s.addEventListener("click",()=>{this.#Ue&&this.#ie.emit("claim",{offer:this.#Ue})}),t.appendChild(n),t.appendChild(s),t}destroy(){this.#Me&&(this.#Me.destroy(),this.#Me=null),this.#ie.removeAllListeners(),this.#Oe=null,this.#Ue=null}}class ${#ie;#_e;#qe=0;#Oe=null;#Ke=null;#ze=null;#Ve=[];#He=null;#Ge=null;#je=null;constructor(e){if(this.#ie=new v,this.#_e=e,0===e.length)throw new Error("OfferCarousel requires at least one offer");this.#We()}render(){this.#Oe=document.createElement("div"),this.#Oe.className=I("carousel"),this.#He=document.createElement("div"),this.#He.setAttribute("role","status"),this.#He.setAttribute("aria-live","polite"),this.#He.setAttribute("aria-atomic","true"),this.#He.className="sr-only",this.#He.style.position="absolute",this.#He.style.width="1px",this.#He.style.height="1px",this.#He.style.padding="0",this.#He.style.margin="-1px",this.#He.style.overflow="hidden",this.#He.style.clip="rect(0, 0, 0, 0)",this.#He.style.whiteSpace="nowrap",this.#He.style.border="0";const e=this.#Qe();if(this.#Oe.appendChild(e),this.#Ke=document.createElement("div"),this.#Ke.className=I("carousel-cards"),this.#Oe.appendChild(this.#He),this.#Oe.appendChild(this.#Ke),this.#_e.length>1){const e=this.#Ye();this.#Oe.appendChild(e)}return this.#Ze(),this.#Je(),this.#Xe(),this.#et(0,!1),this.#Oe}on(e,t){return this.#ie.on(e,t)}getCurrentIndex(){return this.#qe}getTotalOffers(){return this.#_e.length}next(){this.#qe<this.#_e.length-1&&(this.#qe++,this.#et(this.#qe),this.#tt(),this.#nt(`Showing offer ${this.#qe+1} of ${this.#_e.length}`),i.debug(`Navigated to offer ${this.#qe+1}`))}previous(){this.#qe>0&&(this.#qe--,this.#et(this.#qe),this.#tt(),this.#nt(`Showing offer ${this.#qe+1} of ${this.#_e.length}`),i.debug(`Navigated to offer ${this.#qe+1}`))}#Ze(){if(!this.#Ke)return;const e=this.#Ke;this.#_e.forEach((t,n)=>{const i=new k,r=i.render(t),s=document.createElement("div");s.className=I("carousel-item"),s.setAttribute("data-index",n.toString()),s.appendChild(r),i.on("claim",()=>{this.#ie.emit("offerClaim",{offer:t,index:n})}),this.#Ve.push(i),e.appendChild(s)}),requestAnimationFrame(()=>{e.classList.add(I("cards-ready"))})}#et(e,t=!0){if(!this.#Ke)return;const n=this.#Ke.querySelectorAll(`.${I("carousel-item")}`),i=n[e];if(i){i.scrollIntoView({behavior:t?"smooth":"auto",block:"nearest",inline:"center"}),n.forEach((t,n)=>{n===e?t.classList.add(I("active")):t.classList.remove(I("active"))});const r=this.#_e[e];r&&this.#ie.emit("offerView",{offer:r,index:e})}}#Qe(){const e=document.createElement("div");e.className=I("carousel-header");const t=document.createElement("h2");t.className=I("carousel-title"),t.id=I("modal-title"),t.textContent="Unlock 10 free articles – choose an offer below";const n=document.createElement("p");return n.className=I("carousel-subtitle"),n.textContent="Activate one of these partner offers and get 10 free articles. No credit card required.",e.appendChild(t),e.appendChild(n),e}#Ye(){const e=document.createElement("div");e.className=I("carousel-navigation");const t=document.createElement("button");t.className=I("nav-button"),t.setAttribute("aria-label","Previous offer"),t.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="transform: rotate(90deg);">\n <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />\n </svg>\n ',t.addEventListener("click",()=>this.previous());const n=document.createElement("button");return n.className=I("nav-button"),n.setAttribute("aria-label","Next offer"),n.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" style="transform: rotate(270deg);">\n <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />\n </svg>\n ',n.addEventListener("click",()=>this.next()),e.appendChild(t),e.appendChild(n),this.#ze=e,this.#tt(t,n),e}#tt(e,t){if(!this.#ze)return;const n=this.#ze.querySelectorAll(`.${I("nav-button")}`),i=e??n[0],r=t??n[1];i&&(i.disabled=0===this.#qe,i.classList.toggle(I("disabled"),0===this.#qe)),r&&(r.disabled=this.#qe===this.#_e.length-1,r.classList.toggle(I("disabled"),this.#qe===this.#_e.length-1))}#Je(){this.#Ge=this.#it.bind(this),document.addEventListener("keydown",this.#Ge)}#it(e){if(this.#Oe)switch(e.key){case"ArrowLeft":e.preventDefault(),this.previous();break;case"ArrowRight":e.preventDefault(),this.next()}}#Xe(){this.#Ke&&this.#Ke.addEventListener("scroll",()=>{this.#je&&clearTimeout(this.#je),this.#je=window.setTimeout(()=>{this.#rt()},100)})}#rt(){if(!this.#Ke)return;const e=this.#Ke,t=e.querySelectorAll(`.${I("carousel-item")}`),n=e.getBoundingClientRect(),r=n.left+n.width/2;let s=0,o=1/0;if(t.forEach((e,t)=>{const n=e.getBoundingClientRect(),i=Math.abs(r-(n.left+n.width/2));i<o&&(o=i,s=t)}),s!==this.#qe){this.#qe=s,t.forEach((e,t)=>{t===s?e.classList.add(I("active")):e.classList.remove(I("active"))}),this.#tt();const e=this.#_e[s];e&&this.#ie.emit("offerView",{offer:e,index:s}),i.debug(`Scrolled to offer ${s+1}`)}}#nt(e){this.#He&&(this.#He.textContent=e)}#We(){this.#_e.forEach(e=>{e.imageUrl&&((new Image).src=e.imageUrl,i.debug("Preloading offer image",{offerId:e.id,url:e.imageUrl})),e.logoUrl&&((new Image).src=e.logoUrl,i.debug("Preloading merchant logo",{offerId:e.id,url:e.logoUrl}))})}destroy(){this.#Ge&&document.removeEventListener("keydown",this.#Ge),this.#je&&(clearTimeout(this.#je),this.#je=null),this.#Ve.forEach(e=>e.destroy()),this.#Ve=[],this.#ie.removeAllListeners(),this.#Oe=null,this.#Ke=null,this.#ze=null,this.#He=null}}const T=e=>`encore-success-${e}`;class A{#Oe=null;#ie;#t;#st=null;constructor(e){this.#t=e,this.#ie=new v}render(){this.#Oe=document.createElement("div"),this.#Oe.className=T("container");const e=document.createElement("div");e.className=T("icon"),e.innerHTML="✓";const t=document.createElement("h2");t.className=T("title"),t.textContent=this.#t.titleText??"Success!";const n=document.createElement("p");n.className=T("subtitle"),n.textContent=this.#t.subtitleText??this.#ot(this.#t.entitlement);const r=document.createElement("div");r.className=T("details"),r.innerHTML=this.#at(this.#t.entitlement);const s=document.createElement("button");return s.className=T("button"),s.textContent=this.#t.buttonText??"Continue",s.setAttribute("type","button"),s.addEventListener("click",()=>this.#lt()),this.#Oe.appendChild(e),this.#Oe.appendChild(t),this.#Oe.appendChild(n),this.#Oe.appendChild(r),this.#Oe.appendChild(s),this.#t.autoDismissMs&&this.#t.autoDismissMs>0&&this.#ct(this.#t.autoDismissMs),i.debug("Success screen rendered"),this.#Oe}on(e,t){return this.#ie.on(e,t)}destroy(){null!==this.#st&&(clearTimeout(this.#st),this.#st=null),this.#Oe&&(this.#Oe.remove(),this.#Oe=null),this.#ie.removeAllListeners(),i.debug("Success screen destroyed")}#lt(){i.debug("User clicked continue on success screen"),this.#ie.emit("continue",void 0)}#ct(e){this.#st=window.setTimeout(()=>{i.debug("Success screen auto-dismissing"),this.#ie.emit("continue",void 0)},e)}#ot(e){switch(e.type){case"freeTrial":return`You've unlocked a ${e.value??""} ${e.unit??"day"} free trial!`;case"discount":return`You've received a ${e.value??""}${"percent"===e.unit?"%":""} discount!`;case"credit":return`You've earned $${e.value??"0"} in credits!`;default:return"You've unlocked a special offer!"}}#at(e){const t=[];if("freeTrial"===e.type)t.push(`<div class="${T("detail")}">\n <span class="${T("detail-label")}">Type:</span>\n <span class="${T("detail-value")}">Free Trial</span>\n </div>`),e.value&&e.unit&&t.push(`<div class="${T("detail")}">\n <span class="${T("detail-label")}">Duration:</span>\n <span class="${T("detail-value")}">${e.value} ${e.unit}</span>\n </div>`);else if("discount"===e.type){if(t.push(`<div class="${T("detail")}">\n <span class="${T("detail-label")}">Type:</span>\n <span class="${T("detail-value")}">Discount</span>\n </div>`),e.value&&e.unit){const n="percent"===e.unit?`${e.value}%`:`$${e.value}`;t.push(`<div class="${T("detail")}">\n <span class="${T("detail-label")}">Amount:</span>\n <span class="${T("detail-value")}">${n}</span>\n </div>`)}}else"credit"===e.type&&(t.push(`<div class="${T("detail")}">\n <span class="${T("detail-label")}">Type:</span>\n <span class="${T("detail-value")}">Credit</span>\n </div>`),e.value&&t.push(`<div class="${T("detail")}">\n <span class="${T("detail-label")}">Amount:</span>\n <span class="${T("detail-value")}}">$${e.value}</span>\n </div>`));return t.join("")}}class L{#dt=null;#ut=null;#ht=!1;start(e){this.#ht?i.warn("FocusDetector already active"):(this.#dt=()=>{i.debug("Window focused"),e()},this.#ut=()=>{"visible"===document.visibilityState&&(i.debug("Document became visible"),e())},window.addEventListener("focus",this.#dt),document.addEventListener("visibilitychange",this.#ut),this.#ht=!0,i.debug("FocusDetector started"))}stop(){this.#ht&&(this.#dt&&(window.removeEventListener("focus",this.#dt),this.#dt=null),this.#ut&&(document.removeEventListener("visibilitychange",this.#ut),this.#ut=null),this.#ht=!1,i.debug("FocusDetector stopped"))}isActive(){return this.#ht}}const N="0.1.5",S="user_id",R="user_attributes",U=new class{#pt;#h;#p=null;#E=null;#ft=null;#mt=null;#gt=null;#f=null;#bt={};#vt=!1;#yt=!1;#wt={};constructor(){this.#pt=new r,this.#h=new o}configure(e){if(this.#pt.configure(e)){this.#xt();const e=this.#pt.getBaseURL(),t=this.#pt.getAnalyticsBaseURL(),n=this.#pt.getApiKey()??"";if(e&&(this.#p=new g(n,e),t&&(this.#E=new b(n,t)),this.#f&&(this.#ft=new l(this.#h,this.#p,this.#f),this.#mt=new u(this.#p,this.#f,this.#E??void 0)),this.#gt=new L),i.info("Encore SDK initialized successfully",{version:N}),this.#E&&this.#f){const e="undefined"!=typeof window?window.location.hostname:"unknown";this.#E.track(function(e,t,n){return{name:"sdk_initialized",distinctId:e,properties:{sdkVersion:t,appBundleId:n,platform:"web"}}}(this.#f,N,e))}this.#p&&this.#f&&this.#p.initUser(this.#f).catch(e=>{i.warn("Failed to init user on backend (non-blocking)",e)}),this.#p&&this.#f&&this.#p.fetchConfig(this.#f,N).then(e=>{if(e.ui?.values?.text){const t=e.ui.values.text;this.#wt={...t},i.debug("Remote config loaded",t)}}).catch(e=>{i.warn("Failed to fetch remote config (non-blocking)",e)})}}#xt(){const e=this.#h.get(S);e?(this.#f=e,i.debug("Loaded existing user ID:",e)):(this.#f=d(),this.#h.set(S,this.#f),i.debug("Generated new user ID:",this.#f));const t=this.#h.get(R);t&&(this.#bt=t,i.debug("Loaded user attributes"))}#It(){return!!this.#pt.isConfigured()||(i.error("SDK not configured. Call Encore.configure() first."),!1)}identify(e,t){if(!this.#It())return;if(!e||"string"!=typeof e)return void i.error("identify() requires a valid user ID string");const n=this.#f;if(this.#f=e,this.#h.set(S,e),t&&this.setUserAttributes(t),n!==e&&(i.info("User identified:",e),this.#ft&&this.#ft.setUserId(e),this.#mt&&this.#mt.setUserId(e),this.#p&&n&&this.#p.identifyUser(n,e,t?.email?{email:t.email}:void 0).catch(e=>{i.warn("Failed to identify user on backend (non-blocking)",e)}),this.#E)){const n="undefined"!=typeof window?window.location.hostname:"unknown";this.#E.track(function(e,t,n,i){return{name:"user_identified",distinctId:e,properties:{userId:t,appBundleId:n,...i&&{attributes:i}}}}(e,e,n,t))}}getCurrentUserId(){return this.#f}reset(){this.#It()&&(i.info("Resetting SDK"),this.#h.clear(),this.#f=d(),this.#h.set(S,this.#f),this.#bt={},this.#wt={},this.#ft&&(this.#ft.clearQueue(),this.#ft.destroy(),this.#p&&this.#f&&(this.#ft=new l(this.#h,this.#p,this.#f))),this.#mt&&(this.#mt.clearCache(),this.#p&&this.#f&&(this.#mt=new u(this.#p,this.#f,this.#E??void 0))),this.#gt?.isActive()&&this.#gt.stop(),i.debug("SDK reset complete",{newUserId:this.#f}))}getVersion(){return N}setLogLevel(e){i.setLogLevel(e)}async revokeEntitlements(){if(!this.#It())return!1;if(!this.#p||!this.#f)return!1;try{return await this.#p.revokeEntitlements(this.#f)}catch(e){return i.error("Failed to revoke entitlements",e),!1}}setUserAttributes(e){this.#It()&&(e&&"object"==typeof e?(this.#bt={...this.#bt,...e,custom:{...this.#bt.custom,...e.custom}},this.#h.set(R,this.#bt),i.debug("User attributes updated",this.#bt)):i.error("setUserAttributes() requires a valid UserAttributes object"))}getUserAttributes(){return{...this.#bt}}async presentOffer(e){if(!this.#It()){const n={type:"error",error:{code:t.INITIALIZATION_ERROR,message:"SDK not configured"}};return e?.onNotGranted&&e.onNotGranted(n),e?.onError&&e.onError({code:t.INITIALIZATION_ERROR,message:"SDK not configured"}),{granted:!1,reason:n}}if(this.#vt){i.warn("Presentation already in progress");const n={type:"error",error:{code:t.UNKNOWN_ERROR,message:"Presentation already in progress"}};return e?.onNotGranted&&e.onNotGranted(n),{granted:!1,reason:n}}this.#vt=!0;try{const t=await this.#Et(e);return t.granted&&t.entitlement&&e?.onGranted?e.onGranted(t.entitlement):!t.granted&&t.reason&&e?.onNotGranted&&e.onNotGranted(t.reason),t}catch(n){i.error("Error during presentation",n),this.#Ct("Presentation flow error",n);const r={type:"error",error:{code:t.UNKNOWN_ERROR,message:n instanceof Error?n.message:"Unknown error"}};return e?.onError&&"string"!=typeof r&&"error"===r.type&&e.onError(r.error),e?.onNotGranted&&e.onNotGranted(r),{granted:!1,reason:r}}finally{this.#vt=!1}}isActive(e,t){return i.error("isActive() has been removed. Entitlement validation must be done server-side. See: https://docs.encorekit.com/server-side-validation"),!1}didGrant(e,t){this.#It()&&(this.#ft?t&&"string"==typeof t?this.#ft.sendGrantSignal(t,e):i.error("didGrant() requires a valid transaction ID"):i.error("SignalManager not initialized"))}async waitForVerification(e,t){if(!this.#It())return i.error("SDK not configured"),"failed";if(!this.#p)return i.error("API client not initialized"),"failed";if(!e)return i.error("waitForVerification() requires a transaction ID"),"failed";try{i.debug("Starting verification wait",{transactionId:e,timeout:t});const n={transactionId:e};void 0!==t&&(n.timeout=t);const r=new h(this.#p,n);return await r.poll()}catch(t){return i.error("Error during verification wait",{transactionId:e,error:t}),"failed"}}on(e,t){return i.error("on() event listener has been removed. Entitlement validation must be done server-side. See: https://docs.encorekit.com/server-side-validation"),()=>{}}observeEntitlement(e,t){return i.error("observeEntitlement() has been removed. Entitlement validation must be done server-side. See: https://docs.encorekit.com/server-side-validation"),{subscribe:e=>()=>{}}}placement(){return new p(async()=>this.presentOffer())}#Ct(e,t){if(!this.#p)return;const n=t instanceof Error?t.message:String(t),i=t instanceof Error?t.stack:void 0;this.#p.reportError({errorType:t instanceof Error?t.constructor.name:"UnknownError",message:n,context:e,severity:"error",...i&&{stackTrace:i},...this.#f&&{userId:this.#f}}).catch(()=>{}),this.#E&&this.#f&&this.#E.track(function(e,t,n,i){return{name:"sdk_error",distinctId:e,properties:{errorType:t,errorDescription:n,...i&&{context:i}}}}(this.#f,t instanceof Error?t.constructor.name:"UnknownError",n,e))}async#Et(e){if(!this.#mt||!this.#p)return i.error("Managers not initialized"),{granted:!1,reason:{type:"error",error:{code:t.INITIALIZATION_ERROR,message:"Managers not initialized"}}};if(this.#E&&this.#f){const e=d();this.#E.track(function(e,t){return{name:"sdk_offer_presentation_triggered",distinctId:e,properties:{presentationId:t}}}(this.#f,e))}try{this.#yt||(x({}),this.#yt=!0),i.debug("Fetching offers");const{offers:e}=await this.#mt.fetchOffers(this.#bt);if(0===e.length)return i.info("No offers available"),this.#E&&this.#f&&this.#E.track(function(e,t,n){return{name:"sdk_offer_presentation_failed",distinctId:e,properties:{reason:"noOffersAvailable",presentationId:n}}}(this.#f,0,d())),{granted:!1,reason:"noOffersAvailable"};const n={...this.#pt.getUIConfiguration(),...this.#wt},r=this.#mt.beginPresentation(),s=new Map;e.forEach(e=>{s.set(e.id,d())}),this.#E&&this.#f&&this.#E.track(function(e,t,n){return{name:"sdk_offer_presentation_success",distinctId:e,properties:{presentationId:t,offerCount:n}}}(this.#f,r,e.length));const o=new E,a=new $(e),l=await new Promise(r=>{a.on("offerClaim",a=>{const l=a.offer;i.debug("User claimed offer",{offerId:l.id}),(async()=>{try{if(!this.#mt)throw new Error("OfferManager not initialized");const t=await this.#mt.startTransaction(l.campaignId),a=s.get(l.id)??"",c=e.indexOf(l);this.#mt.trackOfferClaimed(l,a,t,c,e.length);const d=this.#kt(l,t);this.#$t(d)||i.warn("Failed to open advertiser URL (popup blocked?)"),this.didGrant("provisional",t),this.#Tt(o,l.entitlement,()=>{var e,t;this.#E&&this.#f&&"credit"===l.entitlement.type&&this.#E.track((e=this.#f,t=this.#f,{name:"sdk_apply_credits_clicked",distinctId:e,properties:{creditsApplied:l.entitlement.value??0,userId:t}})),this.#mt?.endPresentation(),o.hide(),r({granted:!0,entitlement:l.entitlement})},n)}catch(e){i.error("Error starting transaction",{offerId:l.id,error:e}),this.#Ct("Transaction start error",e),this.#mt?.endPresentation("error"),o.hide(),r({granted:!1,reason:{type:"error",error:{code:t.UNKNOWN_ERROR,message:e instanceof Error?e.message:"Transaction failed"}}})}})()}),a.on("complete",e=>{e.claimed||(i.debug("User declined last offer"),this.#mt?.endPresentation("userDeclinedLastOffer"),a.destroy(),o.hide(),r({granted:!1,reason:"userDeclinedLastOffer"}))}),o.on("close",()=>{i.debug("User closed modal"),this.#mt?.endPresentation("userClosedModal"),a.destroy(),r({granted:!1,reason:"userClosedModal"})}),o.on("backdropClick",()=>{i.debug("User clicked outside modal"),this.#mt?.endPresentation("userClickedOutside"),a.destroy(),o.hide(),r({granted:!1,reason:"userClickedOutside"})}),a.on("offerView",t=>{const{offer:n}=t,i=s.get(n.id),r=e.indexOf(n);i&&this.#mt&&this.#mt.trackOfferPresented(n,i,r,e.length)}),o.show();const l=a.render();o.setContent(l)});return o.destroy(),a.destroy(),l}catch(e){return i.error("Error in presentation flow",e),this.#Ct("Presentation flow error",e),{granted:!1,reason:{type:"error",error:{code:t.UNKNOWN_ERROR,message:e instanceof Error?e.message:"Unknown error"}}}}}#kt(e,t){try{const n=new URL(e.advertiserUrl);e.trackingParameters&&Object.entries(e.trackingParameters).forEach(([e,t])=>{n.searchParams.append(e,String(t))});let r=n.toString();return r=r.replace(/TRANSACTION_ID/g,t),i.debug("Built final advertiser URL",{original:e.advertiserUrl,final:r,transactionId:t}),r}catch(n){return i.error("Failed to build advertiser URL",{url:e.advertiserUrl,error:n}),e.advertiserUrl.replace(/TRANSACTION_ID/g,t)}}#$t(e){try{const t=window.open(e,"_blank","noopener,noreferrer");return!!t&&(t.focus(),!0)}catch(t){return i.error("Failed to open advertiser URL",{url:e,error:t}),!1}}#Tt(e,t,n,r){try{const s={entitlement:t,autoDismissMs:0};r?.creditClaimedTitleText&&(s.titleText=r.creditClaimedTitleText),r?.creditClaimedSubtitleText&&(s.subtitleText=r.creditClaimedSubtitleText),r?.applyCreditsButtonText&&(s.buttonText=r.applyCreditsButtonText);const o=new A(s);o.on("continue",()=>{o.destroy(),n()});const a=o.render();e.setContent(a),i.debug("Success screen displayed")}catch(e){i.error("Failed to show success screen",e),n()}}};e.Encore=U,e.default=U,Object.defineProperty(e,"__esModule",{value:!0})});
2
2
  //# sourceMappingURL=encore.min.js.map