{"version":3,"sources":["newsletter-exit-intent.js","../../node_modules/exit-intent-js/src/exit-intent.js"],"names":["_defineProperties","e","r","t","length","o","enumerable","configurable","writable","Object","defineProperty","_toPropertyKey","key","_createClass","prototype","_classCallCheck","a","n","TypeError","_classPrivateMethodInitSpec","_checkPrivateRedeclaration","add","_classPrivateFieldInitSpec","set","has","_classPrivateFieldGet","s","get","_assertClassBrand","_classPrivateFieldSet","arguments","ownKeys","keys","getOwnPropertySymbols","filter","getOwnPropertyDescriptor","push","apply","_objectSpread","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","value","i","_toPrimitive","_typeof","Symbol","toPrimitive","call","String","Number","iterator","constructor","PAGE_VIEW_STORAGE_KEY","getPageViews","undefined","raw","localStorage","getItem","parseInt","isNaN","setPageViews","count","setItem","_","incrementPageViews","amount","updated","isMobileDevice","mobileBreakpoint","window","innerWidth","getScrollThreshold","scrollUpThreshold","mobile","desktop","observeExitIntent","config","timeOnPage","idleTime","mouseLeaveDelay","tabChange","windowBlur","eventName","debug","pageViewsToTrigger","scrollUpInterval","timers","listeners","mouseLeaveTimer","scrollCheckInterval","log","message","console","trigger","reason","event","CustomEvent","detail","dispatchEvent","currentViews","concat","setTimeout","idleTimer","resetIdle","clearTimeout","type","fn","addEventListener","el","onMouseOut","relatedTarget","toElement","onMouseOver","onVisibility","document","visibilityState","onBlur","activeElement","tagName","contains","currentScrollThreshold","lastScrollY","scrollY","deviceType","setInterval","currentScrollY","scrollDistance","destroy","_ref","removeEventListener","clearInterval","module","exports","_suppressNewsletterPopupCloseEvent","WeakMap","_NewsletterPopup_brand","WeakSet","NewsletterPopup","this","_bindEvents","_this","_suppressForSubscriberLink","Soho","plugins","delegate","_handleSubmit","newsletter","querySelector","dataset","autoPopup","cookie","indexOf","_scheduleAutoPopup","$","on","_openPopup","preventDefault","URLSearchParams","location","search","_SUBSCRIBER_QUERY_PARAM","_setCookie","_COOKIE_DAYS_SUBSCRIBE","_this2","form","target","scope","attr","resolvedScope","pathname","ajax","url","method","data","serialize","success","_handleAjaxSuccess","payload","html","val","magnificPopup","instance","isOpen","_updatePopupContent","successful","GTM","trackEvent","startsWith","hide","closest","find","removeAttr","show","content","replaceWith","popupClose","onclick","close","_shouldSuppressAutoPopup","_document$activeEleme","sessionStorage","body","hasAttribute","_SUPPRESSION_SELECTORS","join","_observeExitIntent","_AUTO_POPUP_DELAY","_this3","_this4","svg","Svg","open","items","src","closeMarkup","render","focus","callbacks","_onPopupOpen","documentElement","megaMenuIgnoreClick","_onPopupClose","afterClose","mainClass","fixedContentPos","trackExperiment","newsletterOptimizeExperimentId","ContentSquare","trackPopupOpenPageview","_COOKIE_DAYS_DISMISS","trackPopupClosePageview","name","days","expires","Date","setTime","getTime","toUTCString","_CheckoutThankYouNewsletter_brand","CheckoutThankYouNewsletter","_bind","_this5","_onSubmit","_this6","$form","_onSuccess","_window$Soho","_transformPanel","$panel","remove","msg","append"],"mappings":"AAAA,SAASA,kBAAkBC,EAAGC,GAAK,IAAK,IAAIC,EAAI,EAAGA,EAAID,EAAEE,OAAQD,IAAK,CAAE,IAAIE,EAAIH,EAAEC,GAAIE,EAAEC,WAAaD,EAAEC,aAAc,EAAID,EAAEE,cAAe,EAAI,UAAWF,IAAMA,EAAEG,UAAW,GAAKC,OAAOC,eAAeT,EAAGU,eAAeN,EAAEO,KAAMP,EAAI,CAAE,CACvO,SAASQ,aAAaZ,EAAGC,EAAGC,GAAK,OAAOD,GAAKF,kBAAkBC,EAAEa,UAAWZ,GAAIC,GAAKH,kBAAkBC,EAAGE,GAAIM,OAAOC,eAAeT,EAAG,YAAa,CAAEO,UAAU,IAAOP,CAAG,CAC1K,SAASc,gBAAgBC,EAAGC,GAAK,KAAMD,aAAaC,GAAI,MAAM,IAAIC,UAAU,oCAAsC,CAClH,SAASC,4BAA4BlB,EAAGe,GAAKI,2BAA2BnB,EAAGe,GAAIA,EAAEK,IAAIpB,EAAI,CACzF,SAASqB,2BAA2BrB,EAAGE,EAAGa,GAAKI,2BAA2BnB,EAAGE,GAAIA,EAAEoB,IAAItB,EAAGe,EAAI,CAC9F,SAASI,2BAA2BnB,EAAGE,GAAK,GAAIA,EAAEqB,IAAIvB,GAAI,MAAM,IAAIiB,UAAU,iEAAmE,CACjJ,SAASO,sBAAsBC,EAAGV,GAAK,OAAOU,EAAEC,IAAIC,kBAAkBF,EAAGV,GAAK,CAC9E,SAASa,sBAAsBH,EAAGV,EAAGd,GAAK,OAAOwB,EAAEH,IAAIK,kBAAkBF,EAAGV,GAAId,GAAIA,CAAG,CACvF,SAAS0B,kBAAkB3B,EAAGE,EAAGc,GAAK,GAAI,mBAAqBhB,EAAIA,IAAME,EAAIF,EAAEuB,IAAIrB,GAAI,OAAO2B,UAAU1B,OAAS,EAAID,EAAIc,EAAG,MAAM,IAAIC,UAAU,gDAAkD,CAClM,SAASa,QAAQ9B,EAAGC,GAAK,IAAIC,EAAIM,OAAOuB,KAAK/B,GAAI,GAAIQ,OAAOwB,sBAAuB,CAAE,IAAI5B,EAAII,OAAOwB,sBAAsBhC,GAAIC,IAAMG,EAAIA,EAAE6B,OAAO,SAAUhC,GAAK,OAAOO,OAAO0B,yBAAyBlC,EAAGC,GAAGI,UAAY,IAAKH,EAAEiC,KAAKC,MAAMlC,EAAGE,EAAI,CAAE,OAAOF,CAAG,CAC9P,SAASmC,cAAcrC,GAAK,IAAK,IAAIC,EAAI,EAAGA,EAAI4B,UAAU1B,OAAQF,IAAK,CAAE,IAAIC,EAAI,MAAQ2B,UAAU5B,GAAK4B,UAAU5B,GAAK,CAAC,EAAGA,EAAI,EAAI6B,QAAQtB,OAAON,IAAI,GAAIoC,QAAQ,SAAUrC,GAAKsC,gBAAgBvC,EAAGC,EAAGC,EAAED,GAAK,GAAKO,OAAOgC,0BAA4BhC,OAAOiC,iBAAiBzC,EAAGQ,OAAOgC,0BAA0BtC,IAAM4B,QAAQtB,OAAON,IAAIoC,QAAQ,SAAUrC,GAAKO,OAAOC,eAAeT,EAAGC,EAAGO,OAAO0B,yBAAyBhC,EAAGD,GAAK,EAAI,CAAE,OAAOD,CAAG,CACtb,SAASuC,gBAAgBvC,EAAGC,EAAGC,GAAK,OAAQD,EAAIS,eAAeT,MAAOD,EAAIQ,OAAOC,eAAeT,EAAGC,EAAG,CAAEyC,MAAOxC,EAAGG,YAAY,EAAIC,cAAc,EAAIC,UAAU,IAAQP,EAAEC,GAAKC,EAAGF,CAAG,CACnL,SAASU,eAAeR,GAAK,IAAIyC,EAAIC,aAAa1C,EAAG,UAAW,MAAO,UAAY2C,QAAQF,GAAKA,EAAIA,EAAI,EAAI,CAC5G,SAASC,aAAa1C,EAAGD,GAAK,GAAI,UAAY4C,QAAQ3C,KAAOA,EAAG,OAAOA,EAAG,IAAIF,EAAIE,EAAE4C,OAAOC,aAAc,QAAS,IAAM/C,EAAG,CAAE,IAAI2C,EAAI3C,EAAEgD,KAAK9C,EAAGD,GAAK,WAAY,GAAI,UAAY4C,QAAQF,GAAI,OAAOA,EAAG,MAAM,IAAI1B,UAAU,+CAAiD,CAAE,OAAQ,WAAahB,EAAIgD,OAASC,QAAQhD,EAAI,CAC3T,SAAS2C,QAAQzC,GAAgC,OAAOyC,QAAU,mBAAqBC,QAAU,iBAAmBA,OAAOK,SAAW,SAAU/C,GAAK,cAAcA,CAAG,EAAI,SAAUA,GAAK,OAAOA,GAAK,mBAAqB0C,QAAU1C,EAAEgD,cAAgBN,QAAU1C,IAAM0C,OAAOjC,UAAY,gBAAkBT,CAAG,EAAGyC,QAAQzC,EAAI,CCT7T,IAAAiD,sBAAA,yBAEA,SAAAC,eAAA,IAAA3C,EAAAkB,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAAwB,sBACA,IACA,IAAAG,EAAAC,aAAAC,QAAA/C,GACAK,EAAA2C,SAAAH,EAAA,IACA,OAAAI,MAAA5C,GAAA,EAAAA,CACA,CAAA,MAAAhB,GAEA,OAAA,CACA,CACA,CAEA,SAAA6D,aAAAC,GAAA,IAAAnD,EAAAkB,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAAwB,sBACA,IACAI,aAAAM,QAAApD,EAAAsC,OAAAa,GACA,CAAA,MAAAE,GACA,CAEA,CAQA,SAAAC,qBAAA,IAAAC,EAAArC,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAA,EAAAlB,EAAAkB,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAAwB,sBACAc,EAAAb,aAAA3C,GAAAuD,EAEA,OADAL,aAAAM,EAAAxD,GACAwD,CACA,CASA,SAAAC,iBAAA,IAAAC,EAAAxC,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAA,IACA,OAAAyC,OAAAC,YAAAF,CACA,CAQA,SAAAG,mBAAAC,GAAA,IAAAJ,EAAAxC,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAA,IAEA,MAAA,iBAAA4C,EACAA,EAIA,WAAA5B,QAAA4B,IAAA,OAAAA,EACAL,eAAAC,GACAI,EAAAC,QAAA,EAAAD,EAAAE,SAAA,EAGA,CACA,CAEA,SAAAC,oBAAA,IAEAC,EAAAxC,cAAA,CACAyC,WAAA,KACAC,SAAA,IACAC,gBAAA,IACAC,WAAA,EACAC,YAAA,EACAC,UAAA,cACAC,OAAA,EACAC,mBAAA,EAEAZ,kBAAA,CACAC,OAAA,IACAC,QAAA,KAEAN,iBAAA,IACAiB,iBAAA,KAjBAzD,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAA,CAAA,GAqBA0D,EAAA,GACAC,EAAA,GAEAC,EAAA,KACAC,EAAA,KAEA,SAAAC,EAAAC,GACAf,EAAAO,OACAS,QAAAF,IAAAC,EAEA,CAeA,SAAAE,EAAAC,GAEAJ,EAAA,0BAAAI,GACA,IAAAC,EAAA,IAAAC,YAAApB,EAAAM,UAAA,CAAAe,OAAAH,IACAzB,OAAA6B,cAAAH,EACA,CAIA,IAAAI,EAAA9C,eAiBA,GAhBAuB,EAAAQ,oBAAAe,GAAAvB,EAAAQ,qBACAR,EAAAO,OACAS,QAAAF,IAAA,4CAAAU,OAAAD,EAAA,2BAEAN,EAAA,cAOAjB,EAAAC,WAAA,GACAS,EAAApD,KAAAmE,WAAA,WAAA,OAAAR,EAAA,aAAA,EAAAjB,EAAAC,aAIAD,EAAAE,SAAA,EAAA,CAEA,IAAAwB,EACA,SAAAC,IACAD,GAAAE,aAAAF,GACAA,EAAAD,WAAA,WAAA,OAAAR,EAAA,WAAA,EAAAjB,EAAAE,SACA,CAEA,CAAA,YAAA,UAAA,YAAA,cAAAzC,QAAA,SAAAoE,GACA,IAAAC,EAAAH,EACAlC,OAAAsC,iBAAAF,EAAAC,GACAnB,EAAArD,KAAA,CAAA0E,GAAAvC,OAAAoC,KAAAA,EAAAC,GAAAA,GACA,GACAH,GACA,CAGA,GAAA3B,EAAAG,gBAAA,EAAA,CACA,SAAA8B,EAAA9G,GAEAA,EAAA+G,eAAA/G,EAAAgH,YACAvB,EAAAa,WAAA,WAAA,OAAAR,EAAA,aAAA,EAAAjB,EAAAG,iBAEA,CACA,SAAAiC,IAEAxB,GAAAgB,aAAAhB,EACA,CACAnB,OAAAsC,iBAAA,WAAAE,GACAxC,OAAAsC,iBAAA,YAAAK,GACAzB,EAAArD,KAAA,CAAA0E,GAAAvC,OAAAoC,KAAA,WAAAC,GAAAG,IACAtB,EAAArD,KAAA,CAAA0E,GAAAvC,OAAAoC,KAAA,YAAAC,GAAAM,GACA,CAGA,GAAApC,EAAAI,UAAA,CACA,SAAAiC,IACA,WAAAC,SAAAC,iBACAtB,EAAA,YAEA,CACAqB,SAAAP,iBAAA,mBAAAM,GACA1B,EAAArD,KAAA,CAAA0E,GAAAM,SAAAT,KAAA,mBAAAC,GAAAO,GACA,CAGA,GAAArC,EAAAK,WAAA,CACA,SAAAmC,IAGAf,WAAA,WACA,IAAAgB,EAAAH,SAAAG,cAIAA,GAAA,WAAAA,EAAAC,SAEAJ,SAAAK,SAAAF,GACA3B,EAAA,qDAKAG,EAAA,aACA,EAAA,EACA,CACAxB,OAAAsC,iBAAA,OAAAS,GACA7B,EAAArD,KAAA,CAAA0E,GAAAvC,OAAAoC,KAAA,OAAAC,GAAAU,GACA,CAIA,IAAAI,EAAAjD,mBAAAK,EAAAJ,kBAAAI,EAAAR,kBAEA,GAAAoD,EAAA,EAAA,CACA,IAAAC,EAAApD,OAAAqD,QACAC,EAAAxD,eAAAS,EAAAR,kBAAA,SAAA,UAEAsB,EAAA,oCAAAU,OAAAuB,EAAA,wBAAAvB,OAAAoB,EAAA,QAEA/B,EAAAmC,YAAA,WACA,IAAAC,EAAAxD,OAAAqD,QACAI,EAAAL,EAAAI,EAGAC,GAAAN,IACA9B,EAAA,gCAAAU,OAAA0B,EAAA,UAAA1B,OAAAxB,EAAAS,iBAAA,QAAAe,OAAAuB,EAAA,gBAAAvB,OAAAoB,EAAA,QACA3B,EAAA,aAGA4B,EAAAI,CACA,EAAAjD,EAAAS,iBACA,CAGA,MAAA,CAAA0C,QArIA,WACArC,EAAA,WACAJ,EAAAjD,QAAAmE,cACAlB,EAAA,GACAC,EAAAlD,QAAA,SAAA2F,GAAA,IAAApB,EAAAoB,EAAApB,GAAAH,EAAAuB,EAAAvB,KAAAC,EAAAsB,EAAAtB,GAAA,OAAAE,EAAAqB,oBAAAxB,EAAAC,EAAA,GACAnB,EAAA,GAEAC,GAAAgB,aAAAhB,GACAC,GAAAyC,cAAAzC,EACA,EA6HA,CAxMAzB,qBA2MAW,kBAAAX,mBAAAA,mBAGA,oBAAAmE,QAAAA,OAAAC,UACAD,OAAAC,QAAAzD,mBDnPA,IAAA0D,mCAAA,IAAAC,QAAAC,uBAAA,IAAAC,QAIAC,gBAAA9H,aA+BA,SAAA8H,IAAA5H,gBAAA6H,KAAAD,GAIAxH,4BAAAyH,KAAAH,wBANAnH,2BAAAsH,KAAAL,oCAAA,GAGA3G,kBAAA6G,uBAAAG,KAAAC,aAAA5F,KAAA2F,KACA,GAuRA,SAAAC,cA/QA,IAAAC,EAAAF,KACAhH,kBAAA6G,uBAAAG,KAAAG,4BAAA9F,KAAA2F,MAEAI,KAAAC,QAAAC,SACA9B,SACA,SACA,qGACA,SAAAnH,GAAA,OAAA2B,kBAAA6G,uBAAAK,EAAAK,eAAAlG,KAAA6F,EAAA7I,EAAA,GAGA,IAAAmJ,EAAAhC,SAAAiC,cAAA,sBAEAD,IACAA,EAAAE,QAAAC,WAAAnC,SAAAoC,OAAAC,QAAA,gBAAA,GACA7H,kBAAA6G,uBAAAG,KAAAc,oBAAAzG,KAAA2F,MAGAe,EAAA,sBAAAC,GAAA,mBAAA,WACAhI,kBAAA6G,uBAAAK,EAAAe,YAAA5G,KAAA6F,EACA,IAIAa,EAAA,gCAAAC,GAAA,QAAA,SAAA3J,GACAA,EAAA6J,iBACAlI,kBAAA6G,uBAAAK,EAAAe,YAAA5G,KAAA6F,EACA,EACA,CAEA,SAAAC,6BAOA,IAAAgB,gBAAAxF,OAAAyF,SAAAC,QAEAzI,IAAA0I,wBAAAjG,IACArC,kBAAA6G,uBAAAG,KAAAuB,YAAAlH,KAAA2F,KAAA,cAAA,IAAAwB,uBAAAnG,EAEA,CAEA,SAAAkF,cAOAlJ,GAAA,IAAAoK,EAAAzB,KACA3I,EAAA6J,iBACA,IAAAQ,EAAAX,EAAA1J,EAAAsK,QAEA1I,sBAAA0G,mCAAAK,MAAA,GACA,IAAA4B,EAAAF,EAAAG,KAAA,0BAAAH,EAAAG,KAAA,OAAA,UAGAC,EAAA,UAAAF,EAAA,UAAAjG,OAAAyF,SAAAW,SAAAH,EAEAb,EAAAiB,KAAA,CACAC,IAAA,cACAC,OAAA,OACAC,KAAAT,EAAAU,YACAC,QAAA,SAAAF,GAAA,OAAAnJ,kBAAA6G,uBAAA4B,EAAAa,oBAAAjI,KAAAoH,EAAAU,EAAAT,EAAAI,EAAA,GAEA,CAEA,SAAAQ,mBASAH,EAAAT,EAAAE,GACA,GAAAO,SAAAA,EAAAI,QAAA,CAIA,IAAAC,EAAAL,EAAAI,QAAAC,KACAzB,EAAA,oBAAAW,GAAAe,IAAA,IACA1B,EAAA,oBAAAW,GAAAvE,QAAA,UAEA4D,EAAA2B,cAAAC,SAAAC,QACA5J,kBAAA6G,uBAAAG,KAAA6C,qBAAAxI,KAAA2F,KAAAwC,GAGAL,EAAAI,QAAAO,aACA9J,kBAAA6G,uBAAAG,KAAAuB,YAAAlH,KAAA2F,KAAA,cAAA,IAAAwB,uBAAAnG,GACA+E,KAAA2C,IAAAC,WAAA,kBAAA,YAAApB,IAEA,UAAAA,GAAAA,EAAAqB,WAAA,cACAvB,EAAAwB,OACAxB,EAAAyB,QAAA,eAAAC,KAAA,kCAAAC,WAAA,UAAAC,QAhBA,CAmBA,CAEA,SAAAT,oBAOAL,GACAzB,EAAA2B,cAAAC,SAAAY,QAAAC,YAAAhB,GAEA,IAAAiB,EAAAjF,SAAAiC,cAAA,oBACAgD,IACAA,EAAAC,QAAA3C,EAAA2B,cAAAiB,MAEA,CAEA,SAAAC,2BAMA,IAAAC,EACA,OAAAC,eAAA/I,QAAA,oBAIAyD,SAAAuF,KAAAC,aAAA,qBAIA,QAAAH,EAAArF,SAAAG,qBAAA,IAAAkF,IAAAA,EAAAV,QAAA,YAIA3E,SAAAiC,cAAAwD,uBAAA5I,EAAA6I,KAAA,OACA,CAEA,SAAAC,qBAoBA,OAbAlI,kBAAA,CACAO,UAAA,kBACAL,WAAAiI,kBAAA/I,EACAe,SAAA,EACAC,gBAAA,IACAC,WAAA,EACAC,YAAA,EACAE,OAAA,EACAC,mBAAA,EACAZ,kBAAA,CAAAC,OAAA,IAAAC,QAAA,KACAN,iBAAA,MAVA2D,OAcA,CAEA,SAAAyB,qBAMA,IAAAuD,EAAArE,KACA8D,eAAA1I,QAAA,eAAA,KAGA,IAAAiE,EAAArG,kBAAA6G,uBAAAG,KAAAmE,oBAAA9J,KAAA2F,MAEArE,OAAAsC,iBAAA,kBAAA,SAAA5G,GACA2B,kBAAA6G,uBAAAwE,EAAAT,0BAAAvJ,KAAAgK,IAEAhF,IACAA,EAAArG,kBAAA6G,uBAAAwE,EAAAF,oBAAA9J,KAAAgK,KAGArL,kBAAA6G,uBAAAwE,EAAApD,YAAA5G,KAAAgK,GACAhF,IAEA,EACA,CAEA,SAAA4B,aAOA,IAAAqD,EAAAtE,KAAAuD,EAAArK,UAAA1B,OAAA,QAAAoD,IAAA1B,UAAA,GAAAA,UAAA,GAAA6H,EAAA,sBACAwD,EAAA,IAAAC,IACAzD,EAAA2B,cAAA+B,KAAA,CACAC,MAAA,CACAC,IAAApB,EACAxF,KAAA,UAEA6G,YAAA,8EAAAL,EAAAM,OAAA,SAAA,YACAC,MAAA,oBACAC,UAAA,CACAN,KAAA,WACAzL,kBAAA6G,uBAAAyE,EAAAU,cAAA3K,KAAAiK,GAEA9F,SAAAyG,gBAAAvE,QAAAwE,qBAAA,CACA,EACAvB,MAAA,WAAA,OAAA3K,kBAAA6G,uBAAAyE,EAAAa,eAAA9K,KAAAiK,EAAA,EACAc,WAAA,WACAzH,WAAA,kBACAa,SAAAyG,gBAAAvE,QAAAwE,mBACA,EAAA,IACA,GAEAG,UAAA,kBACAC,iBAAA,IAGAlF,KAAA2C,IAAAwC,gBAAAnF,KAAAoF,+BAAA,EACA,CAEA,SAAAR,eAOA5E,KAAAqF,eACArF,KAAAqF,cAAAC,uBAAA,aAGA,CAEA,SAAAP,gBAOAtM,sBAAA8G,mCAAAK,QACAhH,kBAAA6G,uBAAAG,KAAAuB,YAAAlH,KAAA2F,KAAA,cAAA,IAAA2F,qBAAAtK,GACA+E,KAAA2C,IAAAC,WAAA,kBAAA,SAAA,UAGA/J,sBAAA0G,mCAAAK,MAAA,GAEAI,KAAAqF,eACArF,KAAAqF,cAAAG,yBAEA,CAEA,SAAArE,WASAsE,EAAA9L,EAAA+L,GACA,IAAAC,EAAA,IAAAC,KACAD,EAAAE,QAAAF,EAAAG,UAAA,GAAAJ,EAAA,GAAA,GAAA,KACAtH,SAAAoC,OAAA,GAAAlD,OAAAmI,EAAA,KAAAnI,OAAA3D,EAAA,aAAA2D,OAAAqI,EAAAI,cAAA,UACA,CAnTA,IAAAlC,uBAAA,CAAA5I,EAGA,CACA,uBACA,mBACA,wBACA,0BACA,gCACA,kBACA,6BACA,cAGA+I,kBAAA,CAAA/I,EACA,MAEAmG,uBAAA,CAAAnG,EACA,KAEAiG,wBAAA,CAAAjG,EACA,yBAEAsK,qBAAA,CAAAtK,EACA,IAAA+K,kCAAA,IAAAtG,QAmSAuG,2BAAApO,aACA,SAAAoO,IAAAlO,gBAAA6H,KAAAqG,GAEA9N,4BAAAyH,KAAAoG,mCAFApN,kBAAAoN,kCAAApG,KAAAsG,OAAAjM,KAAA2F,KAAA,GA2EA,SAAAsG,QAnEA,IAAAC,EAAAvG,KACAI,KAAAC,QAAAC,SAAA9B,SAAA,SAAA,wEAAA,SAAAnH,GAAA,OAAA2B,kBAAAoN,kCAAAG,EAAAC,WAAAnM,KAAAkM,EAAAlP,EAAA,EACA,CAEA,SAAAmP,UAOAnP,GAAA,IAAAoP,EAAAzG,KACA3I,EAAA6J,iBACA,IAAAwF,EAAA3F,EAAA1J,EAAAsK,QAEAZ,EAAAiB,KAAA,CACAC,IAAA,cACAC,OAAA,OACAC,KAAAuE,EAAAtE,YACAC,QAAA,SAAAF,GAAA,OAAAnJ,kBAAAoN,kCAAAK,EAAAE,YAAAtM,KAAAoM,EAAAtE,EAAAuE,EALA,YAKA,GAEA,CAEA,SAAAC,WASAxE,EAAAuE,EAAA9E,GAMA,IAAAgF,EALAzE,SAAAA,EAAAI,UAIAxB,EAAA,oBAAA2F,GAAAjE,IAAA,IAAAtF,QAAA,UACAgF,EAAAI,QAAAO,aACA,QAAA8D,EAAAjL,OAAAyE,YAAA,IAAAwG,GAAA,QAAAA,EAAAA,EAAA7D,WAAA,IAAA6D,GAAAA,EAAA5D,YACA5C,KAAA2C,IAAAC,WAAA,kBAAA,YAAApB,GAEA5I,kBAAAoN,kCAAApG,KAAA6G,iBAAAxM,KAAA2F,KAAA0G,EAAAvE,EAAAI,QAAAtF,UAEA,CAEA,SAAA4J,gBAQAH,EAAAzJ,GACA,IAAA6J,EAAAJ,EAAAvD,QAAA,0BACA,GAAA2D,EAAAtP,OAAA,CAIAsP,EAAA1D,KAAA,yDAAA2D,SACAL,EAAAK,SACA,IAAAC,EAAA/J,GAAA,iDACA6J,EAAAG,OAAA,6HAAAD,EAAA,aALA,CAMA,CAIA,IAAAjH,gBACA,IAAAsG","file":"../../javascript/newsletter-exit-intent.js","sourcesContent":["// Vanilla JS Exit Intent Detection Library\n\n// Helper: page-view counter using localStorage so we can optionally delay\n// exit-intent detection until the visitor has landed on the site a certain\n// number of times.\nconst PAGE_VIEW_STORAGE_KEY = 'exit-intent-page-views';\n\nfunction getPageViews(key = PAGE_VIEW_STORAGE_KEY) {\n  try {\n    const raw = localStorage.getItem(key);\n    const n = parseInt(raw, 10);\n    return isNaN(n) ? 0 : n;\n  } catch (e) {\n    // localStorage may be disabled or unavailable (SSR, privacy mode, etc.)\n    return 0;\n  }\n}\n\nfunction setPageViews(count, key = PAGE_VIEW_STORAGE_KEY) {\n  try {\n    localStorage.setItem(key, String(count));\n  } catch (_) {\n    /* no-op */\n  }\n}\n\n/**\n * Increment the persisted page-view counter.\n * @param {number} amount – how much to increment by (default 1)\n * @param {string} key – override storage key if you need to isolate counters.\n * @returns {number} The new total after incrementing.\n */\nfunction incrementPageViews(amount = 1, key = PAGE_VIEW_STORAGE_KEY) {\n  const updated = getPageViews(key) + amount;\n  setPageViews(updated, key);\n  return updated;\n}\n\nincrementPageViews();\n\n/**\n * Detects if the current device is mobile based on screen width\n * @param {number} mobileBreakpoint - Screen width threshold for mobile detection\n * @returns {boolean} True if device is considered mobile\n */\nfunction isMobileDevice(mobileBreakpoint = 768) {\n  return window.innerWidth <= mobileBreakpoint;\n}\n\n/**\n * Gets the appropriate scroll threshold based on device type\n * @param {number|object} scrollUpThreshold - Either a number or object with mobile/desktop properties\n * @param {number} mobileBreakpoint - Screen width threshold for mobile detection\n * @returns {number} The scroll threshold to use\n */\nfunction getScrollThreshold(scrollUpThreshold, mobileBreakpoint = 768) {\n  // If it's just a number, use it for all devices (backward compatibility)\n  if (typeof scrollUpThreshold === 'number') {\n    return scrollUpThreshold;\n  }\n  \n  // If it's an object, choose based on device type\n  if (typeof scrollUpThreshold === 'object' && scrollUpThreshold !== null) {\n    const isMobile = isMobileDevice(mobileBreakpoint);\n    return isMobile ? (scrollUpThreshold.mobile || 0) : (scrollUpThreshold.desktop || 0);\n  }\n  \n  return 0;\n}\n\nfunction observeExitIntent(options = {}) {\n  // Merge user options with defaults\n  const config = {\n    timeOnPage: 15000, // ms, 0 disables\n    idleTime: 8000, // ms, 0 disables\n    mouseLeaveDelay: 1000, // ms, 0 disables\n    tabChange: true, // true/false\n    windowBlur: true, // true/false\n    eventName: 'exit-intent', // event name for the custom event\n    debug: false, // true/false\n    pageViewsToTrigger: 5, // Fire immediately when this many page views is reached\n    // Responsive scroll threshold - can be number (legacy) or object with mobile/desktop values\n    scrollUpThreshold: {\n      mobile: 200,   // pixels, minimum upward scroll distance to trigger on mobile\n      desktop: 400   // pixels, minimum upward scroll distance to trigger on desktop\n    },\n    mobileBreakpoint: 768, // pixels, screen width threshold for mobile detection\n    scrollUpInterval: 100, // ms, interval to check scroll position\n    ...options\n  };\n\n  let timers = []; // Store all timeouts for cleanup\n  let listeners = []; // Store all event listeners for cleanup\n  let idleTimeout = null; // For manual idle detection\n  let mouseLeaveTimer = null; // For mouse leave delay\n  let scrollCheckInterval = null; // For scroll detection\n\n  function log(message) {\n    if (config.debug) {\n      console.log(message);\n    }\n  }\n\n  // Helper to clean up all listeners and timers\n  function destroy() {\n    log(\"destroy\");\n    timers.forEach(clearTimeout); // Clear all timeouts\n    timers = [];\n    listeners.forEach(({el, type, fn}) => el.removeEventListener(type, fn)); // Remove all event listeners\n    listeners = [];\n    if (idleTimeout) clearTimeout(idleTimeout);\n    if (mouseLeaveTimer) clearTimeout(mouseLeaveTimer);\n    if (scrollCheckInterval) clearInterval(scrollCheckInterval);\n  }\n\n  // Call this to trigger exit intent and cleanup\n  function trigger(reason) {\n    // Dispatch a custom event on window (do NOT destroy – we now allow multiple fires)\n    log(\"triggered with reason: \" + reason);\n    const event = new CustomEvent(config.eventName, { detail: reason });\n    window.dispatchEvent(event);\n  }\n\n  // If the visitor has now reached the required number of page views, fire\n  // the event immediately and skip the other detectors.\n  const currentViews = getPageViews();\n  if (config.pageViewsToTrigger && currentViews >= config.pageViewsToTrigger) {\n    if (config.debug) {\n      console.log(`exit-intent: pageViewsToTrigger reached (${currentViews}). Firing immediately.`);\n    }\n    trigger('pageViews');\n\n    // Continue setting up the other detectors – removing the early return allows\n    // multiple reasons to be caught even after the immediate page-view trigger.\n  }\n\n  // 1. Time on page: trigger after a set time\n  if (config.timeOnPage > 0) {\n    timers.push(setTimeout(() => trigger('timeOnPage'), config.timeOnPage));\n  }\n\n  // 2. Idle Time: use IdleDetector if available, otherwise fallback to manual\n  if (config.idleTime > 0) {\n    // Manual idle detection fallback\n    let idleTimer;\n    function resetIdle() {\n      if (idleTimer) clearTimeout(idleTimer);\n      idleTimer = setTimeout(() => trigger('idleTime'), config.idleTime);\n    }\n    // Reset idle timer on user activity\n    ['mousemove', 'keydown', 'mousedown', 'touchstart'].forEach(type => {\n      const fn = resetIdle;\n      window.addEventListener(type, fn);\n      listeners.push({el: window, type, fn});\n    });\n    resetIdle();\n  }\n\n  // 3. Mouse leaves window: trigger after delay if mouse leaves and doesn't return\n  if (config.mouseLeaveDelay > 0) {\n    function onMouseOut(e) {\n      // Only trigger if mouse leaves window (not just an element)\n      if (!e.relatedTarget && !e.toElement) {\n        mouseLeaveTimer = setTimeout(() => trigger('mouseLeave'), config.mouseLeaveDelay);\n      }\n    }\n    function onMouseOver() {\n      // Cancel timer if mouse re-enters window\n      if (mouseLeaveTimer) clearTimeout(mouseLeaveTimer);\n    }\n    window.addEventListener('mouseout', onMouseOut);\n    window.addEventListener('mouseover', onMouseOver);\n    listeners.push({el: window, type: 'mouseout', fn: onMouseOut});\n    listeners.push({el: window, type: 'mouseover', fn: onMouseOver});\n  }\n\n  // 4. Tab changes: trigger when document becomes hidden\n  if (config.tabChange) {\n    function onVisibility() {\n      if (document.visibilityState === 'hidden') {\n        trigger('tabChange');\n      }\n    }\n    document.addEventListener('visibilitychange', onVisibility);\n    listeners.push({el: document, type: 'visibilitychange', fn: onVisibility});\n  }\n\n  // 5. Window blur: trigger when window loses focus\n  if (config.windowBlur) {\n    function onBlur() {\n      // Check if focus moved to a child iframe - if so, don't trigger exit intent\n      // Use setTimeout to allow the browser to update document.activeElement\n      setTimeout(() => {\n        const activeElement = document.activeElement;\n        \n        // If the active element is an iframe and it's a child of this document,\n        // then the user is still on the page and we shouldn't trigger exit intent\n        if (activeElement && activeElement.tagName === 'IFRAME') {\n          // Check if this iframe is a child of the current document\n          if (document.contains(activeElement)) {\n            log('Window blur ignored - focus moved to child iframe');\n            return;\n          }\n        }\n        \n        trigger('windowBlur');\n      }, 0);\n    }\n    window.addEventListener('blur', onBlur);\n    listeners.push({el: window, type: 'blur', fn: onBlur});\n  }\n\n  // 6. Scroll up detection: trigger when user scrolls up quickly\n  // Get the appropriate threshold based on device type\n  const currentScrollThreshold = getScrollThreshold(config.scrollUpThreshold, config.mobileBreakpoint);\n  \n  if (currentScrollThreshold > 0) {\n    let lastScrollY = window.scrollY;\n    const deviceType = isMobileDevice(config.mobileBreakpoint) ? 'mobile' : 'desktop';\n    \n    log(`Scroll detection initialized for ${deviceType} device (threshold: ${currentScrollThreshold}px)`);\n    \n    scrollCheckInterval = setInterval(() => {\n      const currentScrollY = window.scrollY;\n      const scrollDistance = lastScrollY - currentScrollY;\n      \n      // If scrolled up enough pixels since last check, trigger exit intent\n      if (scrollDistance >= currentScrollThreshold) {\n        log(`Fast upward scroll detected: ${scrollDistance}px in ${config.scrollUpInterval}ms (${deviceType} threshold: ${currentScrollThreshold}px)`);\n        trigger('scrollUp');\n      }\n      \n      lastScrollY = currentScrollY;\n    }, config.scrollUpInterval);\n  }\n\n  // Return destroy for manual cleanup if needed\n  return { destroy };\n}\n\n// Attach helper so consumers can manually bump the counter in SPAs.\nobserveExitIntent.incrementPageViews = incrementPageViews;\n\n// Export for module usage (CommonJS)\nif (typeof module !== 'undefined' && module.exports) {\n  module.exports = observeExitIntent;\n} \n\n/**\n * Newsletter popup\n *  - Handles newsletter open popup and form submission, replaces content on success\n */\nclass NewsletterPopup {\n\n    /**\n     * Selectors that indicate the popup should be suppressed.\n     */\n    static #SUPPRESSION_SELECTORS = [\n        '#onetrust-banner-sdk',\n        '.overlay--active',\n        '.quick-basket--active',\n        '.sticky-popup--active-a',\n        '.product-sticky-cta--active-a',\n        '.search--active',\n        '.filters__selected--active',\n        '.mfp-wrap',\n    ];\n\n    /** Initial delay before first suppression check (ms) */\n    static #AUTO_POPUP_DELAY = 15000;\n\n    /** Cookie duration when user subscribes (days) */\n    static #COOKIE_DAYS_SUBSCRIBE = 365;\n\n    /** Query parameter applied only to links sent to known newsletter subscribers */\n    static #SUBSCRIBER_QUERY_PARAM = 'newsletter_subscribed';\n\n    /** Cookie duration when user dismisses popup (days) */\n    static #COOKIE_DAYS_DISMISS = 28;\n\n    /** @internal */\n    #suppressNewsletterPopupCloseEvent = false;\n\n    constructor() {\n        this.#bindEvents();\n    }\n\n    /**\n     * Bind page events\n     *\n     * @private\n     * @returns {void}\n     */\n    #bindEvents() {\n        this.#suppressForSubscriberLink();\n\n        Soho.plugins.delegate(\n            document,\n            'submit',\n            '.js-submit-newsletter, .checkout-thanks-panel__newsletter:not([data-newsletter-scope=\"thank-you\"])',\n            (e) => this.#handleSubmit(e)\n        );\n\n        const newsletter = document.querySelector('.popup--newsletter');\n\n        if (newsletter) {\n            if (newsletter.dataset.autoPopup && document.cookie.indexOf('soho_npopup=') < 0) {\n                this.#scheduleAutoPopup();\n            }\n\n            $('.popup--newsletter').on('newsletter.popup', () => {\n                this.#openPopup();\n            });\n        }\n\n        // Handle manual popup trigger\n        $('.js-newsletter-popup-trigger').on('click', (e) => {\n            e.preventDefault();\n            this.#openPopup();\n        });\n    }\n\n    /**\n     * Suppress automatic popups when a trusted subscriber link identifies the visitor.\n     *\n     * @private\n     * @returns {void}\n     */\n    #suppressForSubscriberLink() {\n        const query = new URLSearchParams(window.location.search);\n\n        if (query.has(NewsletterPopup.#SUBSCRIBER_QUERY_PARAM)) {\n            this.#setCookie('soho_npopup', '1', NewsletterPopup.#COOKIE_DAYS_SUBSCRIBE);\n        }\n    }\n\n    /**\n     * Handle newsletter form submission\n     *\n     * @private\n     * @param {*} e\n     * @returns {void}\n     */\n    #handleSubmit(e) {\n        e.preventDefault();\n        const form = $(e.target);\n\n        this.#suppressNewsletterPopupCloseEvent = true;\n        const scope = form.attr('data-newsletter-scope') || form.attr('id') || 'unknown';\n\n        // Add more specificity to the scope\n        const resolvedScope = (scope === 'block') ? 'block--' + window.location.pathname : scope;\n\n        $.ajax({\n            url: '/newsletter',\n            method: 'post',\n            data: form.serialize(),\n            success: (data) => this.#handleAjaxSuccess(data, form, resolvedScope)\n        });\n    }\n\n    /**\n     * Handle ajax success\n     *\n     * @private\n     * @param {*} data\n     * @param {*} form\n     * @param {*} scope\n     * @returns {void}\n     */\n    #handleAjaxSuccess(data, form, scope) {\n        if (!data?.payload) {\n            return;\n        }\n\n        const html = data.payload.html;\n        $('input[type=email]', form).val(\"\");\n        $('input[type=email]', form).trigger('change');\n\n        if ($.magnificPopup.instance.isOpen) {\n            this.#updatePopupContent(html);\n        }\n\n        if (data.payload.successful) {\n            this.#setCookie('soho_npopup', '1', NewsletterPopup.#COOKIE_DAYS_SUBSCRIBE);\n            Soho.GTM.trackEvent('Newsletter form', 'Subscribe', scope);\n\n            if (scope === 'block' || scope.startsWith('block--')) {\n                form.hide();\n                form.closest('.l-one-half').find('.js-newsletter-success-message').removeAttr('hidden').show();\n            }\n        }\n    }\n\n    /**\n     * Update the popup content\n     *\n     * @private\n     * @param {*} html\n     * @returns {void}\n     */\n    #updatePopupContent(html) {\n        $.magnificPopup.instance.content.replaceWith(html);\n\n        const popupClose = document.querySelector('.js-popup--close');\n        if (popupClose) {\n            popupClose.onclick = $.magnificPopup.close;\n        }\n    }\n\n    /**\n     * Whether the auto-popup should be suppressed right now\n     *\n     * @private\n     * @returns {boolean}\n     */\n    #shouldSuppressAutoPopup() {\n        if (!sessionStorage.getItem('soho_visited')) {\n            return true;\n        }\n\n        if (document.body.hasAttribute('header-active')) {\n            return true;\n        }\n\n        if (document.activeElement?.closest('form')) {\n            return true;\n        }\n\n        return !!document.querySelector(NewsletterPopup.#SUPPRESSION_SELECTORS.join(','));\n    }\n\n    /**\n     * Initialise the observeExitIntent method\n     *\n     * @private\n     * @returns {function}\n     */\n    #observeExitIntent() {\n        const { destroy } = observeExitIntent({\n            eventName: 'soho-exit-event',\n            timeOnPage: NewsletterPopup.#AUTO_POPUP_DELAY,\n            idleTime: 0,\n            mouseLeaveDelay: 100,\n            tabChange: true,\n            windowBlur: true,\n            debug: false,\n            pageViewsToTrigger: 0,\n            scrollUpThreshold: {mobile: 100, desktop: 200},\n            mobileBreakpoint: 999\n        });\n\n        return destroy;\n    }\n\n    /**\n     * Schedule the auto-popup with retry pattern\n     *\n     * @private\n     * @returns {void}\n     */\n    #scheduleAutoPopup() {\n        sessionStorage.setItem('soho_visited', '1');\n\n        // Initialise the observeExitIntent method\n        let destroy = this.#observeExitIntent();\n\n        window.addEventListener('soho-exit-event', e => {\n            if (this.#shouldSuppressAutoPopup()) {\n                // If we need to suppress the popup, destroy the current observeExitIntent instance and initialise a new one\n                destroy();\n                destroy = this.#observeExitIntent();\n            } else {\n                // Otherwise destroy the observeExitIntent instance and open the popup\n                this.#openPopup();\n                destroy();\n            }\n        });\n    }\n\n    /**\n     * Open newsletter popup\n     *\n     * @private\n     * @param {*} content\n     * @returns {void}\n     */\n    #openPopup(content = $('.popup--newsletter')) {\n        const svg = new Svg();\n        $.magnificPopup.open({\n            items: {\n                src: content,\n                type: 'inline'\n            },\n            closeMarkup: '<button title=\"%title%\" type=\"button\" class=\"mfp-close\" aria-label=\"Close\">' + svg.render('close') + '</button>',\n            focus: '#newsletter_email',\n            callbacks: {\n                open: () => {\n                    this.#onPopupOpen()\n\n                    document.documentElement.dataset.megaMenuIgnoreClick = true;\n                },\n                close: () => this.#onPopupClose(),\n                afterClose: () => {\n                    setTimeout(() => {\n                        delete document.documentElement.dataset.megaMenuIgnoreClick;\n                    }, 100);\n                }\n            },\n            mainClass: \"mfp--newsletter\",\n            fixedContentPos: true\n        });\n\n        Soho.GTM.trackExperiment(Soho.newsletterOptimizeExperimentId, 0);\n    }\n\n    /**\n     * Handle popup open event\n     *\n     * @private\n     * @returns {void}\n     */\n    #onPopupOpen() {\n        if (Soho.ContentSquare) {\n            Soho.ContentSquare.trackPopupOpenPageview('newsletter');\n        }\n\n    }\n\n    /**\n     * Handle popup close event\n     *\n     * @private\n     * @returns {void}\n     */\n    #onPopupClose() {\n        if (!this.#suppressNewsletterPopupCloseEvent) {\n            this.#setCookie('soho_npopup', '1', NewsletterPopup.#COOKIE_DAYS_DISMISS);\n            Soho.GTM.trackEvent('Newsletter form', 'Closed', 'popup');\n        }\n\n        this.#suppressNewsletterPopupCloseEvent = false;\n\n        if (Soho.ContentSquare) {\n            Soho.ContentSquare.trackPopupClosePageview();\n        }\n    }\n\n    /**\n     * Set a cookie\n     *\n     * @private\n     * @param {*} name\n     * @param {*} value\n     * @param {*} days\n     * @returns {void}\n     */\n    #setCookie(name, value, days) {\n        const expires = new Date();\n        expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));\n        document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;\n    }\n}\n\n/**\n * Checkout thank-you newsletter handler\n *  - Handles only the inline thank-you panel form (data-newsletter-scope=\"thank-you\")\n *  - Leaves generic popup logic untouched\n */\nclass CheckoutThankYouNewsletter {\n    constructor() { this.#bind(); }\n\n    /**\n     * Bind submit handler for the thank-you newsletter form\n     *\n     * @private\n     * @returns {void}\n     */\n    #bind() {\n        Soho.plugins.delegate(document, 'submit', '.checkout-thanks-panel__newsletter[data-newsletter-scope=\"thank-you\"]', (e) => this.#onSubmit(e));\n    }\n\n    /**\n     * Handle form submission\n     *\n     * @private\n     * @param {Event} e\n     * @returns {void}\n     */\n    #onSubmit(e) {\n        e.preventDefault();\n        const $form = $(e.target);\n        const scope = 'thank-you';\n        $.ajax({\n            url: '/newsletter',\n            method: 'post',\n            data: $form.serialize(),\n            success: (data) => this.#onSuccess(data, $form, scope)\n        });\n    }\n\n    /**\n     * Handle successful subscription response\n     *\n     * @private\n     * @param {object} data\n     * @param {jQuery} $form\n     * @param {string} scope\n     * @returns {void}\n     */\n    #onSuccess(data, $form, scope) {\n        if (!data?.payload) {\n            return;\n        }\n\n        $('input[type=email]', $form).val(\"\").trigger('change');\n        if (data.payload.successful) {\n            if (window.Soho?.GTM?.trackEvent) {\n                Soho.GTM.trackEvent('Newsletter form', 'Subscribe', scope);\n            }\n            this.#transformPanel($form, data.payload.message);\n        }\n    }\n\n    /**\n     * Replace form with success message\n     *\n     * @private\n     * @param {jQuery} $form\n     * @param {string} message\n     * @returns {void}\n     */\n    #transformPanel($form, message) {\n        const $panel = $form.closest('.checkout-thanks-panel');\n        if (!$panel.length) {\n            return;\n        }\n\n        $panel.find('.checkout-thanks-panel__body.richtext.richtext--flush').remove();\n        $form.remove();\n        const msg = message || \"Thank you. You've been signed up successfully.\";\n        $panel.append('<div class=\"checkout-thanks-panel__body richtext richtext--flush\"><p class=\"checkout-thanks-panel__message\" role=\"status\">' + msg + '</p></div>');\n    }\n}\n\n// Instantiate both handlers side-by-side\nnew NewsletterPopup();\nnew CheckoutThankYouNewsletter();\n","// Vanilla JS Exit Intent Detection Library\n\n// Helper: page-view counter using localStorage so we can optionally delay\n// exit-intent detection until the visitor has landed on the site a certain\n// number of times.\nconst PAGE_VIEW_STORAGE_KEY = 'exit-intent-page-views';\n\nfunction getPageViews(key = PAGE_VIEW_STORAGE_KEY) {\n  try {\n    const raw = localStorage.getItem(key);\n    const n = parseInt(raw, 10);\n    return isNaN(n) ? 0 : n;\n  } catch (e) {\n    // localStorage may be disabled or unavailable (SSR, privacy mode, etc.)\n    return 0;\n  }\n}\n\nfunction setPageViews(count, key = PAGE_VIEW_STORAGE_KEY) {\n  try {\n    localStorage.setItem(key, String(count));\n  } catch (_) {\n    /* no-op */\n  }\n}\n\n/**\n * Increment the persisted page-view counter.\n * @param {number} amount – how much to increment by (default 1)\n * @param {string} key – override storage key if you need to isolate counters.\n * @returns {number} The new total after incrementing.\n */\nfunction incrementPageViews(amount = 1, key = PAGE_VIEW_STORAGE_KEY) {\n  const updated = getPageViews(key) + amount;\n  setPageViews(updated, key);\n  return updated;\n}\n\nincrementPageViews();\n\n/**\n * Detects if the current device is mobile based on screen width\n * @param {number} mobileBreakpoint - Screen width threshold for mobile detection\n * @returns {boolean} True if device is considered mobile\n */\nfunction isMobileDevice(mobileBreakpoint = 768) {\n  return window.innerWidth <= mobileBreakpoint;\n}\n\n/**\n * Gets the appropriate scroll threshold based on device type\n * @param {number|object} scrollUpThreshold - Either a number or object with mobile/desktop properties\n * @param {number} mobileBreakpoint - Screen width threshold for mobile detection\n * @returns {number} The scroll threshold to use\n */\nfunction getScrollThreshold(scrollUpThreshold, mobileBreakpoint = 768) {\n  // If it's just a number, use it for all devices (backward compatibility)\n  if (typeof scrollUpThreshold === 'number') {\n    return scrollUpThreshold;\n  }\n  \n  // If it's an object, choose based on device type\n  if (typeof scrollUpThreshold === 'object' && scrollUpThreshold !== null) {\n    const isMobile = isMobileDevice(mobileBreakpoint);\n    return isMobile ? (scrollUpThreshold.mobile || 0) : (scrollUpThreshold.desktop || 0);\n  }\n  \n  return 0;\n}\n\nfunction observeExitIntent(options = {}) {\n  // Merge user options with defaults\n  const config = {\n    timeOnPage: 15000, // ms, 0 disables\n    idleTime: 8000, // ms, 0 disables\n    mouseLeaveDelay: 1000, // ms, 0 disables\n    tabChange: true, // true/false\n    windowBlur: true, // true/false\n    eventName: 'exit-intent', // event name for the custom event\n    debug: false, // true/false\n    pageViewsToTrigger: 5, // Fire immediately when this many page views is reached\n    // Responsive scroll threshold - can be number (legacy) or object with mobile/desktop values\n    scrollUpThreshold: {\n      mobile: 200,   // pixels, minimum upward scroll distance to trigger on mobile\n      desktop: 400   // pixels, minimum upward scroll distance to trigger on desktop\n    },\n    mobileBreakpoint: 768, // pixels, screen width threshold for mobile detection\n    scrollUpInterval: 100, // ms, interval to check scroll position\n    ...options\n  };\n\n  let timers = []; // Store all timeouts for cleanup\n  let listeners = []; // Store all event listeners for cleanup\n  let idleTimeout = null; // For manual idle detection\n  let mouseLeaveTimer = null; // For mouse leave delay\n  let scrollCheckInterval = null; // For scroll detection\n\n  function log(message) {\n    if (config.debug) {\n      console.log(message);\n    }\n  }\n\n  // Helper to clean up all listeners and timers\n  function destroy() {\n    log(\"destroy\");\n    timers.forEach(clearTimeout); // Clear all timeouts\n    timers = [];\n    listeners.forEach(({el, type, fn}) => el.removeEventListener(type, fn)); // Remove all event listeners\n    listeners = [];\n    if (idleTimeout) clearTimeout(idleTimeout);\n    if (mouseLeaveTimer) clearTimeout(mouseLeaveTimer);\n    if (scrollCheckInterval) clearInterval(scrollCheckInterval);\n  }\n\n  // Call this to trigger exit intent and cleanup\n  function trigger(reason) {\n    // Dispatch a custom event on window (do NOT destroy – we now allow multiple fires)\n    log(\"triggered with reason: \" + reason);\n    const event = new CustomEvent(config.eventName, { detail: reason });\n    window.dispatchEvent(event);\n  }\n\n  // If the visitor has now reached the required number of page views, fire\n  // the event immediately and skip the other detectors.\n  const currentViews = getPageViews();\n  if (config.pageViewsToTrigger && currentViews >= config.pageViewsToTrigger) {\n    if (config.debug) {\n      console.log(`exit-intent: pageViewsToTrigger reached (${currentViews}). Firing immediately.`);\n    }\n    trigger('pageViews');\n\n    // Continue setting up the other detectors – removing the early return allows\n    // multiple reasons to be caught even after the immediate page-view trigger.\n  }\n\n  // 1. Time on page: trigger after a set time\n  if (config.timeOnPage > 0) {\n    timers.push(setTimeout(() => trigger('timeOnPage'), config.timeOnPage));\n  }\n\n  // 2. Idle Time: use IdleDetector if available, otherwise fallback to manual\n  if (config.idleTime > 0) {\n    // Manual idle detection fallback\n    let idleTimer;\n    function resetIdle() {\n      if (idleTimer) clearTimeout(idleTimer);\n      idleTimer = setTimeout(() => trigger('idleTime'), config.idleTime);\n    }\n    // Reset idle timer on user activity\n    ['mousemove', 'keydown', 'mousedown', 'touchstart'].forEach(type => {\n      const fn = resetIdle;\n      window.addEventListener(type, fn);\n      listeners.push({el: window, type, fn});\n    });\n    resetIdle();\n  }\n\n  // 3. Mouse leaves window: trigger after delay if mouse leaves and doesn't return\n  if (config.mouseLeaveDelay > 0) {\n    function onMouseOut(e) {\n      // Only trigger if mouse leaves window (not just an element)\n      if (!e.relatedTarget && !e.toElement) {\n        mouseLeaveTimer = setTimeout(() => trigger('mouseLeave'), config.mouseLeaveDelay);\n      }\n    }\n    function onMouseOver() {\n      // Cancel timer if mouse re-enters window\n      if (mouseLeaveTimer) clearTimeout(mouseLeaveTimer);\n    }\n    window.addEventListener('mouseout', onMouseOut);\n    window.addEventListener('mouseover', onMouseOver);\n    listeners.push({el: window, type: 'mouseout', fn: onMouseOut});\n    listeners.push({el: window, type: 'mouseover', fn: onMouseOver});\n  }\n\n  // 4. Tab changes: trigger when document becomes hidden\n  if (config.tabChange) {\n    function onVisibility() {\n      if (document.visibilityState === 'hidden') {\n        trigger('tabChange');\n      }\n    }\n    document.addEventListener('visibilitychange', onVisibility);\n    listeners.push({el: document, type: 'visibilitychange', fn: onVisibility});\n  }\n\n  // 5. Window blur: trigger when window loses focus\n  if (config.windowBlur) {\n    function onBlur() {\n      // Check if focus moved to a child iframe - if so, don't trigger exit intent\n      // Use setTimeout to allow the browser to update document.activeElement\n      setTimeout(() => {\n        const activeElement = document.activeElement;\n        \n        // If the active element is an iframe and it's a child of this document,\n        // then the user is still on the page and we shouldn't trigger exit intent\n        if (activeElement && activeElement.tagName === 'IFRAME') {\n          // Check if this iframe is a child of the current document\n          if (document.contains(activeElement)) {\n            log('Window blur ignored - focus moved to child iframe');\n            return;\n          }\n        }\n        \n        trigger('windowBlur');\n      }, 0);\n    }\n    window.addEventListener('blur', onBlur);\n    listeners.push({el: window, type: 'blur', fn: onBlur});\n  }\n\n  // 6. Scroll up detection: trigger when user scrolls up quickly\n  // Get the appropriate threshold based on device type\n  const currentScrollThreshold = getScrollThreshold(config.scrollUpThreshold, config.mobileBreakpoint);\n  \n  if (currentScrollThreshold > 0) {\n    let lastScrollY = window.scrollY;\n    const deviceType = isMobileDevice(config.mobileBreakpoint) ? 'mobile' : 'desktop';\n    \n    log(`Scroll detection initialized for ${deviceType} device (threshold: ${currentScrollThreshold}px)`);\n    \n    scrollCheckInterval = setInterval(() => {\n      const currentScrollY = window.scrollY;\n      const scrollDistance = lastScrollY - currentScrollY;\n      \n      // If scrolled up enough pixels since last check, trigger exit intent\n      if (scrollDistance >= currentScrollThreshold) {\n        log(`Fast upward scroll detected: ${scrollDistance}px in ${config.scrollUpInterval}ms (${deviceType} threshold: ${currentScrollThreshold}px)`);\n        trigger('scrollUp');\n      }\n      \n      lastScrollY = currentScrollY;\n    }, config.scrollUpInterval);\n  }\n\n  // Return destroy for manual cleanup if needed\n  return { destroy };\n}\n\n// Attach helper so consumers can manually bump the counter in SPAs.\nobserveExitIntent.incrementPageViews = incrementPageViews;\n\n// Export for module usage (CommonJS)\nif (typeof module !== 'undefined' && module.exports) {\n  module.exports = observeExitIntent;\n} "],"sourceRoot":"../../../../resources/javascript"}