{"version":3,"sources":["webpack://specialist-tracking/./node_modules/@financial-times/o-viewport/src/utils.js","webpack://specialist-tracking/./node_modules/@financial-times/o-utils/main.js","webpack://specialist-tracking/./node_modules/@financial-times/o-viewport/main.js","webpack://specialist-tracking/./node_modules/@financial-times/ads-legacy-o-ads/dist/ads-legacy-o-ads.js","webpack://specialist-tracking/./src/entrypoints/oAds.ts","webpack://specialist-tracking/./src/shared/initLibrary.ts","webpack://specialist-tracking/./src/shared/oAds.ts","webpack://specialist-tracking/./src/shared/scripts/insertCustomOAdsParams.ts","webpack://specialist-tracking/./src/shared/scripts/insertUserCustomOAdsParams.ts","webpack://specialist-tracking/./src/shared/scripts/snowplow.ts","webpack://specialist-tracking/./src/shared/scripts/validateTrafficScript.ts","webpack://specialist-tracking/./src/shared/utils.ts","webpack://specialist-tracking/webpack/bootstrap","webpack://specialist-tracking/webpack/runtime/define property getters","webpack://specialist-tracking/webpack/runtime/hasOwnProperty shorthand","webpack://specialist-tracking/webpack/runtime/make namespace object","webpack://specialist-tracking/webpack/startup"],"names":["debug","getHeight","ignoreScrollbars","document","documentElement","clientHeight","Math","max","window","innerHeight","getWidth","clientWidth","innerWidth","broadcast","eventType","data","target","body","console","log","dispatchEvent","CustomEvent","detail","bubbles","getSize","height","width","getScrollPosition","scrollHeight","scrollWidth","left","pageXOffset","scrollX","top","pageYOffset","scrollY","getVisibility","hidden","getOrientation","orientation","screen","split","type","matchMedia","matches","debounce","func","wait","timeout","args","arguments","later","apply","this","clearTimeout","setTimeout","throttle","utils","listeners","intervals","resize","visibility","scroll","listenTo","handler","ev","viewport","originalEvent","addEventListener","listenToResize","scrollPos","scrollLeft","scrollTop","listenToScroll","listenToOrientation","listenToVisibility","stopListeningTo","Object","keys","forEach","removeEventListener","setThrottleInterval","interval","perfMark","name","performance","LUX","msPerformance","webkitPerformance","mozPerformance","mark","clearMarks","buildPerfmarkSuffix","eventDetailsObj","suffix","pos","size","creativeId","join","on","callback","clearPerfMarks","metricsDefinitions","groupsToClear","getEntriesByType","relevantGroupsMarks","filter","group","includes","spoorAction","map","marks","eventsToClear","concat","eventName","match","messenger","post","message","source","JSON","stringify","postMessage","parse","e","breakpoints$1","current","getNearestBreakpoint","winner","dims","breakpoint","breakpointDims","fire","setCurrent","getCurrent","init$2","brps","cb","isFunction","argsIndex","indexOf","slice","call","isOn","hop","prototype","hasOwnProperty","is","object","toString","undefined","start","groupCollapsed","end","groupEnd","localStorage","getItem","location","search","info","warn","error","table","columns","attributeTable","item","val","isArray","isObject","key","value","obj","isString","isWindow","isPlainObject","nodeType","constructor","dehyphenise","string","replace","hyphen","letter","toUpperCase","metricsSampleThreshold","random","off","once","event","srcElement","opts","cancelable","length","responsive","isStorage","isNonEmptyString","str","Boolean","isElement","element","tagName","extend","options","src","copy","copyIsArray","clone","deep","i","hash","delimiter","pairing","pair","hashObj","idx","l","trim","attach","scriptUrl","async","errorcb","autoRemove","tag","createElement","node","getElementsByTagName","hasRun","processCallback","parentElement","removeChild","setAttribute","onreadystatechange","readyState","onload","onerror","parentNode","insertBefore","getReferrer","referrer","parseAttributeName","attribute","getLocation","href","getQueryString","substring","getQueryParamByName","url","results","RegExp","exec","decodeURIComponent","getTimestamp","now","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","iframeToSlotName","iframeWindow","iframes","slotName","contentWindow","getAttribute","buildObjectFromArray","targetObject","reduce","prev","cookie","pop","getVersion","setupMetrics","definitions","disableSampling","Array","eDef","inSample","sampleSize","triggers","trigger","eMarkMap","listenOnInitialised","eventDetails","events","markNames","getEntriesByName","mName","pMarks","markName","round","startTime","mNameNoSuffix","pMarks2","getMarksForEvents","navigation","navMarks","desiredMarks","navMarksArray","getNavigationPerfMarks","assign","eventPayload","category","action","timings","advert","correlator","oAds","gpt","getCorrelator","creative","isEmpty","sendMetrics","multiple","sendMetricsOnEvent","markPageChange","defaults","formats","PartnerContent","sizes","MediumRectangle","Rectangle","WideSkyscraper","Leaderboard","SuperLeaderboard","HalfPage","Billboard","Portrait","AdhesionBanner","MicroBar","Button2","Responsive","extra","large","medium","small","flags","refresh","inview","displayLabelWithBorders","Config","store","access","k","v","result","clear","init","canonical","canonicalTag","querySelector","fetchCanonicalURL","from","querySelectorAll","script","innerHTML","fetchDeclaritiveConfig","config","config$1","bind","init$1","VALID_SIZE_STRINGS","VALID_COLLAPSE_MODES","attributeParsers","regex","test","push","parseInt","mapping","format","responsiveSizes","screenName","toLowerCase","responsiveFormats","lazyLoadThreshold","Number","targeting","base","collapseEmpty","convertLazyLoadBooleanToObject","lazyLoad","onChangeBreakpoint","slot","screensize","hasValidSize","uncollapse","collapse","Slot","container","initLazyLoading","cfg","slotConfig","outer","addContainer","class","tabindex","inner","setName","server","defer","center","label","outOfPage","companion","outerEl","allowedLabels","adsLabelPos","modifier","classList","add","parseAttributeConfig","lazyLoadObserver","initLazyLoad","centerContainer","labelContainer","initResponsive","getSlotSizes","getSlotTargeting","params","entries","getSlotGPTSize","attributes","threshold","viewportMargin","getAttributes","observe","render","unobserve","maximise","floor","setFormatLoaded","addClass","className","remove","clearSlot","destroy","destroySlot","submitImpression","submitGptImpression","details","attrs","attr","insertAdjacentHTML","lastChild","Slots","invokeMethodOnSlots","names","method","slots","run","findFormatBySize","prop","s","onBreakpointChange","isCurrentlyResponsive","stillWantsResponsive","initSlot","getElementById","id","removeAttribute","initRefresh","refreshCount","time","clearInterval","setInterval","parseFloat","initRendered","breakpoints","initPostMessage","slotClass","flushLazyLoading","lazyLoadingObservers","observer","root","contains","lazyLoadingConfig","lazyLoadingObserver","find","rootMargin","IntersectionObserver","changes","a","intersectionRect","sort","b","change","fn","_slot$gpt","_slot$gpt2","_slot$gpt3","row","unitName","lineItemId","debug$1","values","parameters","Targeting","get","methods","socialReferrer","getSocialReferrer","timestamp","socialFlow","OADS_VERSION","sf","socialflow","codedValue","lookup","google","socref","searchTerm","qs","keywords","q","query","queryText","searchField","unescape","kw","ts","res","SEARCH_PARAMS","filterNestedParams","nestedParams","keysToStrip","childParams","URLSearchParams","delete","DEFAULT_LAZY_LOAD","fetchMarginPercent","renderMarginPercent","mobileScaling","loadGPT","googletag","cmd","err","setup","gptConfig","nonPersonalized","pubads","onRenderEnded","companions","disableInitialLoad","companionAds","setRefreshUnfilledSlots","enableCompanions","rendering","enableSyncRendering","enableSingleRequest","enableAsyncRendering","setRenderingMode","setPageTargeting","mode","collapseEmptyDivs","setPageCollapseEmpty","lazyLoadConf","enableLazyLoad","filters","URL","param","searchParams","set","stripUrlParams","enableServices","setTargeting","setRequestNonPersonalizedAds","targetingData","String","onReady","slotMethods","defineSlot","addServices","setCollapseEmpty","setURL","display","onRender","onRefresh","onResize","iframe","gptSlotId","getSlotId","domId","getDomId","iframeId","getId","slotTargeting","getTargetingMap","serviceName","iFrameEl","setUnitName","defineOutOfPageSlot","defineSizeMapping","gptSlot","pubadsReady","updatePageTargeting","sizeMapping","addSize","build","destroySlots","network","site","zone","addService","setCollapseEmptyDiv","impressionURL","trackingUrlElement","dataset","oAdsImpressionUrl","getImpressionURL","override","updateCorrelator","clearPageTargeting","clearTargeting","clearPageTargetingForKey","hasGPTLoaded","apiReady","conf","Ads","initAll","configOptions","disableConsentCookie","consents","behavioral","programmatic","consentCookie","getConsents","Promise","resolve","initLibrary","updateTargeting","cc","isInitialised","setItem","removeItem","version","ads","then","__importDefault","mod","__esModule","defineProperty","exports","initLibrary_1","require","oAds_1","validateTrafficScript_1","insertCustomOAdsParams_1","getUserCustomOAdsParams","onDocumentLoaded","dataLayer","validateTrafficIasScript","onDocumentReady","ads_legacy_o_ads_1","default","updateAdsConfig","extractCookieAsObj","extractStateFromDOM","utils_1","insertUserCustomOAdsParams_1","snowplow_1","isPageArticle","some","entry","article","oAdsConfig","ft_pageview_id","setFTPageviewId","specialistStateCookie","getCookie","uuidId","loggedin","usertype","isUserCustomOAdsParamsEnabled","_specialist_user_data","setUserData","getDomainUserId","domainUserId","setDomainUserId","pt","_a","_b","page","asset_type","setPtTargeting","setSiteTargeting","_c","primary_tag","content_category","uuid","content_id","setArticleData","nodeId","atob","oAdsConfigElement","__rest","t","p","getOwnPropertySymbols","propertyIsEnumerable","USER_CUSTOM_AD_PARAMS","enabledTitles","code","getAppTitleCode","setWindowData","expiry","adsDemographics","ftConsentCookieValue","getLocalStorageObject","getTime","fetch","endpoint","hostname","credentials","json","userData","every","updateLocalStorageWithExpiry","titleCookies","titles","brr","fdi","fta","ic","pwm","sv","tb","endsWith","titleCode","cookieId","domainUserIdCookie","IAS_SCRIPT_ID","slotDisplayQueue","requestAds","displaySlot","displayCalled","__iasPETTimeoutRequestAds","iasDataHandler","__iasPET","setTargetingForGPT","prepareAndPushPETSlot","iasPETSlots","getSlots","getSizes","adSlotId","getSlotElementId","adUnitPath","getAdUnitPath","queue","adSlots","dataHandler","pubId","head","appendChild","__iasAdRefreshConfig","refreshTargeting","enabled","targetingKey","excludeList","attachIasScript","parseJSONSafe","getDocumentHeight","getWindowYScroll","getWindowHeight","waitFor","isReady","reject","timeoutId","ms","offsetHeight","expiryMs","__webpack_module_cache__","__webpack_require__","moduleId","module","__webpack_modules__","d","definition","o","enumerable","r","Symbol","toStringTag"],"mappings":"wCAEA,IAAIA,EA8BJ,SAASC,EAAUC,GAClB,OAAOA,EACJC,SAASC,gBAAgBC,aACzBC,KAAKC,IAAIJ,SAASC,gBAAgBC,aAAcG,OAAOC,aAAe,GAS1E,SAASC,EAASR,GACjB,OAAOA,EACJC,SAASC,gBAAgBO,YACzBL,KAAKC,IAAIJ,SAASC,gBAAgBO,YAAaH,OAAOI,YAAc,G,+BAuExE,SACCZ,MAAO,WACNA,GAAQ,GAETa,UAhHD,SAAmBC,EAAWC,EAAMC,GACnCA,EAASA,GAAUb,SAASc,KAExBjB,GAEHkB,QAAQC,IAAI,aAAcL,EAAWC,GAGtCC,EAAOI,cACN,IAAIC,YAAY,aAAeP,EAAW,CACzCQ,OAAQP,EACRQ,SAAS,MAsGXb,WACAT,YACAuB,QA7DD,SAAiBtB,GAChB,MAAO,CACNuB,OAAQxB,EAAUC,GAClBwB,MAAOhB,EAASR,KA2DjByB,kBA1CD,WACC,MAAO,CACNF,OAAQtB,SAASc,KAAKW,aACtBF,MAAOvB,SAASc,KAAKY,YACrBC,KAAMtB,OAAOuB,aAAevB,OAAOwB,QACnCC,IAAKzB,OAAO0B,aAAe1B,OAAO2B,UAsCnCC,cAbD,WACC,OAAOjC,SAASkC,QAahBC,eAhCD,WACC,MAAMC,EAAc/B,OAAOgC,OAAOD,YAClC,OAAIA,EAC2B,iBAAhBA,EACXA,EAAYE,MAAM,KAAK,GACvBF,EAAYG,KAAKD,MAAM,KAAK,GACrBjC,OAAOmC,WACVnC,OAAOmC,WAAW,2BAA2BC,QACjD,WACA,YAEI3C,KAAeS,IAAa,WAAa,aAsBjDmC,SCpHD,SAAkBC,EAAMC,GACvB,IAAIC,EACJ,OAAO,WACN,MAAMC,EAAOC,UACPC,EAAQ,KACbH,EAAU,KACVF,EAAKM,MAAMC,KAAMJ,IAElBK,aAAaN,GACbA,EAAUO,WAAWJ,EAAOJ,KD4G7BS,SC5FD,SAAkBV,EAAMC,GACvB,IAAIC,EACJ,OAAO,WACN,GAAIA,EACH,OAED,MAAMC,EAAOC,UACPC,EAAQ,KACbH,EAAU,KACVF,EAAKM,MAAMC,KAAMJ,IAGlBD,EAAUO,WAAWJ,EAAOJ,MChDxB,EAAWU,EAAMD,SACjB,EAAWC,EAAMZ,SAEjBa,EAAY,GACZC,EAAY,CACjBC,OAAQ,IACRrB,YAAa,IACbsB,WAAY,IACZC,OAAQ,KAoLT,GACC9D,MAAO,WACNyD,EAAMzD,SAEP+D,SAzCD,SAAkBjD,GACC,WAAdA,GAAwC,QAAdA,GAjH/B,WACC,GAAI4C,EAAUE,OACb,OAED,MAAM9C,EAAY,SACZkD,EAAU,GAAS,SAASC,GACjCR,EAAM5C,UAAU,SAAU,CACzBqD,SAAUT,EAAMjC,UAChB2C,cAAeF,MAEdN,EAAUC,QAGbpD,OAAO4D,iBAAiBtD,EAAWkD,GACnCN,EAAUE,OAAS,CAClB9C,UAAWA,EACXkD,QAASA,GAkGTK,GAGiB,WAAdvD,GAAwC,QAAdA,GA5C/B,WAEC,GAAI4C,EAAUI,OACb,OAGD,MAAMhD,EAAY,SACZkD,EAAU,GAAS,SAASC,GACjC,MAAMK,EAAYb,EAAM9B,oBACxB8B,EAAM5C,UAAU,SAAU,CACzBqD,SAAUT,EAAMjC,UAChBI,aAAc0C,EAAU7C,OACxB8C,WAAYD,EAAUxC,KACtB0C,UAAWF,EAAUrC,IACrBJ,YAAayC,EAAU5C,MACvByC,cAAeF,MAEdN,EAAUG,QAEbtD,OAAO4D,iBAAiBtD,EAAWkD,GACnCN,EAAUI,OAAS,CAClBhD,UAAWA,EACXkD,QAASA,GAuBTS,GAGiB,gBAAd3D,GAA6C,QAAdA,GAlGpC,WAEC,GAAI4C,EAAUnB,YACb,OAGD,MAAMzB,EAAY,oBACZkD,EAAU,GAAS,SAASC,GACjCR,EAAM5C,UAAU,cAAe,CAC9BqD,SAAUT,EAAMjC,UAChBe,YAAakB,EAAMnB,iBACnB6B,cAAeF,MAEdN,EAAUpB,aAEb/B,OAAO4D,iBAAiBtD,EAAWkD,GACnCN,EAAUnB,YAAc,CACvBzB,UAAWA,EACXkD,QAASA,GAiFTU,GAGiB,eAAd5D,GAA4C,QAAdA,GA7EnC,WAEC,GAAI4C,EAAUG,WACb,OAGD,MAAM/C,EAAY,mBACZkD,EAAU,GAAS,SAASC,GACjCR,EAAM5C,UAAU,aAAc,CAC7BwB,OAAQoB,EAAMrB,gBACd+B,cAAeF,MAEdN,EAAUE,YAEbrD,OAAO4D,iBAAiBtD,EAAWkD,GAEnCN,EAAUG,WAAa,CACtB/C,UAAWA,EACXkD,QAASA,GA4DTW,IA4BDC,gBAdD,SAASA,EAAgB9D,GACN,QAAdA,EACH+D,OAAOC,KAAKpB,GAAWqB,QAAQH,GACrBlB,EAAU5C,KACpBN,OAAOwE,oBAAoBtB,EAAU5C,GAAWA,UAAW4C,EAAU5C,GAAWkD,gBACzEN,EAAU5C,KAUlBmE,oBAzKD,SAASA,EAAoBnE,EAAWoE,GACX,iBAAjBhC,UAAU,IACpB+B,EAAoB,SAAU/B,UAAU,IACxC+B,EAAoB,SAAU/B,UAAU,IACxC+B,EAAoB,cAAe/B,UAAU,IAC7C+B,EAAoB,aAAc/B,UAAU,KAClCgC,IACVvB,EAAU7C,GAAaoE,IAmKxB5C,eAAgBmB,EAAMnB,eACtBd,QAASiC,EAAMjC,QACfG,kBAAmB8B,EAAM9B,kBACzBS,cAAeqB,EAAMrB,eC9LhB+C,EAAWC,IAEf,MAAMC,EAAc7E,OAAO8E,KAAO9E,OAAO6E,aAAe7E,OAAO+E,eAAiB/E,OAAOgF,mBAAqBhF,OAAOiF,eAE/GJ,GAAeA,EAAYK,OAC7BL,EAAYM,WAAWP,GACvBC,EAAYK,KAAKN,KAKrB,SAASQ,EAAoBC,GAC3B,IAAIC,EAAS,GAMb,OAJID,GAA8C,iBAApBA,GAAgC,QAASA,GAAmB,SAAUA,IAClGC,EAAS,KAAO,CAACD,EAAgBE,IAAKF,EAAgBT,KAAMS,EAAgBG,KAAMH,EAAgBI,YAAYC,KAAK,OAG9GJ,EAqCT,SAASK,EAAGf,EAAMgB,EAAUpF,GAC1BoE,EAAO,QAAQA,KAGfpE,EAASA,GAAUb,SAASc,MAAQd,SAASC,iBACtCgE,iBAAiBgB,EAAMgB,GAuEhC,SAASC,EAAeC,EAAoBC,GAC1C,IAAKlB,cAAgBA,YAAYmB,iBAC/B,OAGF,MACMC,EADiBH,EAAmBI,QAAOC,GAASJ,EAAcK,SAASD,EAAME,eAC5CC,KAAIH,GAASA,EAAMI,QAExDC,EAAgB,GAAGC,UAAUR,GACjBpB,YAAYmB,iBAAiB,QACrCzB,SAAQ,EAChBK,WAEA4B,EAAcjC,SAAQmC,IAChB9B,EAAK+B,MAAM,QAAQD,MACrB7B,YAAYM,WAAWP,SA8F/B,IAAIgC,EAAY,CACdC,KAAM,SAAUC,EAASC,GACvBD,EAA6B,iBAAZA,EAAuBA,EAAUE,KAAKC,UAAUH,IACjEC,EAASrE,UAAU,IAAM1C,OAAOyB,KACzByF,YAAYJ,EAAS,MAE9BK,MAAO,SAAUL,GAEf,GAAuB,iBAAZA,GAAuC,MAAfA,EAAQ,GACzC,OAAOA,EAIT,IACE,OAAOE,KAAKG,MAAML,GAClB,MAAOM,GAEP,OAAON,KAKb,IAAIlB,EACAyB,EACAC,EAEJ,SAASC,IACP,IAAIC,EACJ,MAAMC,EAAO,WAAkB,GAa/B,OADApD,OAAOC,KAAK+C,GAAe9C,SAV3B,SAA+BmD,GAC7B,MAAMC,EAAiBN,EAAcK,GAEjCD,EAAKvG,OAASyG,EAAe,IAAMF,EAAKxG,QAAU0G,EAAe,MAC9DH,GAAUG,EAAe,IAAMN,EAAcG,GAAQ,MACxDA,EAASE,MAMRF,EAGT,SAASI,IACP,MAAMJ,EAASD,IAEXD,IAAYE,IACdK,EAAWL,GACX5B,EAAS4B,IAIb,SAASK,EAAWjD,GAClB0C,EAAU1C,EAGZ,SAASkD,IACP,OAAOR,EAET,SAASS,EAAOC,EAAMC,GACpB,QAAK,EAAMC,WAAWD,KAKtBZ,EAAgBW,EAChBpC,EAAWqC,EACXJ,EAAWN,KACX5H,SAASc,KAAKmD,iBAAiB,wBAAyBgE,GACxDjI,SAASc,KAAKmD,iBAAiB,mBAAoBgE,GACnD,WAAmB,eACnB,WAAmB,UACZE,KAqBT,SAASnH,IACP,IAAIuB,EACAiG,GAEiD,IAAjD,sBAAsBC,QAAQ1F,UAAU,KAC1CR,EAAO,MACPiG,EAAY,IAEZjG,EAAOQ,UAAU,GACjByF,EAAY,GAGd,MAAM1F,EAAO,GAAG4F,MAAMC,KAAK5F,UAAWyF,GAElCxH,EAAI4H,KAAKrG,IACXlC,OAAOU,QAAQwB,GAAMU,MAAM5C,OAAOU,QAAS+B,GAlC/C,sBAwIA,MAAM+F,EAAMnE,OAAOoE,UAAUC,eAmB7B,SAASC,EAAGC,GACV,MAAM1G,EAAOmC,OAAOoE,UAAUI,SAASP,KAAKM,GAAQjC,MAAM,sBAAsB,GAEhF,OAAe,OAAXiC,EACK,YACaE,IAAXF,EACF,YAEA1G,EA1BX6F,EAAOD,WAAaA,EACpBnH,EAAIoI,MA9DU,SAAU5C,GACjBxF,EAAI4H,KAAK,mBAIdvI,OAAOU,QAAQsI,eAAe7C,GAAS,UA0DzCxF,EAAIsI,IApDQ,WACLtI,EAAI4H,KAAK,aAIdvI,OAAOU,QAAQwI,YAgDjBvI,EAAI4H,KAlGS,SAAUrG,GAGrB,OADciH,cAAgBA,aAAaC,QAAQ,UAAsD,IAA3CC,SAASC,OAAOlB,QAAQ,gBACtEpI,OAAOU,SAAWV,OAAOU,QAAQwB,IAgGnDvB,EAAI4I,KA1ES,WACX,MAAM9G,EAAO,CAAC,QAAQgE,OAAO,GAAG4B,MAAMC,KAAK5F,UAAW,IACtD/B,EAAIiC,MAAM,KAAMH,IAyElB9B,EAAI6I,KA3FS,WACX,MAAM/G,EAAO,CAAC,QAAQgE,OAAO,GAAG4B,MAAMC,KAAK5F,UAAW,IACtD/B,EAAIiC,MAAM,KAAMH,IA0FlB9B,EAAI8I,MApFU,WACZ,MAAMhH,EAAO,CAAC,SAASgE,OAAO,GAAG4B,MAAMC,KAAK5F,UAAW,IACvD/B,EAAIiC,MAAM,KAAMH,IAmFlB9B,EAAI+I,MAlDU,SAAUnJ,EAAMoJ,GACxBhJ,EAAI4H,KAAK,QAAUvI,OAAOU,UACxBA,QAAQgJ,MACVhJ,QAAQgJ,MAAMnJ,EAAMoJ,GAEpBjJ,QAAQC,IAAIJ,KA8ClBI,EAAIiJ,eA1CmB,SAAUhB,EAAQe,GACvC,GAAIhJ,EAAI4H,KAAK,QAAUvI,OAAOU,QAC5B,GAAIkI,GAAUlI,QAAQgJ,MAAO,CAC3B,MAAMnJ,EAAO8D,OAAOC,KAAKsE,GAAQtC,KAAIuD,IACnC,IAAIC,EAQJ,OALEA,EADEC,EAAQnB,EAAOiB,KAAUG,EAASpB,EAAOiB,IACrC7C,KAAKC,UAAU2B,EAAOiB,IAEtBjB,EAAOiB,GAGR,CACLI,IAAKJ,EACLK,MAAOJ,MAGXpJ,QAAQgJ,MAAMnJ,EAAMoJ,QAEpBjJ,QAAQC,IAAIiI,IAmDlB,MAAMmB,EAAU,SAAUI,GACxB,MAAmB,UAAZxB,EAAGwB,IAQNC,EAAW,SAAUD,GACzB,MAAmB,WAAZxB,EAAGwB,IAQNjC,EAAa,SAAUiC,GAC3B,MAAmB,aAAZxB,EAAGwB,IAiBNH,EAAW,SAAUG,GACzB,MAAmB,WAAZxB,EAAGwB,IAQNE,EAAW,SAAUF,GACzB,OAAOA,GAAe,OAARA,GAAgBA,IAAQnK,QAUlCsK,EAAgB,SAAUH,GAC9B,MAAM3B,EAAMnE,OAAOoE,UAAUC,eAI7B,IAAKyB,IAAQH,EAASG,IAAQA,EAAII,UAAYF,EAASF,GACrD,OAAO,EAGT,IAEE,GAAIA,EAAIK,cAAgBhC,EAAIF,KAAK6B,EAAK,iBAAmB3B,EAAIF,KAAK6B,EAAIK,YAAY/B,UAAW,iBAC3F,OAAO,EAET,MAAOrB,GAGP,OAAO,EAKT,IAAI6C,EAEJ,IAAKA,KAAOE,GAGZ,YAAerB,IAARmB,GAAqBzB,EAAIF,KAAK6B,EAAKF,IAyMtCQ,EAAc,SAAUC,GAC5B,OAAOA,EAAOC,QAAQ,eAAe,SAAUhE,EAAOiE,EAAQC,GAC5D,OAAOA,EAAOC,kBAsHZC,EAAyBjL,KAAKkL,SAIpC,IAAI,EAAQ,CACVrF,KACAsF,IA7zBF,SAAarG,EAAMgB,EAAUpF,GAC3BoE,EAAO,QAAQA,KAGfpE,EAASA,GAAUb,SAASc,MAAQd,SAASC,iBACtC4E,oBAAoBI,EAAMgB,IAyzBjCsF,KAhzBF,SAActG,EAAMgB,EAAUpF,GAa5BmF,EAAGf,GAZa,SAAUuG,IAEXA,EAAM3K,QAAU2K,EAAMC,YAC9B5G,oBAAoBI,EAAO,QAAQA,IAAQgB,GAE5CA,IACFA,EAASuF,GAETvF,EAAW,QAIGpF,IAoyBlBH,UAz2BF,SAAmBqG,EAAWnG,EAAMC,GAElCA,EAASA,GAAUb,SAASc,MAAQd,SAASC,gBAC7C8G,EAAY,QAAQA,IACpB,MAAM2E,EAAO,CACXtK,SAAS,EACTuK,YAAY,EACZxK,OAAQP,GASJ+E,EAASF,EAPqB,iBAAT7E,GAAqB,QAASA,EACzB,CAC9BgF,IAAKhF,EAAKgF,IACVX,KAAMrE,EAAKqE,KACXY,KAAMjF,EAAKiF,MAAQjF,EAAKiF,KAAK+F,OAAShL,EAAKiF,KAAKqD,WAAa,GAC7DpD,WAAYlF,EAAKkF,YACf,IAGJd,EADiB+B,EAAYpB,GAE7B9E,EAAOI,cAAc,IAAIC,YAAY6F,EAAW2E,KAu1BhDzE,YACA4E,WAAYzD,EACZpH,MACAoJ,UACAK,WACAlC,aACAuD,UAxYgB,SAAUtB,GAC1B,MAAmB,YAAZxB,EAAGwB,IAwYVH,WACAK,WACAC,gBACAoB,iBA5UuB,SAAUC,GACjC,OAAOvB,EAASuB,IAAQC,QAAQD,EAAIJ,SA4UpCM,UA1UgB,SAAUC,GAC1B,OAAOA,GAAgC,IAArBA,EAAQvB,UAAkBuB,EAAQC,UAAW,GA0U/DC,OAxUF,SAASA,IAIP,IAAIC,EACAC,EACAC,EACAC,EACAC,EACA7L,EAASkC,UAAU,IAAM,GAC7B,MAAM6I,EAAS7I,UAAU6I,OACzB,IAAIe,GAAO,EACPC,EAAI,EAmBR,GAjBsB,kBAAX/L,IACT8L,EAAO9L,EACPA,EAASkC,UAAU,IAAM,GAEzB6J,EAAI,GAMgB,iBAAX/L,GAAwB0H,EAAW1H,KAC5CA,EAAS,IAMP+K,IAAWgB,EACb,OAAO/L,EAGT,KAAO+L,EAAIhB,EAAQgB,IAEjB,GAAiC,QAA5BN,EAAUvJ,UAAU6J,IAEvB,IAAK,MAAM3H,KAAQqH,EAGjB,GAAIA,EAAQvD,eAAe9D,GAAO,CAIhC,GAHAsH,EAAM1L,EAAOoE,GACbuH,EAAOF,EAAQrH,GAEXpE,IAAW2L,EACb,SAIEG,GAAQH,IAAS7B,EAAc6B,IAASpC,EAAQoC,KAClDC,EAAcrC,EAAQoC,GAElBC,GACFA,GAAc,EACdC,EAAQH,GAAOnC,EAAQmC,GAAOA,EAAM,IAEpCG,EAAQH,GAAOlC,EAASkC,GAAOA,EAAM,GAIvC1L,EAAOoE,GAAQoH,EAAOM,EAAMD,EAAOF,SACjBrD,IAATqD,IACT3L,EAAOoE,GAAQuH,GAQzB,OAAO3L,GAiQPgM,KArPW,SAAUb,EAAKc,EAAWC,GACrC,IAAIC,EACAzC,EACJ,MAAM0C,EAAU,GAEhB,GAAIjB,GAAOA,EAAI1J,MAGb,IAAK,IAAI4K,EAAM,EAAGC,GAFlBnB,EAAMA,EAAI1J,MAAMwK,IAEUlB,OAAQsB,EAAMC,EAAGD,GAAO,EAChD3C,EAAQyB,EAAIkB,GACZF,EAAOzC,EAAMjI,MAAMyK,GAEfC,EAAKpB,OAAS,IAChBqB,EAAQD,EAAK,GAAGI,QAAUJ,EAAKtE,MAAM,GAAG3C,KAAKgH,IAKnD,OAAOE,GAoOPI,OAvNa,SAAUC,EAAWC,EAAOtH,EAAUuH,EAASC,GAC5D,MAAMC,EAAM1N,SAAS2N,cAAc,UAC7BC,EAAO5N,SAAS6N,qBAAqB,UAAU,GACrD,IAAIC,GAAS,EAEb,SAASC,EAAgB9H,GAElB6H,IACH7H,EAAS0C,OACTmF,GAAS,EAGLL,GACFC,EAAIM,cAAcC,YAAYP,IAwCpC,OAnCAA,EAAIQ,aAAa,MAAOZ,GACxBI,EAAIQ,aAAa,QAAS,IAGtBX,IACFG,EAAIH,MAAQ,QAKVhF,EAAWtC,KAET4C,EAAIF,KAAK+E,EAAK,sBAChBA,EAAIS,mBAAqB,WACA,WAAnBT,EAAIU,YACNL,EAAgB9H,IAIpByH,EAAIW,OAAS,WACXN,EAAgB9H,KAOlBsC,EAAWiF,KACbE,EAAIY,QAAU,WACZP,EAAgBP,KAKpBI,EAAKW,WAAWC,aAAad,EAAKE,GAC3BF,GAmKPe,YAzJkB,WAClB,OAAOzO,SAAS0O,UAAY,IAyJ5B5D,cACA6D,mBAvIyB,SAAUC,GACnC,MAAM3J,EAAOwF,EAASmE,GAAaA,EAAYA,EAAU3J,KACzD,OAAO6F,EAAY7F,EAAK+F,QAAQ,iBAAkB,MAsIlD6D,YA5HkB,WAClB,OAAO7O,SAAS0J,SAASoF,MAAQ,IA4HjCC,eAnHqB,WACrB,OAAO/O,SAAS0J,SAASC,OAAOqF,UAAU,IAAM,IAmHhDC,oBA1G0B,SAAUhK,EAAMiK,GAC1CA,EAAMA,GAAO7O,OAAOqJ,SAASoF,KAC7B7J,EAAOA,EAAK+F,QAAQ,SAAU,QAC9B,MACMmE,EADQ,IAAIC,OAAO,OAASnK,EAAO,qBACnBoK,KAAKH,GAE3B,OAAKC,EAIAA,EAAQ,GAING,mBAAmBH,EAAQ,GAAGnE,QAAQ,MAAO,MAH3C,GAJA,MAoGTuE,aAtFmB,WACnB,MAAMC,EAAM,IAAIC,KAChB,MAAO,CAACD,EAAIE,cAAe,IAAIF,EAAIG,WAAa,IAAIjH,OAAO,GAAI,IAAI8G,EAAII,YAAYlH,OAAO,GAAI,IAAI8G,EAAIK,aAAanH,OAAO,GAAI,IAAI8G,EAAIM,eAAepH,OAAO,GAAI,IAAI8G,EAAIO,eAAerH,OAAO,IAAI3C,KAAK,KAqFvMiK,iBA3EuB,SAAUC,GAEjC,MAAMC,EAAUlQ,SAAS6N,qBAAqB,UAC9C,IAAIsC,EACAvC,EACAhB,EAAIsD,EAAQtE,OAEhB,KAAOgB,KAEL,GAAIsD,EAAQtD,GAAGwD,gBAAkBH,EAAc,CAC7CrC,EAAOsC,EAAQtD,GACf,MAMJ,GAAIgB,EAEF,KAAOA,EAAKW,YAAY,CAItB,GAHA4B,EAAWvC,EAAKyC,aAAa,mBAGzBF,EACF,OAAOA,EAGTvC,EAAOA,EAAKW,WAIhB,OAAO,GA6CP+B,qBA3C2B,SAA8BC,GACzD,OAAOA,EAAaC,QAAO,CAACC,EAAM7P,KAChC6P,EAAK7P,EAAK0J,KAAO1J,EAAK2J,MACfkG,IACN,KAwCHC,OAtCa,SAAUzL,GACvB,MAAMkF,EAAMnK,SAAS0Q,OAAO1J,MAAM,YAAY/B,qBAC9C,OAAOkF,EAAMA,EAAIwG,MAAQ,MAqCzBC,WAnCiB,IAhcL,SAoeZC,aAvvBF,SAAsBC,EAAa7K,EAAU8K,GACtCC,MAAM5G,QAAQ0G,GAKnBA,EAAYlM,SAAQ,SAAUqM,IACxBF,GAAmB,EAAMG,SAASD,EAAKE,eACxBH,MAAM5G,QAAQ6G,EAAKG,UAAYH,EAAKG,SAAW,IACvDxM,SAAQ,SAAUyM,IAOjC,SAA4BtK,EAAWuK,EAAUrL,GAC/CjG,SAASiE,iBAAiB8C,GAAW,SAASwK,EAAoB/F,IASpE,SAAqB8F,EAAUE,EAAcvL,GAC3C,MAAMN,EAAS,EAAMF,oBAAoB+L,GACnC5K,EAjGR,SAA2B6K,EAAQ9L,GACjC,MAAM+L,EAAYD,EAAO9K,KAAII,GAAa,QAAUA,EAAYpB,IAEhE,IAAKT,cAAgBA,YAAYyM,iBAE/B,MAAO,GAGT,MAAM/K,EAAQ,GAsBd,OArBA8K,EAAU9M,SAAQ,SAAUgN,GAC1B,MAAMC,EAAS3M,YAAYyM,iBAAiBC,GACtCE,EAAWF,EAAM5G,QAAQ,QAAS,IAAIA,QAAQrF,EAAQ,IAE5D,GAAIkM,GAAUA,EAAOjG,OAEnBhF,EAAMkL,GAAY3R,KAAK4R,MAAMF,EAAO,GAAGG,gBAMzC,GAAIrM,EAAQ,CACV,MAAMsM,EAAgBL,EAAM5G,QAAQrF,EAAQ,IACtCuM,EAAUhN,YAAYyM,iBAAiBM,GAEzCC,GAAWA,EAAQtG,SACrBhF,EAAMkL,GAAY3R,KAAK4R,MAAMG,EAAQ,GAAGF,gBAIvCpL,EAmEOuL,CAAkBb,EAAS1K,MAAOjB,GAEhD,GAAI2L,EAASc,WAAY,CACvB,MAAMC,EA9CV,SAAgCC,GAC9B,IAAKpN,cAAgBA,YAAYmB,mBAAqB,EAAM+D,QAAQkI,GAElE,MAAO,GAGT,MAAMC,EAAgBrN,YAAYmB,iBAAiB,cAC7CgM,EAAW,EAAMjI,QAAQmI,IAAkBA,EAAc,IAAM,GAC/D3L,EAAQ,GAId,OAHA0L,EAAa1N,SAAQ,SAAUkN,GAC7BlL,EAAMkL,GAA0C,iBAAvBO,EAASP,GAAyB3R,KAAK4R,MAAMM,EAASP,IAAa,KAEvFlL,EAkCY4L,CAAuBlB,EAASc,YACjD1N,OAAO+N,OAAO7L,EAAOyL,GAGvB,MAAMK,EAAe,CACnBC,SAAU,MACVC,OAAQtB,EAAS5K,YACjBmM,QAAS,CACPjM,MAAOA,IAGX8L,EAAaI,OAAS,CACpBC,WAAY1S,OAAO2S,KAAKC,IAAIC,iBAG1B1B,GAAgB,QAASA,IAC3BkB,EAAaS,SAAW,CACtBlO,KAAMuM,EAAavM,KACnBW,IAAK4L,EAAa5L,IAClBC,KAAM2L,EAAa3L,MAAQ2L,EAAa3L,KAAKqD,WAC7CpD,WAAY0L,EAAa1L,YAAc,GAGL,kBAAzB0L,EAAa4B,UACtBV,EAAaS,SAASC,QAAU5B,EAAa4B,UAIjDnN,EAASyM,GAzCPW,CAAY/B,EAAU9F,EAAMrK,OAAQ8E,GAE/BqL,EAASgC,UACZtT,SAAS6E,oBAAoBkC,EAAWwK,MAXtCgC,CAAmB,QAAUlC,EAASJ,EAAMhL,SARhD/C,KAAKlC,IAAI6I,KAAK,+EAsvBhB3D,iBACAsN,eA3rBF,SAAwB1C,EAAa1K,GACnCF,EAAe4K,EAAa1K,GAC5B,EAAM1F,UAAU,eA0rBhBwQ,SArCF,SAAkBC,GAChB,YAA6B,IAAfA,GAA8BA,EAAa/F,GAqCzDpG,WACAS,uBAQF,MAAMgO,EAAW,CACfC,QAAS,CACPC,eAAgB,CACdC,MAAO,CAAC,UAEVC,gBAAiB,CACfD,MAAO,CAAC,IAAK,MAEfE,UAAW,CACTF,MAAO,CAAC,IAAK,KAEfG,eAAgB,CACdH,MAAO,CAAC,IAAK,MAEfI,YAAa,CACXJ,MAAO,CAAC,IAAK,KAEfK,iBAAkB,CAChBL,MAAO,CAAC,CAAC,IAAK,IAAK,CAAC,IAAK,MAE3BM,SAAU,CACRN,MAAO,CAAC,IAAK,MAEfO,UAAW,CACTP,MAAO,CAAC,IAAK,MAEfQ,SAAU,CACRR,MAAO,CAAC,IAAK,OAEfS,eAAgB,CACdT,MAAO,CAAC,IAAK,KAEfU,SAAU,CACRV,MAAO,CAAC,GAAI,KAEdW,QAAS,CACPX,MAAO,CAAC,IAAK,KAEfY,WAAY,CACVZ,MAAO,CAAC,EAAG,KAGf/H,WAAY,CACV4I,MAAO,CAAC,KAAM,GAEdC,MAAO,CAAC,IAAM,GAEdC,OAAQ,CAAC,IAAK,GAEdC,MAAO,CAAC,EAAG,IAGbC,MAAO,CACLC,SAAS,EACTC,QAAQ,GAEVC,yBAAyB,GAqC3B,SAASC,IACP/R,KAAKgS,MAAQ,GAGfD,EAAOnM,UAAUqM,OAAS,SAAUC,EAAGC,GACrC,IAAIC,EAgBJ,OAdI,EAAM3K,cAAcyK,IACtB,EAAM/I,QAAO,EAAMnJ,KAAKgS,MAAOE,GAC/BE,EAASpS,KAAKgS,YACQ,IAANG,EAEdC,OADe,IAANF,EACAlS,KAAKgS,MAELhS,KAAKgS,MAAME,IAGtBlS,KAAKgS,MAAME,GAAKC,EAChBC,EAASD,GAGJC,GAGTL,EAAOnM,UAAUyM,MAAQ,SAAUjL,GAC7BA,SACKpH,KAAKgS,MAAM5K,GAElBpH,KAAKgS,MAAQ,IAIjBD,EAAOnM,UAAU0M,KAAO,WAEtB,OADAtS,KAAKgS,MAAQ,EAAM7I,QAAO,EAAM,GAAIoH,EApDtC,WACE,IAAIgC,EACJ,MAAMC,EAAe1V,SAAS2V,cAAc,yBAM5C,OAJID,IACFD,EAAYC,EAAa5G,MAGpB,CACL2G,UAAWA,GA2CiCG,GAnEhD,WACE,IAAIzG,EAAU,GAKd,OAJgB6B,MAAM6E,KAAK7V,SAAS8V,iBAAiB,8BAC7ClR,SAAQmR,IACd5G,EAAU9O,OAAOgH,KAAO,EAAMgF,OAAO8C,EAAS9H,KAAKG,MAAMuO,EAAOC,YAAc,iBAEzE7G,EA6D4D8G,IAC5D/S,KAAKgS,OAGd,MAAMgB,EAAS,IAAIjB,EACnB,IAAIkB,EAAWD,EAAOf,OAAOiB,KAAKF,GAClC,MAAMG,EAASH,EAAOV,KAAKY,KAAKF,GAC1BX,EAAQW,EAAOX,MAAMa,KAAKF,GAE1BI,EAAqB,CAAC,SACtBC,EAAuB,CAAC,SAAU,QAAS,SAC3CC,EAAmB,CACvB5C,MAAO,SAAUrJ,EAAOqJ,GACtB,IAAc,IAAVrJ,GAA6B,UAAVA,EACrB,OAAO,EACF,GAAI,EAAMH,QAAQwJ,GAAQ,CAE/B,MAAM6C,EAAQ,cACdlM,EAAMjI,MAAM,KAAKiE,QAAOV,GAAQA,EAAK+F,SAAQhH,SAAQiB,IAC/C4Q,EAAMC,KAAK7Q,GACbA,EAAKmF,QAAQyL,GAAO,SAAUzP,EAAOzF,EAAOD,GAC1CsS,EAAM+C,KAAK,CAACC,SAASrV,EAAO,IAAKqV,SAAStV,EAAQ,SAE3CgV,EAAmB7N,QAAQ5C,IAAS,GAC7C+N,EAAM+C,KAAK9Q,MAKjB,OAAO+N,GAETF,QAAS,SAAUnJ,EAAOqJ,GACxB,IAAc,IAAVrJ,GAA6B,UAAVA,EACrBqJ,GAAQ,MACH,CACL,MAAMiD,EAAUV,IAAWzC,SACX,EAAMtJ,QAAQG,GAASA,EAAQA,EAAMjI,MAAM,MACnDsC,SAAQkS,IACVD,GAAWA,EAAQC,IACrBA,EAASD,EAAQC,GAEb,EAAM1M,QAAQ0M,EAAOlD,MAAM,KAAO0C,EAAmB7N,QAAQqO,EAAOlD,MAAM,KAAO,EACnFkD,EAAOlD,MAAMhP,SAAQiB,IACnB+N,EAAM+C,KAAK9Q,MAGb+N,EAAM+C,KAAKG,EAAOlD,QAGpB,EAAM5S,IAAI8I,MAAM,uCAAuCgN,QAK7D,OAAOlD,GAETmD,gBAAiB,SAAU9R,EAAMsF,EAAOqJ,GACtC,MAAMoD,EAAa/R,EAAK+F,QAAQ,SAAU,IAAIiM,cAQ9C,OALK,EAAMtM,cAAciJ,KACvBA,EAAQ,IAGVA,EAAMoD,GAAcR,EAAiB5C,MAAMrJ,EAAOqJ,EAAMoD,IAAe,IAChEpD,GAETsD,kBAAmB,SAAUjS,EAAMsF,EAAOqJ,GACxC,MAAMoD,EAAa/R,EAAK+F,QAAQ,WAAY,IAAIiM,cAQhD,OALK,EAAMtM,cAAciJ,KACvBA,EAAQ,IAGVA,EAAMoD,GAAcR,EAAiB9C,QAAQnJ,EAAO,IAC7CqJ,GAETuD,kBAAmB,SAAU5M,GAC3B,OAAOA,EAAMjI,MAAM,KAAKqE,IAAIyQ,SAE9BC,UAAW,SAAU9M,EAAO8M,GAG1B,OAFA9M,EAAQ,EAAMsC,KAAKtC,EAAO,IAAK,KAC/B,EAAM8B,OAAOgL,EAAW9M,GACjB8M,GAETC,KAAM,SAAU/M,GAQd,MANc,KAAVA,GAA0B,SAAVA,EAClBA,GAAQ,EACW,UAAVA,IACTA,GAAQ,GAGHA,GAETgN,cAAe,SAAUhN,GAGvB,IAFoE,IAAzCgM,EAAqB9N,QAAQ8B,GAOxD,OAAOA,EAJL,EAAMvJ,IAAI6I,KAAK,qBAAqBU,kFAQpCiN,EAAiChN,KAChB,IAAjBA,EAAIiN,WACNjN,EAAIiN,SAAW,KAIbC,EAAqBlM,IACzB,MAAMmM,EAAOnM,EAAMrK,OAAOwW,KAC1BA,EAAKC,WAAapM,EAAMrK,OAAOyW,WAE3BD,EAAKE,eACPF,EAAKG,cAELH,EAAKI,WACLJ,EAAKpC,UAUT,SAASyC,EAAKC,EAAWL,EAAYM,GACnC,MACMC,EAAMhC,IACZ,IAAIiC,EAAajC,EAAS,UAAY,GAEtCjT,KAAK+U,UAAYA,EAIbL,IACF1U,KAAK0U,WAAaA,GAIpB1U,KAAKmV,MAAQnV,KAAKoV,aAAaL,EAAW,CACxCM,MAAO,eACP,cAAe,OACfC,SAAU,OAEZtV,KAAKuV,MAAQvV,KAAKoV,aAAapV,KAAKmV,MAAO,CACzCE,MAAO,iBAGTrV,KAAKwV,UACLN,EAAaA,EAAWlV,KAAK+B,OAAS,GAEtC/B,KAAKyV,OAAS,MACdzV,KAAK0V,OAAQ,EAEb1V,KAAKmU,UAAYe,EAAWf,WAAa,GACzCnU,KAAK0Q,MAAQwE,EAAWxE,OAAS,GACjC1Q,KAAK2V,OAAST,EAAWS,SAAU,EACnC3V,KAAK4V,MAAQV,EAAWU,QAAS,EACjC5V,KAAK6V,UAAYX,EAAWW,YAAa,EACzC7V,KAAK8V,WAAqC,IAAzBZ,EAAWY,UAC5B9V,KAAKqU,cAAgBa,EAAWb,cAG5B,EAAMnN,QAAQgO,EAAW1E,SAC3B8C,EAAiB9C,QAAQ0E,EAAW1E,QAASxQ,KAAK0Q,OACzC,EAAMjJ,cAAcyN,EAAW1E,WACxCxQ,KAAK0Q,MAAQ,GACblP,OAAOC,KAAKyT,EAAW1E,SAAS9O,SAAQoS,IACtC9T,KAAK0Q,MAAMoD,GAAcR,EAAiB9C,QAAQ0E,EAAW1E,QAAQsD,GAAa,aAInD,IAAxBoB,EAAWX,SACpBvU,KAAKuU,SAAWW,EAAWX,SAE3BvU,KAAKuU,SAAWtB,EAAS,cAAe,EAG1C,MAAM8C,EAAUhB,EAAUtC,cAAc,iBAExC,GAAIsD,GAAWd,EAAInD,yBAA2B9R,KAAK+U,UAAU5H,aAAa,oBAAqB,CAC7F,MAAM6I,EAAgB,CAAC,OAAQ,SAAU,SACnCC,EAAcjW,KAAK+U,UAAU5H,aAAa,oBAChD,EAAM9E,KAzDY,mBAyDM,KACtB,MAAM6N,EAAWF,EAAczQ,QAAQ0Q,GAAeA,EAAc,OACpEF,EAAQI,UAAUC,IAAI,4BAA6B,8BAA8BF,QAQrF,GAHAlW,KAAKqW,wBAGArW,KAAK0Q,MAAMhI,SAAW,EAAMjB,cAAczH,KAAK0Q,OAElD,OADA,EAAM5S,IAAI8I,MAAM,mCAAoC5G,KAAK+B,OAClD,EAIT/B,KAAKsW,iBAAmBtB,EAAgBhV,KAAKuU,UAC7CvU,KAAKuW,eACLvW,KAAKwW,kBACLxW,KAAKyW,iBACLzW,KAAK0W,iBAgTP,SAASC,EAAalC,GACpB,IAAK3G,MAAM5G,QAAQuN,EAAK/D,OAAQ,MAAO,kBACvC,MAAMA,EAAQ,GAEd,IAAK,MAAM/N,KAAQ8R,EAAK/D,MACtBA,EAAM+C,KAAK3F,MAAM5G,QAAQvE,GAAQA,EAAKE,KAAK,KAAOF,GAGpD,OAAO+N,EAAM7N,KAAK,MAQpB,SAAS+T,GAAiB,UACxBzC,IAEA,MAAM0C,EAAS,GAEf,IAAK,MAAOzP,EAAKH,KAAQzF,OAAOsV,QAAQ3C,GAAa,IACnD0C,EAAOpD,KAAK,GAAGrM,KAAOH,KAGxB,OAAO4P,EAAOhU,KAAK,MAQrB,SAASkU,GAAe,IACtBhH,IAEA,YAAmB,IAARA,EAA4B,mBACnCA,EAAIG,QAAgB,QACnBpC,MAAM5G,QAAQ6I,EAAIpN,MAChBoN,EAAIpN,KAAKE,KAAK,KADgB,MA/UvCiS,EAAKlP,UAAUyQ,qBAAuB,WACpCvI,MAAM6E,KAAK3S,KAAK+U,UAAUiC,YAAYtV,SAAQgK,IAC5C,MAAM3J,EAAO,EAAM0J,mBAAmBC,EAAU3J,MAC1CsF,EAAQqE,EAAUrE,MAEX,YAATtF,EACF/B,KAAK+B,GAAQuR,EAAiBvR,GAAMsF,EAAOrH,KAAK0Q,OAC9B,kBAAT3O,EACT/B,KAAKqU,cAAgBf,EAAiBe,cAAchN,GAClC,sBAATtF,GAAgC/B,KAAKuU,UAC9CD,EAA+BtU,MAC/BA,KAAKuU,SAAS0C,UAAY3D,EAAiBW,kBAAkB5M,IAC3C,2BAATtF,GAAqC/B,KAAKuU,UACnDD,EAA+BtU,MAC/BA,KAAKuU,SAAS2C,eAAiB5D,EAAiBc,KAAK/M,IAC5CiM,EAAiBvR,GAC1B/B,KAAK+B,GAAQuR,EAAiBvR,GAAMsF,EAAOrH,KAAK+B,IACvC,cAAcyR,KAAKzR,GAC5B/B,KAAK0Q,MAAQ4C,EAAiBU,kBAAkBjS,EAAMsF,EAAOrH,KAAK0Q,OACzD,YAAY8C,KAAKzR,GAC1B/B,KAAK0Q,MAAQ4C,EAAiBO,gBAAgB9R,EAAMsF,EAAOrH,KAAK0Q,OAEzD1Q,KAAK6F,eAAe9D,KAC3B/B,KAAK+B,GAAQuR,EAAiBc,KAAK/M,QAKzCyN,EAAKlP,UAAUuR,cAAgB,WAC7B,MAAMH,EAAa,GAKnB,OAJAlJ,MAAM6E,KAAK3S,KAAK+U,UAAUiC,YAAYtV,SAAQgK,IAC5CsL,EAAW,EAAMvL,mBAAmBC,IAAcA,EAAUrE,SAE9DrH,KAAKgX,WAAaA,EACXhX,MAOT8U,EAAKlP,UAAU2Q,aAAe,WAiB5B,OAfIvW,KAAKsW,kBAAoBtW,KAAKuU,WAChCvU,KAAK0V,OAAQ,EACb1V,KAAKsW,iBAAiBc,QAAQpX,KAAK+U,WAI/B/U,KAAK8V,WACP,EAAMzN,KAAK,gBAAgB,KACrBrI,KAAK2U,gBACP3U,KAAKqX,WAENrX,KAAK+U,YAIL/U,MAGT8U,EAAKlP,UAAUyR,OAAS,WACtBrX,KAAK+E,KAAK,iBAGN/E,KAAKsW,kBACPtW,KAAKsW,iBAAiBgB,UAAUtX,KAAK+U,YASzCD,EAAKlP,UAAU8Q,eAAiB,WAW9B,OATI,EAAMjP,cAAczH,KAAK0Q,SAEtB1Q,KAAK2U,gBACR3U,KAAK6U,WAGP,EAAM/R,GAAG,aAAc0R,EAAoBxU,KAAK+U,YAG3C/U,MAOT8U,EAAKlP,UAAU2R,SAAW,SAAU5U,GAC9BA,GAA4B,MAApBuR,OAAOvR,EAAK,KAAmC,MAApBuR,OAAOvR,EAAK,KACjD3C,KAAK+E,KAAK,SAAU,CAClBpC,KAAM,CAAC,OAAQ,WASrBmS,EAAKlP,UAAU4P,QAAU,WAQvB,OAPAxV,KAAK+B,KAAO/B,KAAK+U,UAAU5H,aAAa,oBAAsBnN,KAAK+U,UAAU5H,aAAa,cAErFnN,KAAK+B,OACR/B,KAAK+B,KAAO,cAAc9E,KAAKua,MAAsB,IAAhBva,KAAKkL,YAC1CnI,KAAK+U,UAAU/J,aAAa,kBAAmBhL,KAAK+B,OAG/C/B,MAOT8U,EAAKlP,UAAUiP,SAAW,WAKxB,OAJA7U,KAAK+U,UAAUoB,UAAUC,IAAI,gBAC7BpW,KAAKyX,iBAAgB,GACrB3a,SAASc,KAAKuY,UAAUC,IAAI,YAAYpW,KAAK+B,QAC7C,EAAMvE,UAAU,YAAawC,MACtBA,MAOT8U,EAAKlP,UAAU8R,SAAW,SAAUC,GAGlC,OAFA3X,KAAK+U,UAAUoB,UAAUC,IAAI,SAASuB,KACtC,EAAMna,UAAU,iBAAkBwC,MAC3BA,MAOT8U,EAAKlP,UAAU6R,gBAAkB,SAAU7D,GAEzC,OADA5T,KAAK+U,UAAU/J,aAAa,oBAAqB4I,GAC1C5T,MAOT8U,EAAKlP,UAAUgP,WAAa,WAG1B,OAFA5U,KAAK+U,UAAUoB,UAAUyB,OAAO,gBAChC9a,SAASc,KAAKuY,UAAUyB,OAAO,YAAY5X,KAAK+B,QACzC/B,MAOT8U,EAAKlP,UAAUyM,MAAQ,WAMrB,OAJI,EAAMhN,WAAWrF,KAAgB,YACnCA,KAAK6X,YAGA7X,MAOT8U,EAAKlP,UAAUkS,QAAU,WAavB,OAXI,EAAMzS,WAAWrF,KAAkB,eACrC,EAAMoI,IAAI,aAAcoM,EAAoBxU,KAAK+U,WACjD/U,KAAK+X,cAED/X,KAAKmV,MAAMrK,gBAAkB9K,KAAK+U,UACpC/U,KAAK+U,UAAUhK,YAAY/K,KAAKmV,OAEhCtX,QAAQ+I,MAAM,wEAIX5G,MAOT8U,EAAKlP,UAAUoS,iBAAmB,WAMhC,OAJI,EAAM3S,WAAWrF,KAA0B,sBAC7CA,KAAKiY,sBAGAjY,MAOT8U,EAAKlP,UAAUb,KAAO,SAAUhD,EAAMrE,GACpC,MAAMqS,EAAM/P,KAAK+P,KAAO,GAClBmI,EAAU,CACdnW,KAAM/B,KAAK+B,MAAQ,GACnBW,IAAK1C,KAAKmU,WAAanU,KAAKmU,UAAUzR,KAAO,GAC7CC,KAAMoN,EAAIpN,MAAQ,GAClBC,WAAYmN,EAAInN,YAAc,GAC9B6R,KAAMzU,MAYR,MAT2B,kBAAhB+P,EAAIG,UACbgI,EAAQhI,QAAUH,EAAIG,SAGpB,EAAMzI,cAAc/J,IACtB,EAAMyL,OAAO+O,EAASxa,GAGxB,EAAMF,UAAUuE,EAAMmW,EAASlY,KAAK+U,WAC7B/U,MAOT8U,EAAKlP,UAAUwP,aAAe,SAAU1K,EAAMyN,GAC5C,IAAIpD,EAAY,QAYhB,OATIoD,GACF3W,OAAOC,KAAK0W,GAAOzW,SAAQ,SAAU0W,GACnC,MAAM/Q,EAAQ8Q,EAAMC,GACpBrD,GAAa,GAAGqD,KAAQ/Q,QAI5B0N,GAAa,UACbrK,EAAK2N,mBAAmB,YAAatD,GAC9BrK,EAAK4N,WAGdxD,EAAKlP,UAAU+O,aAAe,SAAUD,GAGtC,QAFAA,EAAaA,GAAc1U,KAAK0U,cAEd,EAAMjN,cAAczH,KAAK0Q,SACP,IAA3B1Q,KAAK0Q,MAAMgE,IAUtBI,EAAKlP,UAAU4Q,gBAAkB,WAK/B,OAJIxW,KAAK2V,QACP3V,KAAK+U,UAAUoB,UAAUC,IAAI,iBAGxBpW,MAOT8U,EAAKlP,UAAU6Q,eAAiB,WAC9B,IAAIkB,EAYJ,OAVmB,IAAf3X,KAAK4V,OAAiC,SAAf5V,KAAK4V,MAC9B+B,EAAY,aACY,UAAf3X,KAAK4V,QACd+B,EAAY,eAGVA,IAAc1E,EAAS,4BACzBjT,KAAK+U,UAAUoB,UAAUC,IAAI,UAAUuB,KAGlC3X,MAyFT,IAAI0U,EAAa,KAQjB,SAAS6D,KAGT,SAASC,GAAoBC,EAAOC,EAAQ3V,GAC1C,IAAI4V,EAAQ,GAgBZ,OAfAF,EAAQA,GAASjX,OAAOC,KAAKzB,MAGzB,EAAM6I,iBAAiB4P,GACzBE,EAAMlF,KAAKgF,GACF,EAAMvR,QAAQuR,KACvBE,EAAQF,GAGVE,EAAMjX,QAAQkX,GAAI1F,KAAK,KAAMlT,KAAM0Y,IAE/B,EAAMrT,WAAWtC,IACnBA,EAAS0C,KAAKzF,KAAM2Y,GAGf3Y,KAST,SAAS4Y,GAAID,EAAOjJ,EAAQ3N,GAC1B,MAAM0S,EAAOkE,EAAM5W,GAEf0S,EACE,EAAMpP,WAAWoP,EAAK/E,IACxB+E,EAAK/E,KAED,EAAMrK,WAAWoP,EAAK1P,MACxB0P,EAAK1P,KAAK2K,GAEV,EAAM5R,IAAI6I,KAAK,mCAAoC+I,EAAQ3N,GAI/D,EAAMjE,IAAI6I,KAAK,uCAAwC+I,EAAQ3N,GAInE,SAAS8W,GAAiBlW,GACxB,IAAKA,EACH,OAAO,EAGT,MAAM6N,EAAUyC,EAAS,WAEzB,IAAK,MAAM6F,KAAQtI,EAGjB,GAAIA,EAAQ3K,eAAeiT,GAAO,CAChC,IAAIpI,EAAQF,EAAQsI,GAAMpI,MAM1B,GALAA,EAAQ,EAAMxJ,QAAQwJ,EAAM,IAAMA,EAAQ,CAACA,GAC7BA,EAAMrN,QAAO,SAAU0V,GACnC,OAAOA,EAAE,KAAOrF,SAAS/Q,EAAK,GAAI,KAAOoW,EAAE,KAAOrF,SAAS/Q,EAAK,GAAI,OAG5D+F,OACR,OAAOoQ,GAiKf,SAASE,GAAmBL,EAAOjE,GACjCiE,EAAMjX,SAAQ,SAAU+S,GAEtB,GAAIA,EAAM,CAIR,MAAMwE,EAAwBxE,EAAKM,WAAkE,eAArDN,EAAKM,UAAU5H,aAAa,qBACtE+L,EAAuBzE,EAAK/D,MAAMgE,IAAeD,EAAK/D,MAAMgE,GAAYrR,QAAOV,GAAmC,eAA3BkW,GAAiBlW,KAAwB+F,OAAS,EAE/I,GAAIuQ,GAAyBC,EAC3B,OAAO,EAGTzE,EAAKC,WAAaA,EAClBD,EAAK1P,KAAK,aAAc,CACtB2P,WAAYA,QAvKpB6D,EAAM3S,UAAUiP,SAAW,SAAU4D,GACnC,OAAOD,GAAoB/S,KAAKzF,KAAMyY,EAAO,aAO/CF,EAAM3S,UAAUgP,WAAa,SAAU6D,GACrC,OAAOD,GAAoB/S,KAAKzF,KAAMyY,EAAO,eAO/CF,EAAM3S,UAAUgM,QAAU,SAAU6G,GAClC,OAAOD,GAAoB/S,KAAKzF,KAAMyY,EAAO,YAO/CF,EAAM3S,UAAUyM,MAAQ,SAAUoG,GAChC,OAAOD,GAAoB/S,KAAKzF,KAAMyY,EAAO,UAO/CF,EAAM3S,UAAUkS,QAAU,SAAUW,GAClC,OAAOD,GAAoB/S,KAAKzF,KAAMyY,EAAO,WAAW,SAAUA,GAChEA,EAAM/W,SAAQK,IACZ/B,KAAK+B,GAAQ,YACN/B,KAAK+B,UASlBwW,EAAM3S,UAAUoS,iBAAmB,SAAUjW,GAC3C,OAAOyW,GAAoB/S,KAAKzF,KAAM+B,EAAM,qBAO9CwW,EAAM3S,UAAUuT,SAAW,SAAUpE,GAanC,GAVI,EAAMxN,SAASwN,KACjBA,EAAYjY,SAASsc,eAAerE,IAAcjY,SAAS2V,cAAc,qBAAqBsC,SAE7EA,EAAUsE,KACzBtE,EAAU/J,aAAa,kBAAmB+J,EAAUsE,IACpDtE,EAAUuE,gBAAgB,QAKzB,EAAMtQ,UAAU+L,GAEnB,OADA,EAAMjX,IAAI8I,MAAM,qCAAsCmO,IAC/C,EAITA,EAAU/J,aAAa,cAAe,QAEtC,MAAMyJ,EAAO,IAAIK,EAAKC,EAAWL,EAAY1U,KAAKgV,gBAAgB9B,KAAKlT,OAUvE,OAPIyU,IAASzU,KAAKyU,EAAK1S,OACrB/B,KAAKyU,EAAK1S,MAAQ0S,EAClBA,EAAK1P,KAAK,cACD/E,KAAKyU,EAAK1S,OACnB,EAAMjE,IAAI8I,MAAM,8BAA+B6N,EAAK1S,MAG/C0S,GAGT8D,EAAM3S,UAAU2T,YAAc,WAC5B,GAAItG,EAAS,SAASrB,SAAWqB,EAAS,WAAY,CACpD,MAAMvV,EAAOuV,EAAS,WAItB,GAHAjT,KAAKwZ,aAAe,EAGhB9b,EAAK+b,OAAS/b,EAAKmU,OAAQ,CAC7B,MAAMD,EAAU,MAETlU,EAAKR,KAAO8C,KAAKwZ,eAAiB9b,EAAKR,IAC1C8C,KAAK4R,UACI5R,KAAKwZ,cAAgB9b,EAAKR,KACnCwc,cAAc9H,IAIlB+H,YAAY/H,EAAwC,KAA9BgI,WAAWlc,EAAK+b,OAAS,KAInD,OAAOzZ,MAQTuY,EAAM3S,UAAUiU,aAAe,WAc7B,OAbA,EAAM/W,GAAG,kBAAmB,SAAU6V,EAAOrQ,GAC3C,MAAMmM,EAAOkE,EAAMrQ,EAAMrK,OAAO8D,MAGhC,GAAI0S,EAAM,CACR,EAAMtL,OAAOsL,EAAKA,EAAKgB,QAASnN,EAAMrK,OAAOwW,EAAKgB,SAClD,MAAM9S,EAAO2F,EAAMrK,OAAO8R,IAAIpN,KACxBiR,EAASiF,GAAiBlW,GAChC8R,EAAKgD,gBAAgB7D,GACrBa,EAAK8C,SAAS5U,GACd8R,EAAK1P,KAAK,aAAcuD,EAAMrK,UAEhCiV,KAAK,KAAMlT,OACNA,MAOTuY,EAAM3S,UAAU8Q,eAAiB,WAC/B,MAAMoD,EAAc7G,EAAS,cAO7B,OAJI,EAAM9L,SAAS2S,KACjBpF,EAAa,EAAM/L,WAAWmR,EAAad,GAAmB9F,KAAK,KAAMlT,QAGpEA,MAiCTuY,EAAM3S,UAAUmU,gBAAkB,WAEhC5c,OAAO4D,iBAAiB,UAExB,SAAmB4X,EAAOrQ,GACxB,MAAM5K,EAAO,EAAMqG,UAAUO,MAAMgE,EAAM5K,MAGzC,GAAIA,EAAK2B,OAAS,UAAUmU,KAAK9V,EAAK2B,OAAS,SAASmU,KAAK9V,EAAK2B,OAAQ,CACxE,MAAMA,EAAO3B,EAAK2B,KAAKyI,QAAQ,QAAS,IAGlC2M,EAAOkE,EADI,EAAM7L,iBAAiBxE,EAAMpE,OAAO/G,WACrB,EAEhC,IAAKsX,EAEH,YADA,EAAM3W,IAAI8I,MAAM,2CAKL,mBAATvH,EACFoV,EAAK1P,KAAK,mBACQ,cAAT1F,GAAwB3B,EAAKsc,UACtCvF,EAAKiD,SAASha,EAAKsc,WAEH,aAAT3a,GACPoV,EAAK1P,KAAK,iBACV0P,EAAKI,YAIE,SAASrB,KAAK9V,EAAK2B,MAC1BoV,EAAK1P,KAAK,QAASrH,GAEnB,EAAMI,IAAI8I,MAAM,+CAhCuBsM,KAAK,KAAMlT,OAAO,IAwCjEuY,EAAM3S,UAAUqU,iBAAmB,WACjCja,KAAKka,qBAAuBla,KAAKka,qBAAqB7W,QAAO8W,GACpDpR,SAASoR,EAASC,MAAQtd,SAASud,SAASF,EAASC,UAIhE7B,EAAM3S,UAAUoP,gBAAkB,SAAUE,GAC1C,MAAMoF,EAAoBrH,EAAS,aAAeiC,EAAa,GAC/DlV,KAAKka,qBAAuBla,KAAKka,sBAAwB,GACzDla,KAAKia,mBAEL,IAAIM,EAAsBva,KAAKka,qBAAqBM,MAAKL,GAEhDG,EAAkBF,MAAQD,EAASC,OAoB5C,GAAI,yBAA0Bjd,SAAWod,GAAuBxR,QAAQuR,GAAoB,CAC1F,MAAMlR,EAAU,GAGiB,iBAAtBkR,IAELA,EAAkBpD,iBACpB9N,EAAQqR,WAAaH,EAAkBpD,gBAKrCoD,EAAkBrD,YACpB7N,EAAQ6N,UAAYqD,EAAkBrD,WAGxC7N,EAAQgR,KAAOE,EAAkBF,MAAQ,MAG3CG,EAAsB,IAAIG,qBApC5B,SAAkBC,GAIhBA,EAAQtX,QAAOuX,GAAKA,EAAEC,iBAAiBzc,QAAUwc,EAAEC,iBAAiBxc,OAASuc,EAAEC,iBAAiBjc,KAAOgc,EAAEC,iBAAiBpc,OAAMqc,MAAK,CAACF,EAAGG,IAAMH,EAAEC,iBAAiBjc,IAAMmc,EAAEF,iBAAiBjc,MAAK8C,SAAQsZ,IACtM,MAAM/N,EAAW+N,EAAOrd,OAAOwP,aAAa,mBAGxCF,GACFuL,GAAoB/S,KAAKzF,KAAMiN,EAAU,cA2BWiG,KAAKlT,MAAOoJ,GACpEpJ,KAAKka,qBAAqBzG,KAAK8G,GAGjC,OAAOA,GAGThC,EAAM3S,UAAUlE,QAAU,SAAUuZ,GASlC,OARAzZ,OAAOC,KAAKzB,MAAM0B,SAAQK,IACxB,MAAM0S,EAAOzU,KAAK+B,GAGd0S,aAAgBK,GAClBmG,EAAGxV,KAAKzF,KAAMyU,MAGXzU,MAOTuY,EAAM3S,UAAU0M,KAAO,WACrBtS,KAAKuZ,cACLvZ,KAAK6Z,eACL7Z,KAAK0W,iBACL1W,KAAK+Z,kBACL/Z,KAAKgV,mBAGPuD,EAAM3S,UAAUjJ,MAAQ,YA5ZxB,SAAiBgc,GACf,MAAMjb,EAAO,GAEb,IAAK,MAAM+W,KAAQkE,EACjB,GAVgB,SAULlE,EAAO,CAChB,IAAIyG,EAAWC,EAAYC,EAE3B,MAAMC,EAAM,CACVtZ,KAAM0S,EAAK1S,KACX,YAAwC,QAA1BmZ,EAAYzG,EAAK1E,WAA+B,IAAdmL,OAAuB,EAASA,EAAUI,SAC1F,eAA4C,QAA3BH,EAAa1G,EAAK1E,WAAgC,IAAfoL,OAAwB,EAASA,EAAWvY,aAAe,MAC/G,gBAA6C,QAA3BwY,EAAa3G,EAAK1E,WAAgC,IAAfqL,OAAwB,EAASA,EAAWG,aAAe,MAChH5Y,KAAMoU,EAAetC,GACrB/D,MAAOiG,EAAalC,GACpBN,UAAWyC,EAAiBnC,IAE9B/W,EAAK+V,KAAK4H,GAIdxd,QAAQyF,MAAM,aACdzF,QAAQgJ,MAAMnJ,GACdG,QAAQwI,WAuYRmV,CAAQha,OAAOia,OAAOzb,QAGxB,IAAI2Y,GAAQ,IAAIJ,EAEhB,IAAImD,GAAa,GAEjB,SAASC,MAGTA,GAAU/V,UAAUgW,IAAM,WACxB,MAAMC,EAAU,CACdC,eAAgB9b,KAAK+b,kBACrBC,UAAWhc,KAAKgc,UAChBrT,WAAY3I,KAAK2I,YAEnB,EAAMQ,OAAOuS,GAAY1b,KAAKic,aAAcjc,KAAK0N,cAEjD,IAAK,MAAM1G,KAAQ6U,EAGbA,EAAQhW,eAAemB,IACzB,EAAMmC,OAAOuS,GAAYG,EAAQ7U,MAIrC,OAAO0U,IAGTC,GAAU/V,UAAUwQ,IAAM,SAAU9O,GAE9B,EAAMG,cAAcH,IACtB,EAAM6B,OAAOuS,GAAYpU,IAI7BqU,GAAU/V,UAAUgS,OAAS,SAAUxQ,GAEjCsU,GAAWtU,WACNsU,GAAWtU,IAItBuU,GAAU/V,UAAUyM,MAAQ,WAC1BqJ,GAAa,IAGfC,GAAU/V,UAAU8H,WAAa,WAC/B,GAAIuF,EAAS,mBACX,MAAO,CACLiJ,aAAc,EAAMxO,eAU1BiO,GAAU/V,UAAUqW,WAAa,WAC/B,MAAME,EAAK,EAAMpQ,oBAAoB,cAErC,GAAIoQ,EACF,MAAO,CACLC,WAAYD,IAKlBR,GAAU/V,UAAUmW,kBAAoB,WACtC,IAAIM,EACJ,MAAM7Q,EAAW,EAAMD,cAEjB+Q,EAAS,CACb,OAAQ,MACR,eAAgB,MAChB,eAAgB,MAChB,mBAAoB,MACpB,cAAe,MACfC,OAAQ,OAUV,OARA/a,OAAOC,KAAK6a,GAAQ5a,SAAQsK,IACL,IAAIE,OAAO,uBAAuBF,MAGtCwH,KAAKhI,KACpB6Q,EAAaC,EAAOtQ,OAGjBqQ,GAAc,CACnBG,OAAQH,IACL,IAGPV,GAAU/V,UAAU6W,WAAa,WAC/B,MAAMC,EAAK,EAAM/S,KAAK,EAAMkC,iBAAkB,MAAO,KACrD,IAAI8Q,EAAWD,EAAGE,GAAKF,EAAG3D,GAAK2D,EAAGG,OAASH,EAAGI,WAAaJ,EAAGK,kBAAe9W,EAO7E,OAJI0W,GAAyB,KAAbA,IACdA,EAAWK,SAASL,GAAU5I,cAAcjM,QAAQ,UAAW,KAAKA,QAAQ,OAAQ,KAAKoC,QAGpF,CACL+S,GAAIN,IAIRhB,GAAU/V,UAAUoW,UAAY,WAC9B,MAAO,CACLkB,GAAI,EAAM7Q,iBAIdsP,GAAU/V,UAAU+C,WAAa,WAC/B,OAAOsK,EAAS,cAAgB,CAC9BkK,IAAK,EAAMxU,WAAW1D,cACpB,IAGN0W,GAAU/V,UAAUjJ,MAAQ,WAC1B,MAAMmB,EAAM,EAAMA,IACZ4d,EAAa1b,KAAK4b,MAGe,IAAnCpa,OAAOC,KAAKia,GAAYhT,SAC1B5K,EAAIoI,MAAM,aACVpI,EAAIiJ,eAAe/G,KAAK4b,OACxB9d,EAAIsI,QAIR,IAAI+N,GAAY,IAAIwH,GAEpB,MAAMyB,GAAgB,CAAC,IAAK,MAc5B,SAASC,GAAmBC,EAAcC,GACxC,IAAKA,GAAeA,EAAY7U,OAAS,EACvC,OAAO4U,EAGT,MAAME,EAAc,IAAIC,gBAAgBH,GAExC,IAAK,MAAMlW,KAAOmW,EAChBC,EAAYE,OAAOtW,GAGrB,OAAOoW,EAAYxX,WAwDrB,MAAM2X,GAAoB,CACxBC,mBAAoB,IACpBC,oBAAqB,IACrBC,cAAe,GAGjB,IAAIhE,IAAc,EA0BlB,SAASiE,KACF5gB,OAAO6gB,YAEV7gB,OAAO6gB,UAAY,GAInB7gB,OAAO6gB,UAAUC,IAAM,IAGzB,EAAM9T,OAAO,kDAAkD,GAAM,KACnE,EAAM3M,UAAU,yBACf0gB,IACD,EAAM1gB,UAAU,oBAAqB0gB,MAgBzC,SAASC,GAAMC,GACb,MAAMC,EAAkBpL,EAAS,mBAAqB,EAAI,EAC1D+K,UAAUM,SAASvd,iBAAiB,kBAAmBwd,IA6IzD,SAA0BH,GACpBA,EAAUI,aACZR,UAAUM,SAASG,qBACnBT,UAAUU,eAAeC,yBAAwB,IA/InDC,CAAiBR,GA4DnB,SAA0BA,GACxB,MAAMS,EAAYT,EAAUS,UAEV,SAAdA,EACFb,UAAUM,SAASQ,sBACI,QAAdD,EACTb,UAAUM,SAASS,sBAEnBf,UAAUM,SAASU,uBAnErBC,CAAiBb,GACjBc,GAAiB/K,GAAUyH,OAyH7B,WACE,MAAMuD,EAAOlM,EAAS,iBAET,WAATkM,GACFnB,UAAUM,SAASc,mBAAkB,GAG1B,UAATD,GACFnB,UAAUM,SAASc,mBAAkB,GAhIvCC,GAEIjB,EAAUvY,eAAe,mBAyC/B,SAAwByZ,GACtB,IAAIA,GAAyC,iBAAjBA,GAAqD,kBAAjBA,EAI9D,EAAMxhB,IAAI6I,KAAK,qDAAsD2Y,OAJsB,CAC3F,MAAM9W,EAAOhH,OAAO+N,OAAO,GAAIoO,GAA2C,iBAAjB2B,EAA4BA,EAAe,IACpGniB,OAAO6gB,UAAUM,SAASiB,eAAe/W,IA3CzC+W,CAAenB,EAAUmB,gBAG3B,MAAMvT,EApGR,UAAwB,KACtBJ,EAAI,QACJ4T,IAGA,MAAMxT,EAAM,IAAIyT,IAAI7T,GAEpB,IAAK,MAAO8T,EAAOrc,KAAW7B,OAAOsV,QAAQ0I,GAC3C,GAAc,SAAVE,EAEF,IAAK,MAAMtY,KAAO/D,EAChB2I,EAAI2T,aAAajC,OAAOtW,OAErB,CAEL,MAAMkW,EAAetR,EAAI2T,aAAa/D,IAAI8D,GAEtCpC,GACFtR,EAAI2T,aAAaC,IAAIF,EAAOrC,GAAmBC,EAAcja,IAKnE,OAAO2I,EAAIJ,KA6ECiU,CAAe,CACzBjU,KAAMzO,OAAOqJ,SAASoF,KACtB4T,QAAS,CACPpF,KAAMgD,MAMV,OAHAY,UAAU8B,iBACV9B,UAAUM,SAASyB,aAAa,MAAO/T,GACvCgS,UAAUM,SAAS0B,6BAA6B3B,IACzC,EA6DT,SAASa,GAAiBe,GAcxB,OAbI,EAAMxY,cAAcwY,GACtBjC,UAAUC,IAAIxK,MAAK,KACjB,MAAM6K,EAASN,UAAUM,SACzB9c,OAAOC,KAAKwe,GAAeve,SAAQ0F,IAEjCkX,EAAOyB,aAAa3Y,EAAK8Y,OAAOD,EAAc7Y,WAKlD,EAAMtJ,IAAI6I,KAAK,kCAAmCsZ,GAG7CA,EAgET,SAASE,GAAQC,EAAa9X,GAC5B,MAAMmM,EAAOnM,EAAMrK,OAAOwW,KAGN,QAAhBA,EAAKgB,SACPhB,EAAK1E,IAAM,GAEX,EAAM5G,OAAOsL,EAAM2L,GAEnBpC,UAAUC,IAAIxK,MAAK,KACjBgB,EAAK4L,aAAaC,cAAcC,mBAAmBR,eAAeS,UAE7D/L,EAAKiB,OAASjB,EAAKE,gBACtBF,EAAKgM,cAUb,SAASC,GAASpY,GAChB,MAAMmM,EAAOnM,EAAMrK,OAAOwW,KAGtB,EAAMpP,WAAWoP,EAAKgM,UACxBhM,EAAKgM,UAQT,SAASE,GAAUrY,GAYjB,OAXAnL,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxB,MAAMU,EAAY7L,EAAMrK,OAAOkW,UAE3B,EAAM1M,cAAc0M,IACtB3S,OAAOC,KAAK0S,GAAWzS,SAAQK,IAC7BuG,EAAMrK,OAAOwW,KAAK1E,IAAI0E,KAAKsL,aAAahe,EAAMoS,EAAUpS,OAI5Dic,UAAUM,SAAS1M,QAAQ,CAACtJ,EAAMrK,OAAOwW,KAAK1E,IAAI0E,UAE7CzU,KAGT,SAAS4gB,GAAStY,GAChB,MAAMuY,EAASvY,EAAMrK,OAAOwW,KAAK1E,IAAI8Q,OAC/Ble,EAAO2F,EAAMrK,OAAO0E,KAC1Bke,EAAOxiB,MAAQsE,EAAK,GACpBke,EAAOziB,OAASuE,EAAK,GAOvB,SAAS4b,GAAcjW,GACrB,MAAM5K,EAAO,CACXqS,IAAK,IAED+Q,EAAYxY,EAAMmM,KAAKsM,YACvBC,EAAQF,EAAUG,WAAW7hB,MAAM,KACnC8hB,EAAW,qBAAqBJ,EAAUK,UAChDzjB,EAAK2B,KAAO2hB,EAAMvT,MAClB/P,EAAKqE,KAAOif,EAAMne,KAAK,KACvBnF,EAAKiF,KAAO2F,EAAM3F,MAAQ2F,EAAM3F,KAAK+F,OAASJ,EAAM3F,KAAKE,OAAS,GAClEnF,EAAKkF,WAAa0F,EAAM1F,WACxB,MAAMwe,EAAgB9Y,EAAMmM,KAAK4M,iBAAmB/Y,EAAMmM,KAAK4M,kBAE3DD,GAAiBA,EAAc1e,MACjChF,EAAKgF,IAAM0e,EAAc1e,IAAIgG,OAAS0Y,EAAc1e,IAAIG,OAAS,IAGnE,MAAM5E,EAASP,EAAKqS,IACpB9R,EAAOiS,QAAU5H,EAAM4H,QACvBjS,EAAO0E,KAAO2F,EAAM3F,KACpB1E,EAAO2E,WAAa0F,EAAM1F,WAC1B3E,EAAOsd,WAAajT,EAAMiT,WAC1Btd,EAAOqjB,YAAchZ,EAAMgZ,YAC3B,MAAMC,EAAWzkB,SAASsc,eAAe8H,GAErCK,GACFA,EAASvW,aAAa,WAAY,MAClCuW,EAASvW,aAAa,cAAe,QACrCuW,EAASvW,aAAa,OAAQ,gBAC9BuW,EAASvW,aAAa,QAAS,iBAC/B/M,EAAO4iB,OAASU,GAGhB,EAAMzjB,IAAI6I,KAAK,uCAGjB,EAAMnJ,UAAU,kBAAmBE,GAUrC,MAAM0iB,GAAc,CAIlBC,WAAY,WAiBV,OAhBAljB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxBzT,KAAK+P,IAAIsJ,GAAK,GAAGrZ,KAAK+B,WACtB/B,KAAKuV,MAAMvK,aAAa,KAAMhL,KAAK+P,IAAIsJ,IACvCrZ,KAAKwhB,cAEAxhB,KAAK6V,UAQR7V,KAAK+P,IAAI0E,KAAOuJ,UAAUyD,oBAAoBzhB,KAAK+P,IAAIuL,SAAUtb,KAAK+P,IAAIsJ,IAPtES,IAAe,EAAM3S,SAASnH,KAAK0Q,QACrC1Q,KAAK0W,iBACL1W,KAAK+P,IAAI0E,KAAOuJ,UAAUqC,WAAWrgB,KAAK+P,IAAIuL,SAAU,CAAC,EAAG,GAAItb,KAAK+P,IAAIsJ,IAAIqI,kBAAkB1hB,KAAK+P,IAAIW,QAExG1Q,KAAK+P,IAAI0E,KAAOuJ,UAAUqC,WAAWrgB,KAAK+P,IAAIuL,SAAUtb,KAAK0Q,MAAO1Q,KAAK+P,IAAIsJ,OAM5ErZ,MAET6X,UAAW,SAAU8J,GACnB,SAAIxkB,OAAO6gB,UAAU4D,cAAezkB,OAAO6gB,UAAUM,UACnDqD,EAAUA,GAAW3hB,KAAK+P,IAAI0E,KACvBuJ,UAAUM,SAASjM,MAAM,CAACsP,MAKrCjL,eAAgB,WA0Bd,OAzBAvZ,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxB,EAAM3Q,GAAG,cAAcwF,IACrB,MAAMmM,EAAOnM,EAAMrK,OAAOwW,KACpBC,EAAapM,EAAMrK,OAAOyW,WAChCmN,GAAoB,CAClB1E,IAAKzI,IAGHD,EAAKE,aAAaD,KAEhBD,EAAK1E,IAAI8Q,OACXpM,EAAK1P,KAAK,WACA/E,KAAK0V,OACfjB,EAAKgM,aAGRzgB,KAAK+U,WACR,MAAMpB,EAAUqK,UAAU8D,cAC1BtgB,OAAOC,KAAKqY,IAAapY,SAAQmD,IAC3B7E,KAAK0Q,MAAM7L,IACb8O,EAAQoO,QAAQjI,GAAYjV,GAAa7E,KAAK0Q,MAAM7L,OAGxD7E,KAAK+P,IAAIW,MAAQiD,EAAQqO,WAEpBhiB,MAMT+X,YAAa,SAAU4J,GACrB,SAAIxkB,OAAO6gB,UAAU4D,cAAezkB,OAAO6gB,UAAUM,UACnDqD,EAAUA,GAAW3hB,KAAK+P,IAAI0E,KACvBuJ,UAAUiE,aAAa,CAACN,MASnClB,QAAS,WAKP,OAJAtjB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxBzT,KAAK+E,KAAK,gBACViZ,UAAUyC,QAAQzgB,KAAK+P,IAAIsJ,OAEtBrZ,MAMTwhB,YAAa,WAqBX,OApBArkB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxB,IAAI6H,EACJ,MAAMvL,EAAMkD,EAAS,QAAU,GACzBmF,EAAOpY,KAAK+U,UAAU5H,aAAa,4BAEzC,GAAI,EAAMtE,iBAAiBuP,GACzBkD,EAAWlD,OACN,GAAI,EAAMvP,iBAAiBkH,EAAIuL,UACpCA,EAAWvL,EAAIuL,aACV,CACL,MAAM4G,EAAUnS,EAAImS,QACdC,EAAOpS,EAAIoS,KACXC,EAAOrS,EAAIqS,KACjB9G,EAAW,IAAI4G,IACf5G,GAAY,EAAMzS,iBAAiBsZ,GAAQ,IAAIA,IAAS,GACxD7G,GAAY,EAAMzS,iBAAiBuZ,GAAQ,IAAIA,IAAS,GAG1DpiB,KAAK+P,IAAIuL,SAAWA,KAEftb,MAMTsgB,YAAa,SAAUqB,GAUrB,OATAxkB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxB,MAAM1D,EAAMkD,EAAS,QAAU,IAC/B0O,EAAUA,GAAW3hB,KAAK+P,IAAI0E,MACtB4N,WAAWrE,UAAUM,UAEzBvO,EAAIyO,aAAiC,IAAnBxe,KAAK8V,WACzB6L,EAAQU,WAAWrE,UAAUU,mBAG1B1e,MAOTugB,iBAAkB,WAYhB,OAXApjB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxB,MAAM0L,EAAOnf,KAAKqU,eAAiBpB,EAAS,kBAxcpB,QA0cX,WAATkM,EACFnf,KAAK+P,IAAI0E,KAAK6N,qBAAoB,GAAM,GACtB,UAATnD,EACTnf,KAAK+P,IAAI0E,KAAK6N,qBAAoB,GAChB,UAATnD,GACTnf,KAAK+P,IAAI0E,KAAK6N,qBAAoB,MAG/BtiB,MAETiY,oBAAqB,WAanB,GAAIjY,KAAK6V,WAAa7V,KAAK+P,IAAI8Q,OAAQ,CACrC,MAAM0B,EAZR,SAA0B1B,GACxB,MAAM2B,EAAqB3B,EAAO3T,cAAcpQ,SAAS2V,cAAc,+BAEvE,OAAI+P,EACKA,EAAmBC,QAAQC,mBAElC,EAAM5kB,IAAI6I,KAAK,mEACR,GAKagc,CAAiB3iB,KAAK+P,IAAI8Q,QAG5C0B,GACF,EAAMpY,OAAOoY,GAAe,GAAM,KAChC,EAAMzkB,IAAI4I,KAAK,+BACd,KACD,EAAM5I,IAAI4I,KAAK,kDACd,QAGL,EAAM5I,IAAI6I,KAAK,0DAQnB6Z,OAAQ,SAAUmB,GAMhB,OALAxkB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxBkO,EAAUA,GAAW3hB,KAAK+P,IAAI0E,KAC9B,MAAMlC,EAAYU,EAAS,aAC3B0O,EAAQ/B,IAAI,WAAYrN,GAAwB,EAAM5G,kBAEjD3L,MAMT+f,aAAc,SAAU4B,GAWtB,OAVAxkB,OAAO6gB,UAAUC,IAAIxK,MAAK,KACxBkO,EAAUA,GAAW3hB,KAAK+P,IAAI0E,KAG1B,EAAMhN,cAAczH,KAAKmU,YAC3B3S,OAAOC,KAAKzB,KAAKmU,WAAWzS,SAAQge,IAClCiC,EAAQ5B,aAAaL,EAAO1f,KAAKmU,UAAUuL,UAI1C1f,OAsCX,SAAS6hB,GAAoBe,GACvBzlB,OAAO6gB,UAETkB,GADe,EAAMzX,cAAcmb,GAAYA,EAAWzO,GAAUyH,OAGpE,EAAM9d,IAAI6I,KAAK,2EA0BnB,IAAIoJ,GAAM,CACRuC,KAtkBF,WACE,MAAM8L,EAAYnL,EAAS,QAAU,GACrC6G,GAAc7G,EAAS,cACvB8K,KACA,EAAMjb,GAAG,YAAaqd,GAAQjN,KAAK,KAAMkN,KACzC,EAAMtd,GAAG,gBAAiB4d,IAC1B,EAAM5d,GAAG,UAAW6d,IACpB,EAAM7d,GAAG,SAAU8d,IACnB5C,UAAUC,IAAIxK,KAAK0K,GAAMjL,KAAK,KAAMkL,KA+jBpCD,SACA0E,iBAzDF,WACE,EAAM/kB,IAAI6I,KAAK,2GACfqX,UAAUC,IAAIxK,MAAK,KACjBuK,UAAUM,SAASuE,uBAuDrB7S,cAnDF,WACE,GAAI7S,OAAO6gB,WAAa7gB,OAAO6gB,UAAUM,OACvC,OAAON,UAAUM,SAAStO,iBAkD5B6R,uBACAiB,mBA/CF,WACM3lB,OAAO6gB,UACTA,UAAUC,IAAIxK,MAAK,KACjBuK,UAAUM,SAASyE,oBAGrB,EAAMjlB,IAAI6I,KAAK,8EA0CjBqc,yBAzbF,SAAkC5b,GAC3BjK,OAAO6gB,UAKP5W,EAKL4W,UAAUC,IAAIxK,MAAK,KACjBuK,UAAUM,SAASyE,eAAe3b,MALlC,EAAMtJ,IAAI6I,KAAK,wDALf,EAAM7I,IAAI6I,KAAK,8EAwbjBsc,aA7BF,WACE,SAAI9lB,OAAO6gB,YAAa7gB,OAAO6gB,UAAUkF,WA6BzCnF,WACAphB,MAvBF,WACE,MAAMmB,EAAM,EAAMA,IACZqlB,EAAOlQ,EAAS,OAEjBkQ,IAILrlB,EAAIoI,MAAM,OACVpI,EAAIiJ,eAAeoc,GACnBrlB,EAAIsI,SAkBN,SAASgd,KAwIPtmB,SAASiE,iBAAiB,qBAAsBsiB,IArI5ClmB,SAAWA,OAAO2S,OACpB3S,OAAO2S,KAAO9P,MAIlBiT,EAASX,KAAOa,EAChBF,EAASZ,MAAQA,EAEjB+Q,GAAIxd,UAAUoN,OAASC,EACvBmQ,GAAIxd,UAAU+S,MAAQA,GACtByK,GAAIxd,UAAUmK,IAAMA,GACpBqT,GAAIxd,UAAUuO,UAAYA,GAC1BiP,GAAIxd,UAAUxF,MAAQ,EAMtBgjB,GAAIxd,UAAU0M,KAAO,SAAUlJ,GAC7BA,EAAUA,GAAW,GACrBpJ,KAAKgT,OAAOV,OACZ,MAAMgR,EAAgB9hB,OAAO+N,OAAOnG,EAAS,CAC3CiV,iBAAkBjV,EAAQma,uBAsB5B,OApBAvjB,KAAKgT,OAAOsQ,GAERla,EAAQma,qBACVvjB,KAAKwjB,SAAW,CACdC,YAAY,GAGdzjB,KAAKwjB,SAiFT,WAEE,MACM1f,EAAQhH,SAAS0Q,OAAO1J,MADnB,qBAGX,IAAKA,EAEH,MAAO,CACL2f,YAAY,EACZC,cAAc,GAIlB,MAAMC,EAAgBvX,mBAAmBtI,EAAM,IAC/C,MAAO,CACL2f,YAAkE,IAAtDE,EAAcpe,QAAQ,2BAClCme,cAAqE,IAAvDC,EAAcpe,QAAQ,6BAjGpBqe,GAGd5jB,KAAKwjB,SAASC,YAChBzjB,KAAKI,MAAM5C,UAAU,qBAGnBwC,KAAKwjB,SAASE,cAChB1jB,KAAKI,MAAM5C,UAAU,uBAGvBwC,KAAKI,MAAM5C,UAAU,gBACrBwC,KAAKmU,UAAUiC,IAAIpW,KAAKgT,SAASmB,WAC1B0P,QAAQC,QAAQ9jB,KAAK+jB,gBAO9BX,GAAIxd,UAAUoe,gBAAkB,SAAUtmB,GACxCsC,KAAKmU,UAAUiC,IAAI1Y,GACnBsC,KAAK+P,IAAI8R,oBAAoB7hB,KAAKmU,UAAUyH,QAG9CwH,GAAIxd,UAAUme,YAAc,WAiB1B,OAhBA/jB,KAAK2Y,MAAMrG,OAEPtS,KAAKwjB,SAASE,eAChB1jB,KAAKgT,OAAO,CACVqL,iBAAiB,IAEnBre,KAAKmU,UAAUiC,IAAI,CACjB6N,GAAI,OAIRjkB,KAAK+P,IAAIuC,OACTtS,KAAKI,MAAM0C,GAAG,QAAS9C,KAAKrD,MAAMuW,KAAKlT,OACvCA,KAAKkkB,eAAgB,EACrBlkB,KAAKI,MAAM5C,UAAU,cAAewC,MAkEpClD,SAAS6E,oBAAoB,qBAAsB0hB,IAhE5CrjB,MAGTojB,GAAIxd,UAAUjJ,MAAQ,WACpB,IAAIib,GAAS,EAETtR,aAAaC,QAAQ,QACvBqR,GAAS,EAETtR,aAAa6d,QAAQ,QAAQ,GAG/BnkB,KAAK+P,IAAIpT,QACTqD,KAAK2Y,MAAMhc,QACXqD,KAAKmU,UAAUxX,QAEXib,GACFtR,aAAa8d,WAAW,SAI5BhB,GAAIxd,UAAUye,QAAU,WACtBrkB,KAAKI,MAAMtC,IAAI6I,KAAK,sFACpB3G,KAAKI,MAAMtC,IAAI,kBAAkBkC,KAAKI,MAAMsN,iBAG9C0V,GAAIxd,UAAU8H,WAAa,WACzB,OAAO1N,KAAKI,MAAMsN,cAGpB,MAAM2V,GAAU,WACd,OAAOiB,GAAIhS,OAAOiS,MAAK,KACPzW,MAAM6E,KAAK7V,SAAS8V,iBAAiB,8BAC7ClR,QAAQ4iB,GAAI3L,MAAMQ,SAASjG,KAAKoR,GAAI3L,YAI9CyK,GAAIxd,UAAUyd,QAAUA,GA8BxB,MAAMiB,GAAM,IAAIlB,I,oBCn9FhB,IAAIoB,EAAmBxkB,MAAQA,KAAKwkB,iBAAoB,SAAUC,GAC9D,OAAQA,GAAOA,EAAIC,WAAcD,EAAM,CAAE,QAAWA,IAExDjjB,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtD,IAAMwd,EAAgBC,EAAQ,KACxBC,EAASP,EAAgBM,EAAQ,MACjCE,EAA0BF,EAAQ,KAClCG,EAA2BT,EAAgBM,EAAQ,MACpBA,EAAQ,KAChBI,0BAC7BL,EAAcM,kBAAiB,WAC3BhoB,OAAOioB,UAAYjoB,OAAOioB,WAAa,GACvCJ,EAAwBK,0BAAyB,GACjDJ,EAAwB,UACxBF,EAAM,c,YCdVvjB,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtDud,EAAQO,iBAAmBP,EAAQU,qBAAkB,EAWrDV,EAAQU,gBAVR,SAAyBvB,GACO,YAAxBjnB,SAASoO,WACT6Y,IAGAjnB,SAASiE,iBAAiB,oBAAoB,WAC1CgjB,QAeZa,EAAQO,iBAVR,SAA0BpB,GACK,YAAvBjnB,SAASoO,WACT6Y,IAGA5mB,OAAO4D,iBAAiB,QAAQ,WAC5BgjB,S,oBCnBZ,IAAIS,EAAmBxkB,MAAQA,KAAKwkB,iBAAoB,SAAUC,GAC9D,OAAQA,GAAOA,EAAIC,WAAcD,EAAM,CAAE,QAAWA,IAExDjjB,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IAEtD,IAAMke,EAAqBf,EAAgBM,EAAQ,MAKnDF,EAAQY,QAJR,WAEID,EAAkB,QAASlC,Y,cCR/B7hB,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtDud,EAAQa,gBAAkBb,EAAQc,mBAAqBd,EAAQe,yBAAsB,EACrF,IAAMC,EAAUd,EAAQ,KAClBe,EAA+Bf,EAAQ,KACvCgB,EAAahB,EAAQ,KAsD3B,SAASiB,IACL,QAAK5oB,OAAOioB,WAELjoB,OAAOioB,UAAUY,MAAK,SAAAC,GAAK,QAAMA,EAAMC,WA1ClDtB,EAAQY,QAdR,WACI,IAAMW,EAAavB,EAAQe,oBAAoB,sBAAwB,GAClEQ,EAAWhS,YACZgS,EAAWhS,UAAY,IAuD/B,SAAyBgS,GACrBhpB,OAAOipB,eAAiBjpB,OAAOipB,gBAAmBnpB,KAAK4R,MAAsB,KAAhB5R,KAAKkL,UAClEge,EAAWhS,UAAUiS,eAAiBjpB,OAAOipB,eAxD7CC,CAAgBF,GA0DpB,SAAqBA,GACjB,IAAMG,EAAwB1B,EAAQc,mBAAmBE,EAAQW,UAAU,sBACvED,aAAqE,EAASA,EAAsBjN,MACpG8M,EAAWhS,UAAUqS,OAASF,aAAqE,EAASA,EAAsBjN,KAClIiN,aAAqE,EAASA,EAAsBjnB,QACpG8mB,EAAWhS,UAAUsS,SAA0C,cAA/BH,EAAsBjnB,KAAuB,KAAO,MACpF8mB,EAAWhS,UAAUuS,SAAWJ,aAAqE,EAASA,EAAsBjnB,MAEpIwmB,EAA6Bc,kCAC7BR,EAAWhS,UAAY3S,OAAO+N,OAAO/N,OAAO+N,OAAO,GAAI4W,EAAWhS,WAAahX,OAAOypB,uBAAyB,KAlEnHC,CAAYV,GAqEhB,SAAyBA,GACAL,EAAWgB,oBAE5BX,EAAWhS,UAAU4S,aAAejB,EAAWgB,mBAvEnDE,CAAgBb,GAsFpB,SAAwBA,GAChBA,EAAWhS,UAAU8S,KAtDpB9pB,OAAOioB,WAELjoB,OAAOioB,UAAUY,MAAK,SAAAC,GAAW,IAAIiB,EAAIC,EAAI,MAAmL,aAAnD,QAAvHA,EAAyE,QAAnED,EAAKjB,aAAqC,EAASA,EAAMmB,YAAyB,IAAPF,OAAgB,EAASA,EAAGxpB,YAAyB,IAAPypB,OAAgB,EAASA,EAAGE,iBAuDpNlB,EAAWhS,UAAU8S,GAAK,OApDzB9pB,OAAOioB,WAELjoB,OAAOioB,UAAUY,MAAK,SAAAC,GAAW,IAAIiB,EAAIC,EAAI,MAAmL,aAAnD,QAAvHA,EAAyE,QAAnED,EAAKjB,aAAqC,EAASA,EAAMmB,YAAyB,IAAPF,OAAgB,EAASA,EAAGxpB,YAAyB,IAAPypB,OAAgB,EAASA,EAAGE,iBAoDpNlB,EAAWhS,UAAU8S,GAAK,OAjDzB9pB,OAAOioB,WAELjoB,OAAOioB,UAAUY,MAAK,SAAAC,GAAW,IAAIiB,EAAIC,EAAI,MAAmL,gBAAnD,QAAvHA,EAAyE,QAAnED,EAAKjB,aAAqC,EAASA,EAAMmB,YAAyB,IAAPF,OAAgB,EAASA,EAAGxpB,YAAyB,IAAPypB,OAAgB,EAASA,EAAGE,iBAiDpNlB,EAAWhS,UAAU8S,GAAK,OAC1BlB,MACAI,EAAWhS,UAAU8S,GAAK,QA/F9BK,CAAenB,GAiGnB,SAA0BA,GACtBA,EAAWhS,UAAUgO,KAAOgE,EAAWpW,IAAIoS,KAjG3CoF,CAAiBpB,GACbJ,KAsER,SAAwBI,GACpB,IAAIe,EAAIC,EAAIK,EACN9pB,EAAOP,OAAOioB,UAAU5K,MAAK,SAAAxT,GAAI,QAAMA,EAAKkf,WAClD,GAAKxoB,GAASA,EAAKwoB,SAAYxoB,EAAKwoB,QAAQxoB,KAA5C,CAHgC,IAKxBwoB,EAAYxoB,EAAZwoB,SACHC,EAAWhS,UAAUsT,cAA0F,QAAzEP,EAAKhB,aAAyC,EAASA,EAAQxoB,YAAyB,IAAPwpB,OAAgB,EAASA,EAAGQ,oBACpJvB,EAAWhS,UAAUsT,YAAwF,QAAzEN,EAAKjB,aAAyC,EAASA,EAAQxoB,YAAyB,IAAPypB,OAAgB,EAASA,EAAGO,mBAEhJvB,EAAWhS,UAAUwT,OAAmF,QAAzEH,EAAKtB,aAAyC,EAASA,EAAQxoB,YAAyB,IAAP8pB,OAAgB,EAASA,EAAGI,cAC7IzB,EAAWhS,UAAUwT,KAAOzB,EAAQxoB,KAAKkqB,aA/EzCC,CAAe1B,GAEnBvB,EAAQa,gBAAgBU,IAO5BvB,EAAQe,oBAJoB,SAACmC,GACzB,IAAMpd,EAAO5N,SAASsc,eAAe0O,GACrC,OAAO3jB,KAAKG,MAAM8H,mBAAmB1B,aAAmC,EAASA,EAAKoI,aAa1F8R,EAAQc,mBAVmB,SAAC5hB,GACxB,IAAI0J,OAASvH,EACb,IACIuH,EAAS1J,EAAQK,KAAKG,MAAMnH,OAAO4qB,KAAKjkB,SAAUmC,EAEtD,MAAO1B,GACH1G,QAAQ+I,MAAM,2BAA4B9C,GAE9C,OAAO0J,GASXoX,EAAQa,gBANgB,SAACU,GACrB,IAAM6B,EAAoBlrB,SAASsc,eAAe,qBAC9C4O,IACAA,EAAkBlV,UAAY3O,KAAKC,UAAU+hB,M,oBCvCrD,IAAI8B,EAAUjoB,MAAQA,KAAKioB,QAAW,SAAUlP,EAAGxU,GAC/C,IAAI2jB,EAAI,GACR,IAAK,IAAIC,KAAKpP,EAAOvX,OAAOoE,UAAUC,eAAeJ,KAAKsT,EAAGoP,IAAM5jB,EAAEgB,QAAQ4iB,GAAK,IAC9ED,EAAEC,GAAKpP,EAAEoP,IACb,GAAS,MAALpP,GAAqD,mBAAjCvX,OAAO4mB,sBACtB,KAAI1e,EAAI,EAAb,IAAgBye,EAAI3mB,OAAO4mB,sBAAsBrP,GAAIrP,EAAIye,EAAEzf,OAAQgB,IAC3DnF,EAAEgB,QAAQ4iB,EAAEze,IAAM,GAAKlI,OAAOoE,UAAUyiB,qBAAqB5iB,KAAKsT,EAAGoP,EAAEze,MACvEwe,EAAEC,EAAEze,IAAMqP,EAAEoP,EAAEze,KAE1B,OAAOwe,GAEX1mB,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtDud,EAAQM,wBAA0BN,EAAQ+B,mCAAgC,EAC1E,IAAMf,EAAUd,EAAQ,KAClBgB,EAAahB,EAAQ,KAErBwD,EAAwB,wBACxBC,EAAgB,CAAC,MAAO,MAAO,KAAM,MAAO,KAAM,OAKxD3D,EAAQ+B,8BAJ8B,WAClC,IAAM6B,EAAO1C,EAAW2C,kBACxB,QAAOD,GAAOD,EAAchlB,SAASilB,IAGzC,IAIME,EAAgB,SAACxB,GACOA,EAApB7C,QAAoB6C,EAAXyB,OADW,IACIC,EAAkBX,EAAOf,EAAI,CAAC,UAAW,WACvE,OAAO/pB,OAAOypB,sBAAwBgC,GA+B1ChE,EAAQM,wBA7BwB,WAC5B,GAAKN,EAAQ+B,kCARPkC,EAAuBjD,EAAQW,UAAU,gBACiE,IAAjFna,mBAAmByc,GAAsBtjB,QAAQ,2BAOhF,CAT4B,IACtBsjB,EAUAnrB,EAAOkoB,EAAQkD,sBAAsBR,GAG3C,GAFI5qB,GACAgrB,EAAchrB,KACdA,GAtBgB,QAsBRA,EAAK2mB,UAA+B,IAAI9X,MAAOwc,UAAYrrB,EAAKirB,cAEvD1iB,IAAjB9I,OAAO6rB,OAAwBlD,EAAWgB,kBAA9C,CAEA,IAAImC,EAAW,2BAGkB,qCAA7B9rB,OAAOqJ,SAAS0iB,WAChBD,EAAW,gEAEfD,MAAMC,EAJiB,CAAEE,YAAa,YAKjC5E,MAAK,SAAApH,GAAG,OAAIA,EAAIiM,UAChB7E,MAAK,SAAA8E,GAEDA,IAAY7nB,OAAOC,KAAK4nB,GAAUC,OAAM,SAAAliB,GAAG,OAAKiiB,EAASjiB,QAE9DiiB,EAAShF,QAtCO,MAwChBuB,EAAQ2D,6BAA6BjB,EAAuBe,EADrC,QAEvBX,EAAcW,OATlB,OAWW,SAAA9kB,GAAC,OAAI1G,QAAQ8I,KAAK,sCAAuCpC,U,wHC1DxE/C,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtDud,EAAQkC,gBAAkBlC,EAAQ6D,gBAAkB7D,EAAQ4E,kBAAe,EAC3E,IAmBIhB,EAnBE5C,EAAUd,EAAQ,KAClB2E,EAAS,CACXC,IAAK,+BACLC,IAAK,sBACLC,IAAK,gBACLC,GAAI,2BACJC,IAAK,aACLC,GAAI,uBACJC,GAAI,iBAYR,SAASvB,IACL,IAAIvB,EAIJ,OAHKsB,IACDA,EAAwG,QAAhGtB,EAAK1lB,OAAOsV,QAAQ2S,GAAQjP,MAAK,gB,IAAA,G,EAAA,E,4CAAA,I,owBAAKnT,GAAL,kBAAgBlK,OAAOqJ,SAAS0iB,SAASe,SAAS5iB,aAA4B,IAAP6f,OAAgB,EAASA,EAAG,IAEzIsB,EAfX5D,EAAQ4E,aAAe,CACnBE,IAAK,gBACLC,IAAK,gBACLC,IAAK,gBACLC,GAAI,gBACJC,IAAK,gBACLC,GAAI,gBACJC,GAAI,iBAURpF,EAAQ6D,gBAAkBA,EAgB1B7D,EAAQkC,gBAXgB,WACpB,IAJMoD,EAIAC,GAJAD,EAAYzB,KACC7D,EAAQ4E,aAAaU,GAAa,KAIrD,IAAKC,EACD,MAAO,GAEX,IAAMC,EAAqBxE,EAAQW,UAAU4D,GAC7C,OAAKC,EAGEA,EAAmBhrB,MAAM,KAAK,GAF1B,K,YCzCfoC,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtDud,EAAQS,8BAA2B,EAEnC,IAGMgF,EAAgB,iBAClBC,EAAmB,GA0BvB,SAASC,IAKLD,EAAiB5oB,SAAQ,SAAC+S,GACtB,IAAMwG,EALU,SAACxG,GAAD,OAAU,WAC1BA,EAAK1P,KAAK,gBACV5H,OAAO6gB,UAAUyC,QAAQhM,EAAK1E,IAAIsJ,KAGvBmR,CAAY/V,GACnBA,EAAKgW,cACLttB,OAAO6gB,UAAUC,IAAIxK,KAAKwH,GAE1BxG,EAAKgM,QAAU,kBAAMtjB,OAAO6gB,UAAUC,IAAIxK,KAAKwH,OAG3D,IAAMyP,EAA4BxqB,WAAWqqB,EAzCtB,KA0CvB,SAASI,IACL1qB,aAAayqB,GACbvtB,OAAOytB,SAASC,qBAChBN,IAEJ,IAAMO,EAAwB,SAACxiB,GAC3B,IAAI4e,EACJ,GAA0E,QAArEA,EAAK5e,aAAqC,EAASA,EAAMrK,cAA2B,IAAPipB,OAAgB,EAASA,EAAGzS,KAA9G,CACI,IAAMA,EAAOnM,EAAMrK,OAAOwW,KAC1B6V,EAAiB7W,KAAKgB,GAClBA,EAAKgM,UACLhM,EAAKgM,QAAU,WACXhM,EAAKgW,eAAgB,IAOjCttB,OAAO6gB,UAAUC,IAAIxK,MAAK,WACtB,IACMsX,EADW5tB,OAAO6gB,UAAUM,SAAS0M,WACdvnB,KAAI,SAACgR,GAC9B,IAAM/D,EAAQ+D,EAAKwW,WAAWxnB,KAAI,SAACd,GAC/B,OAAIA,EAAKtF,UAAYsF,EAAK/F,UACf,CAAC+F,EAAKtF,WAAYsF,EAAK/F,aAEvB,CAAC,EAAG,MAEnB,MAAO,CACHsuB,SAAUzW,EAAK0W,mBACfxoB,KAAM+N,EACN0a,WAAY3W,EAAK4W,oBAGzBluB,OAAOytB,SAASU,MAAM7X,KAAK,CACvB8X,QAASR,EACTS,YAAab,SAQzB/F,EAAQS,yBAJyB,SAACzT,IA/ElC,SAAyBA,GAKrB,GAJAzU,OAAOytB,SAAWztB,OAAOytB,UAAY,GACrCztB,OAAOytB,SAASU,MAAQnuB,OAAOytB,SAASU,OAAS,GACjDnuB,OAAOytB,SAASa,MAPD,UAQQ3uB,SAASsc,eAAeiR,GAC/C,CAGA,IAAMxX,EAAS/V,SAAS2N,cAAc,UACtCoI,EAAO6C,OAAQ,EACf7C,EAAOxJ,IAfY,8CAgBnBwJ,EAAOwG,GAAKgR,EACZvtB,SAAS4uB,KAAKC,YAAY9Y,GAC1BjB,IAGAzU,OAAOyuB,qBAAuBzuB,OAAOyuB,sBAAwB,GAC7DzuB,OAAOyuB,qBAAqBC,iBAAmB,CAC3CC,SAAS,EACTC,aAAc,OAElB5uB,OAAOyuB,qBAAqBI,YAAc,CACtCtpB,IAAK,CAAC,QAAS,gBAAiB,cAAe,gBA0DnDupB,CAAgBra,GAChB9U,SAASiE,iBAAiB,iBAAkB+pB,K,YCzFhDtpB,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,IACtDud,EAAQ2B,UAAY3B,EAAQsH,cAAgBtH,EAAQkE,sBAAwBlE,EAAQ2E,6BAA+B3E,EAAQuH,kBAAoBvH,EAAQwH,iBAAmBxH,EAAQyH,gBAAkBzH,EAAQplB,SAAWolB,EAAQ0H,aAAU,EAYzO1H,EAAQ0H,QAPQ,SAACC,GAAD,OAAa,IAAI1I,SAAQ,SAACC,EAAS0I,GAC/CtsB,YAAW,WACP,GAAIqsB,IACA,OAAOzI,IACXc,EAAQ0H,QAAQC,GAAShI,KAAKT,KAC/B,QAaPc,EAAQplB,SAPR,SAAkByb,GAAc,IACxBwR,EADcC,EAAU,uDAAL,IAEvB,OAAO,WAAmB,kCAAN9sB,EAAM,yBAANA,EAAM,gBACtBK,aAAawsB,GACbA,EAAYvsB,YAAW,kBAAM+a,EAAGlb,MAAM,EAAMH,KAAO8sB,KAa3D9H,EAAQyH,gBALR,WACI,OAAOlvB,OAAOC,aACVN,SAASC,gBAAgBC,cACzBF,SAASc,KAAKZ,cAAgB,GAWtC4nB,EAAQwH,iBALR,WACI,OAAOjvB,OAAO0B,aACV/B,SAASc,KAAKuD,WACdrE,SAASC,gBAAgBoE,WAAa,GAS9CyjB,EAAQuH,kBAHR,WACI,OAAOlvB,KAAKC,IAAIJ,SAASc,KAAKW,cAAgB,EAAGzB,SAASC,gBAAgBwB,cAAgB,EAAGzB,SAASc,KAAK+uB,cAAgB,EAAG7vB,SAASC,gBAAgB4vB,cAAgB,EAAG7vB,SAASc,KAAKZ,cAAgB,EAAGF,SAASC,gBAAgBC,cAAgB,IAUxP4nB,EAAQ2E,6BAH6B,SAACniB,EAAK1J,EAAMkvB,GAC7CtmB,aAAa6d,QAAQ/c,EAAKjD,KAAKC,UAAU5C,OAAO+N,OAAO/N,OAAO+N,OAAO,GAAI7R,GAAO,CAAEirB,QAAQ,IAAIpc,MAAOwc,UAAY6D,OAUrHhI,EAAQkE,sBAJsB,SAAC1hB,GAC3B,IAAMJ,EAAOV,aAAaC,QAAQa,GAClC,OAAOJ,EAAO4d,EAAQsH,cAAcllB,GAAQ,MAchD4d,EAAQsH,cARc,SAACpjB,GACnB,IACI,OAAO3E,KAAKG,MAAMwE,GAEtB,MAAOvE,GACH,OAAO,OASfqgB,EAAQ2B,UALU,SAACxkB,GACf,IACM+B,EADYhH,SAAS0Q,OACH1J,MAAM,IAAIoI,OAAO,QAAUnK,EAAO,aAC1D,OAAO+B,EAAQA,EAAM,GAAK,QClF1B+oB,EAA2B,GAG/B,SAASC,EAAoBC,GAE5B,GAAGF,EAAyBE,GAC3B,OAAOF,EAAyBE,GAAUnI,QAG3C,IAAIoI,EAASH,EAAyBE,GAAY,CAGjDnI,QAAS,IAOV,OAHAqI,EAAoBF,GAAUtnB,KAAKunB,EAAOpI,QAASoI,EAAQA,EAAOpI,QAASkI,GAGpEE,EAAOpI,QCnBfkI,EAAoBI,EAAI,CAACtI,EAASuI,KACjC,IAAI,IAAI/lB,KAAO+lB,EACXL,EAAoBM,EAAED,EAAY/lB,KAAS0lB,EAAoBM,EAAExI,EAASxd,IAC5E5F,OAAOmjB,eAAeC,EAASxd,EAAK,CAAEimB,YAAY,EAAMzR,IAAKuR,EAAW/lB,MCJ3E0lB,EAAoBM,EAAI,CAAC9lB,EAAKwR,IAAStX,OAAOoE,UAAUC,eAAeJ,KAAK6B,EAAKwR,GCCjFgU,EAAoBQ,EAAK1I,IACH,oBAAX2I,QAA0BA,OAAOC,aAC1ChsB,OAAOmjB,eAAeC,EAAS2I,OAAOC,YAAa,CAAEnmB,MAAO,WAE7D7F,OAAOmjB,eAAeC,EAAS,aAAc,CAAEvd,OAAO,KCFvDylB,EAAoB,M","file":"client-bundles/oAds.js","sourcesContent":["import * as Utils from '@financial-times/o-utils';\n\nlet debug;\n\n/**\n *\n * @param {string} eventType the name of the event\n * @param {object} data the payload of the event\n * @param {EventTarget} target the target of the event\n */\nfunction broadcast(eventType, data, target) {\n\ttarget = target || document.body;\n\n\tif (debug) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log('o-viewport', eventType, data);\n\t}\n\n\ttarget.dispatchEvent(\n\t\tnew CustomEvent('oViewport.' + eventType, {\n\t\t\tdetail: data,\n\t\t\tbubbles: true,\n\t\t})\n\t);\n}\n\n/**\n * Get the viewport height.\n *\n * @param {boolean} ignoreScrollbars [false] - set to true to discount scrollbar height.\n * @returns {number} viewport height\n */\nfunction getHeight(ignoreScrollbars) {\n\treturn ignoreScrollbars\n\t\t? document.documentElement.clientHeight\n\t\t: Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n}\n\n/**\n * Get the viewport width.\n *\n * @param {boolean} ignoreScrollbars [false] - set to true to discount scrollbar width\n * @returns {number} viewport width\n */\nfunction getWidth(ignoreScrollbars) {\n\treturn ignoreScrollbars\n\t\t? document.documentElement.clientWidth\n\t\t: Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n}\n\n/**\n * Viewport size.\n *\n * @typedef {object} Size\n * @property {number} height viewport height\n * @property {number} width viewport width\n */\n\n/**\n * Get the viewport width and height.\n *\n * @param {boolean} ignoreScrollbars [false] - set to true to discount scrollbar width/height.\n * @returns {Size} viewport width and height object\n */\nfunction getSize(ignoreScrollbars) {\n\treturn {\n\t\theight: getHeight(ignoreScrollbars),\n\t\twidth: getWidth(ignoreScrollbars),\n\t};\n}\n\n/**\n * Scroll position.\n *\n * @typedef {object} ScrollPosition\n * @property {number} height - `document.body.scrollHeight`\n * @property {number} width - `document.body.scrollWidth`\n * @property {number} left - `window.pageXOffset || window.scrollX`\n * @property {number} top - `window.pageYOffset || window.scrollY`\n */\n\n/**\n * @returns {ScrollPosition} current scroll info\n */\nfunction getScrollPosition() {\n\treturn {\n\t\theight: document.body.scrollHeight,\n\t\twidth: document.body.scrollWidth,\n\t\tleft: window.pageXOffset || window.scrollX,\n\t\ttop: window.pageYOffset || window.scrollY,\n\t};\n}\n\n/**\n * @returns {string} - 'portrait' or 'landscape'\n */\nfunction getOrientation() {\n\tconst orientation = window.screen.orientation;\n\tif (orientation) {\n\t\treturn typeof orientation === 'string'\n\t\t\t? orientation.split('-')[0]\n\t\t\t: orientation.type.split('-')[0];\n\t} else if (window.matchMedia) {\n\t\treturn window.matchMedia('(orientation: portrait)').matches\n\t\t\t? 'portrait'\n\t\t\t: 'landscape';\n\t} else {\n\t\treturn getHeight() >= getWidth() ? 'portrait' : 'landscape';\n\t}\n}\n\n/**\n * @returns {boolean} - true if the viewport is visible\n */\nfunction getVisibility() {\n\treturn document.hidden;\n}\n\nexport default {\n\tdebug: function () {\n\t\tdebug = true;\n\t},\n\tbroadcast,\n\tgetWidth,\n\tgetHeight,\n\tgetSize,\n\tgetScrollPosition,\n\tgetVisibility,\n\tgetOrientation,\n\tdebounce: Utils.debounce,\n\tthrottle: Utils.throttle,\n};\n","/**\n*\n* Debounces function so it is only called after n milliseconds\n* without it not being called\n*\n* @example\n* Utils.debounce(myFunction() {}, 100);\n*\n* @param {Function} func - Function to be debounced\n* @param {number} wait - Time in miliseconds\n*\n* @returns {Function} - Debounced function\n*/\nfunction debounce(func, wait) {\n\tlet timeout;\n\treturn function() {\n\t\tconst args = arguments;\n\t\tconst later = () => {\n\t\t\ttimeout = null;\n\t\t\tfunc.apply(this, args);\n\t\t};\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(later, wait);\n\t};\n}\n\n/**\n*\n* Throttle function so it is only called once every n milliseconds\n*\n* @example\n* Utils.throttle(myFunction() {}, 100);\n*\n* @param {Function} func - Function to be throttled\n* @param {number} wait - Time in miliseconds\n*\n* @returns {Function} - Throttled function\n*/\nfunction throttle(func, wait) {\n\tlet timeout;\n\treturn function() {\n\t\tif (timeout) {\n\t\t\treturn;\n\t\t}\n\t\tconst args = arguments;\n\t\tconst later = () => {\n\t\t\ttimeout = null;\n\t\t\tfunc.apply(this, args);\n\t\t};\n\n\t\ttimeout = setTimeout(later, wait);\n\t};\n}\n\nexport {\n\tdebounce,\n\tthrottle\n};\n","import utils from './src/utils.js';\n\nconst throttle = utils.throttle;\nconst debounce = utils.debounce;\n\nconst listeners = {};\nconst intervals = {\n\tresize: 100,\n\torientation: 100,\n\tvisibility: 100,\n\tscroll: 100\n};\n\n/**\n *\n * @param {string} eventType - The type of event to throttle for this duration.\n * @param {number} interval - The duration to throttle in ms.\n * @returns {void}\n * @example\n * \t // throttle for different events at different durations\n * setThrottleInterval('scroll', 100)\n * setThrottleInterval('resize', 300)\n * setThrottleInterval('orientation', 30)\n * setThrottleInterval('visibility', 30)\n * \t\t// throttle all events at 30ms\n * setThrottleInterval(30);\n */\nfunction setThrottleInterval(eventType, interval) {\n\tif (typeof arguments[0] === 'number') {\n\t\tsetThrottleInterval('scroll', arguments[0]);\n\t\tsetThrottleInterval('resize', arguments[1]);\n\t\tsetThrottleInterval('orientation', arguments[2]);\n\t\tsetThrottleInterval('visibility', arguments[3]);\n\t} else if (interval) {\n\t\tintervals[eventType] = interval;\n\t}\n}\n\n/**\n * @access private\n */\nfunction listenToResize() {\n\tif (listeners.resize) {\n\t\treturn;\n\t}\n\tconst eventType = 'resize';\n\tconst handler = debounce(function(ev) {\n\t\tutils.broadcast('resize', {\n\t\t\tviewport: utils.getSize(),\n\t\t\toriginalEvent: ev\n\t\t});\n\t}, intervals.resize);\n\n\n\twindow.addEventListener(eventType, handler);\n\tlisteners.resize = {\n\t\teventType: eventType,\n\t\thandler: handler\n\t};\n}\n\n/**\n * @access private\n */\nfunction listenToOrientation() {\n\n\tif (listeners.orientation) {\n\t\treturn;\n\t}\n\n\tconst eventType = 'orientationchange';\n\tconst handler = debounce(function(ev) {\n\t\tutils.broadcast('orientation', {\n\t\t\tviewport: utils.getSize(),\n\t\t\torientation: utils.getOrientation(),\n\t\t\toriginalEvent: ev\n\t\t});\n\t}, intervals.orientation);\n\n\twindow.addEventListener(eventType, handler);\n\tlisteners.orientation = {\n\t\teventType: eventType,\n\t\thandler: handler\n\t};\n}\n\n/**\n * @access private\n */\nfunction listenToVisibility() {\n\n\tif (listeners.visibility) {\n\t\treturn;\n\t}\n\n\tconst eventType = 'visibilitychange';\n\tconst handler = debounce(function(ev) {\n\t\tutils.broadcast('visibility', {\n\t\t\thidden: utils.getVisibility(),\n\t\t\toriginalEvent: ev\n\t\t});\n\t}, intervals.visibility);\n\n\twindow.addEventListener(eventType, handler);\n\n\tlisteners.visibility = {\n\t\teventType: eventType,\n\t\thandler: handler\n\t};\n}\n\n/**\n * @access private\n */\nfunction listenToScroll() {\n\n\tif (listeners.scroll) {\n\t\treturn;\n\t}\n\n\tconst eventType = 'scroll';\n\tconst handler = throttle(function(ev) {\n\t\tconst scrollPos = utils.getScrollPosition();\n\t\tutils.broadcast('scroll', {\n\t\t\tviewport: utils.getSize(),\n\t\t\tscrollHeight: scrollPos.height,\n\t\t\tscrollLeft: scrollPos.left,\n\t\t\tscrollTop: scrollPos.top,\n\t\t\tscrollWidth: scrollPos.width,\n\t\t\toriginalEvent: ev\n\t\t});\n\t}, intervals.scroll);\n\n\twindow.addEventListener(eventType, handler);\n\tlisteners.scroll = {\n\t\teventType: eventType,\n\t\thandler: handler\n\t};\n}\n\n/**\n * Start listening for an event(s).\n *\n * @param {string} eventType - The event to start listening for. One of `resize`, `scroll`, `orientation`, `visibility` or `all`.\n * @example\n * \t\t// Start listening for all events.\n * \t\toViewport.listenTo('all');\n *\n * \t\t// It is now possible to listen for debounce o-viewport events such as `oViewport.orientation`.\n * document.body.addEventListener('oViewport.orientation', function(event) {\n * \tconsole.log(event.type); // oViewport.orientation\n * });\n */\nfunction listenTo(eventType) {\n\tif (eventType === 'resize' || eventType === 'all') {\n\t\tlistenToResize();\n\t}\n\n\tif (eventType === 'scroll' || eventType === 'all') {\n\t\tlistenToScroll();\n\t}\n\n\tif (eventType === 'orientation' || eventType === 'all') {\n\t\tlistenToOrientation();\n\t}\n\n\tif (eventType === 'visibility' || eventType === 'all') {\n\t\tlistenToVisibility();\n\t}\n}\n\n/**\n * Stop listening for an event(s).\n *\n * @param {string} eventType - The event to stop listening for. One of `resize`, `scroll`, `orientation`, `visibility` or `all`.\n * @example\n * \t\t// Start listening for all events.\n * \t\toViewport.listenTo('all');\n * \t\t// We're done. Stop listening for all events.\n * \t\toViewport.stopListeningTo('all');\n */\nfunction stopListeningTo(eventType) {\n\tif (eventType === 'all') {\n\t\tObject.keys(listeners).forEach(stopListeningTo);\n\t} else if (listeners[eventType]) {\n\t\twindow.removeEventListener(listeners[eventType].eventType, listeners[eventType].handler);\n\t\tdelete listeners[eventType];\n\t}\n}\n\nexport default {\n\tdebug: function () {\n\t\tutils.debug();\n\t},\n\tlistenTo,\n\tstopListeningTo,\n\tsetThrottleInterval,\n\tgetOrientation: utils.getOrientation,\n\tgetSize: utils.getSize,\n\tgetScrollPosition: utils.getScrollPosition,\n\tgetVisibility: utils.getVisibility\n};\n","import oViewport from '@financial-times/o-viewport';\n\n/**\n * Utility methods for o-ads events. Methods defined here are added to the utils object not the utils.event object.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils/events\n * @see utils\n */\n// Creates a timestamp in the browser's performance entry buffer\n// for later use\nconst perfMark = name => {\n /* istanbul ignore next */\n const performance = window.LUX || window.performance || window.msPerformance || window.webkitPerformance || window.mozPerformance;\n\n if (performance && performance.mark) {\n performance.clearMarks(name);\n performance.mark(name);\n }\n}; // Creates a suffix for an event's performance mark based on some of the attributes on\n// the event payload which help identify unequivocally the slot that originated the event\n\nfunction buildPerfmarkSuffix(eventDetailsObj) {\n let suffix = \"\";\n\n if (eventDetailsObj && typeof eventDetailsObj === \"object\" && \"pos\" in eventDetailsObj && \"name\" in eventDetailsObj) {\n suffix = \"__\" + [eventDetailsObj.pos, eventDetailsObj.name, eventDetailsObj.size, eventDetailsObj.creativeId].join(\"__\");\n }\n\n return suffix;\n}\n/**\n * Broadscasts an o-ads event\n * @param {string} name The name of the event\n * @param {object} data The data to send as event detail\n * @param {HTMLElement} target The element to attach the event listener to\n */\n\nfunction broadcast(eventName, data, target) {\n /* istanbul ignore next: ignore the final fallback as hard trigger */\n target = target || document.body || document.documentElement;\n eventName = `oAds.${eventName}`;\n const opts = {\n bubbles: true,\n cancelable: true,\n detail: data\n };\n const isSlotEvent = typeof data === \"object\" && \"pos\" in data;\n const evDetails = isSlotEvent ? {\n pos: data.pos,\n name: data.name,\n size: data.size && data.size.length ? data.size.toString() : \"\",\n creativeId: data.creativeId\n } : {};\n const suffix = buildPerfmarkSuffix(evDetails);\n const markName = eventName + suffix;\n perfMark(markName);\n target.dispatchEvent(new CustomEvent(eventName, opts));\n}\n/**\n * Sets an event listener for an oAds event\n * @param {string} name The name of the event\n * @param {EventListenerOrEventListenerObject} callback The function to execute on the event\n * @param {HTMLElement} [target] The element to attach the event listener to\n */\n\nfunction on(name, callback, target) {\n name = `oAds.${name}`;\n /* istanbul ignore next: ignore the final fallback as hard trigger */\n\n target = target || document.body || document.documentElement;\n target.addEventListener(name, callback);\n}\n/**\n * Removes an event listener for an oAds event\n * @param {string} name The name of the event\n * @param {function} callback The function on the event to be removed\n * @param {HTMLElement} target The element the event listener is attached to\n */\n\nfunction off(name, callback, target) {\n name = `oAds.${name}`;\n /* istanbul ignore next: ignore the final fallback as hard trigger */\n\n target = target || document.body || document.documentElement;\n target.removeEventListener(name, callback);\n}\n/**\n * Sets a one time event listener for an oAds event\n * @param {string} name The name of the event\n * @param {function} callback The function to execute on the event\n * @param {HTMLElement} [target] The element to attach the event listener to\n */\n\nfunction once(name, callback, target) {\n const handler = function (event) {\n /* istanbul ignore next: ignore the final fallback as hard trigger */\n const targ = event.target || event.srcElement;\n targ.removeEventListener(name = `oAds.${name}`, callback);\n\n if (callback) {\n callback(event); // we set callback to null so if for some reason the listener isn't removed the callback will still only be called once\n\n callback = null;\n }\n };\n\n on(name, handler, target);\n}\n\nfunction getMarksForEvents(events, suffix) {\n const markNames = events.map(eventName => \"oAds.\" + eventName + suffix);\n\n if (!performance || !performance.getEntriesByName) {\n /* istanbul ignore next */\n return {};\n }\n\n const marks = {};\n markNames.forEach(function (mName) {\n const pMarks = performance.getEntriesByName(mName);\n const markName = mName.replace(\"oAds.\", \"\").replace(suffix, \"\");\n\n if (pMarks && pMarks.length) {\n // We don't need sub-millisecond precision\n marks[markName] = Math.round(pMarks[0].startTime);\n return;\n } // If no mark has been found, we might be looking for a page-level\n // mark name, i.e. one without a suffix\n\n\n if (suffix) {\n const mNameNoSuffix = mName.replace(suffix, \"\");\n const pMarks2 = performance.getEntriesByName(mNameNoSuffix);\n\n if (pMarks2 && pMarks2.length) {\n marks[markName] = Math.round(pMarks2[0].startTime);\n }\n }\n });\n return marks;\n}\nfunction clearPerfMarks(metricsDefinitions, groupsToClear) {\n if (!performance || !performance.getEntriesByType) {\n return;\n }\n\n const relevantGroups = metricsDefinitions.filter(group => groupsToClear.includes(group.spoorAction));\n const relevantGroupsMarks = relevantGroups.map(group => group.marks); // Because relevantGroupsMarks is a 2D array ...\n\n const eventsToClear = [].concat(...relevantGroupsMarks);\n const perfMarks = performance.getEntriesByType(\"mark\");\n perfMarks.forEach(({\n name\n }) => {\n eventsToClear.forEach(eventName => {\n if (name.match(`oAds.${eventName}`)) {\n performance.clearMarks(name);\n }\n });\n });\n}\n/* istanbul ignore next */\n\nfunction getNavigationPerfMarks(desiredMarks) {\n if (!performance || !performance.getEntriesByType || !utils.isArray(desiredMarks)) {\n /* istanbul ignore next */\n return {};\n }\n\n const navMarksArray = performance.getEntriesByType(\"navigation\");\n const navMarks = utils.isArray(navMarksArray) && navMarksArray[0] || {};\n const marks = {};\n desiredMarks.forEach(function (markName) {\n marks[markName] = typeof navMarks[markName] === \"number\" ? Math.round(navMarks[markName]) : 0;\n });\n return marks;\n}\n\nfunction setupMetrics(definitions, callback, disableSampling) {\n if (!Array.isArray(definitions)) {\n this.log.warn(\"Metrics definitions should be an array. o-Ads will not record any metrics.\");\n return;\n }\n\n definitions.forEach(function (eDef) {\n if (disableSampling || utils.inSample(eDef.sampleSize)) {\n const triggers = Array.isArray(eDef.triggers) ? eDef.triggers : [];\n triggers.forEach(function (trigger) {\n sendMetricsOnEvent(\"oAds.\" + trigger, eDef, callback);\n });\n }\n });\n}\n\nfunction sendMetricsOnEvent(eventName, eMarkMap, callback) {\n document.addEventListener(eventName, function listenOnInitialised(event) {\n sendMetrics(eMarkMap, event.detail, callback);\n\n if (!eMarkMap.multiple) {\n document.removeEventListener(eventName, listenOnInitialised);\n }\n });\n}\n\nfunction sendMetrics(eMarkMap, eventDetails, callback) {\n const suffix = utils.buildPerfmarkSuffix(eventDetails);\n const marks = getMarksForEvents(eMarkMap.marks, suffix);\n\n if (eMarkMap.navigation) {\n const navMarks = getNavigationPerfMarks(eMarkMap.navigation);\n Object.assign(marks, navMarks);\n }\n\n const eventPayload = {\n category: \"ads\",\n action: eMarkMap.spoorAction,\n timings: {\n marks: marks\n }\n };\n eventPayload.advert = {\n correlator: window.oAds.gpt.getCorrelator()\n };\n\n if (eventDetails && \"pos\" in eventDetails) {\n eventPayload.creative = {\n name: eventDetails.name,\n pos: eventDetails.pos,\n size: eventDetails.size && eventDetails.size.toString(),\n creativeId: eventDetails.creativeId || 0\n };\n\n if (typeof eventDetails.isEmpty === \"boolean\") {\n eventPayload.creative.isEmpty = eventDetails.isEmpty;\n }\n }\n\n callback(eventPayload);\n}\n\nfunction markPageChange(definitions, groupsToClear) {\n clearPerfMarks(definitions, groupsToClear);\n utils.broadcast(\"pageChange\");\n}\n\n/**\n * Utility methods for postMessage api.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils\n */\nvar messenger = {\n post: function (message, source) {\n message = typeof message === \"string\" ? message : JSON.stringify(message);\n source = arguments[1] || window.top;\n source.postMessage(message, \"*\");\n },\n parse: function (message) {\n // Check whether the message looks like an object before trying to parse it\n if (typeof message !== \"string\" || message[0] !== \"{\") {\n return message;\n } // try returning the parsed object\n\n\n try {\n return JSON.parse(message);\n } catch (e) {\n // return the original message\n return message;\n }\n }\n};\n\nlet callback;\nlet breakpoints$1;\nlet current;\n\nfunction getNearestBreakpoint() {\n let winner;\n const dims = oViewport.getSize(true);\n\n function findCurrentBreakpoint(breakpoint) {\n const breakpointDims = breakpoints$1[breakpoint];\n\n if (dims.width >= breakpointDims[0] && dims.height >= breakpointDims[1]) {\n if (!winner || breakpointDims[0] >= breakpoints$1[winner][0]) {\n winner = breakpoint;\n }\n }\n }\n\n Object.keys(breakpoints$1).forEach(findCurrentBreakpoint);\n return winner;\n}\n\nfunction fire() {\n const winner = getNearestBreakpoint();\n\n if (current !== winner) {\n setCurrent(winner);\n callback(winner);\n }\n}\n\nfunction setCurrent(name) {\n current = name;\n}\n\nfunction getCurrent() {\n return current;\n}\nfunction init$2(brps, cb) {\n if (!utils.isFunction(cb)) {\n // must have a call back function\n return false;\n }\n\n breakpoints$1 = brps;\n callback = cb;\n setCurrent(getNearestBreakpoint());\n document.body.addEventListener(\"oViewport.orientation\", fire);\n document.body.addEventListener(\"oViewport.resize\", fire);\n oViewport.listenTo(\"orientation\");\n oViewport.listenTo(\"resize\");\n return getCurrent();\n}\noViewport.setThrottleInterval;\n\n/* eslint no-console: 0 */\n/**\n * Utility methods for logging.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils/log\n * @see utils\n */\n\n/* jshint devel: true */\n\n/**\n * Safe logger for the browser\n * @exports utils/log\n * @param {string} type Sets the type of log message log, warn, error or info, if not set to one of these values log will be used\n * @param {any} args the arguments to be passed to console[type]\n */\n\nfunction log() {\n let type;\n let argsIndex;\n\n if (\"log warn error info\".indexOf(arguments[0]) === -1) {\n type = \"log\";\n argsIndex = 0;\n } else {\n type = arguments[0];\n argsIndex = 1;\n }\n\n const args = [].slice.call(arguments, argsIndex);\n\n if (log.isOn(type)) {\n window.console[type].apply(window.console, args);\n }\n}\n/**\n * Determine if debug logging is on and if the type if supported\n * @param {string} type\n */\n\nconst isOn = function (type) {\n /* istanbul ignore else */\n const debug = localStorage && localStorage.getItem(\"oAds\") || location.search.indexOf(\"DEBUG=OADS\") !== -1;\n return debug && window.console && window.console[type];\n};\n/**\n * Log a warning message\n */\n\nconst warn = function () {\n const args = [\"warn\"].concat([].slice.call(arguments, 0));\n log.apply(null, args);\n};\n/**\n * Log an error message\n */\n\nconst error = function () {\n const args = [\"error\"].concat([].slice.call(arguments, 0));\n log.apply(null, args);\n};\n/**\n * Log an info message\n */\n\nconst info = function () {\n const args = [\"info\"].concat([].slice.call(arguments, 0));\n log.apply(null, args);\n};\n/**\n * Start a collapsed group\n * @param {string} group the name of the group, defaults to o-ads\n */\n\nconst start = function (group) {\n if (!log.isOn(\"groupCollapsed\")) {\n return;\n }\n\n window.console.groupCollapsed(group || \"o-ads\");\n};\n/**\n * End a collapsed group\n */\n\nconst end = function () {\n if (!log.isOn(\"groupEnd\")) {\n return;\n }\n\n window.console.groupEnd();\n};\nconst table = function (data, columns) {\n if (log.isOn(\"log\") && window.console) {\n if (console.table) {\n console.table(data, columns);\n } else {\n console.log(data);\n }\n }\n};\nconst attributeTable = function (object, columns) {\n if (log.isOn(\"log\") && window.console) {\n if (object && console.table) {\n const data = Object.keys(object).map(item => {\n let val;\n\n if (isArray(object[item]) || isObject(object[item])) {\n val = JSON.stringify(object[item]);\n } else {\n val = object[item];\n }\n\n return {\n key: item,\n value: val\n };\n });\n console.table(data, columns);\n } else {\n console.log(object);\n }\n }\n};\n\n// generated by genversion\nvar version = \"18.3.3\";\n\n/**\n * Utility methods for the advertising library.\n * @author Origami Advertising, origami.advertising@ft.com\n * @module utils\n */\n\nconst hop = Object.prototype.hasOwnProperty;\ninit$2.getCurrent = getCurrent;\nlog.start = start;\nlog.end = end;\nlog.isOn = isOn;\nlog.info = info;\nlog.warn = warn;\nlog.error = error;\nlog.table = table;\nlog.attributeTable = attributeTable;\n/**\n * Uses object prototype toString method to get at the type of object we are dealing,\n * IE returns [object Object] for null and undefined so we need to filter those\n * http://es5.github.com/#x15.2.4.2\n * @private\n * @param {object} Any javascript object\n * @returns The type of the object e.g Array, String, Object\n */\n\nfunction is(object) {\n const type = Object.prototype.toString.call(object).match(/^\\[object\\s(.*)\\]$/)[1];\n\n if (object === null) {\n return \"Null\";\n } else if (object === undefined) {\n return \"Undefined\";\n } else {\n return type;\n }\n}\n/**\n * Test if an object is an Array\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Array, otherwise false\n */\n\n\nconst isArray = function (obj) {\n return is(obj) === \"Array\";\n};\n/**\n * Test if an object is a String\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type String, otherwise false\n */\n\nconst isString = function (obj) {\n return is(obj) === \"String\";\n};\n/**\n * Test if an object is a Function\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Function, otherwise false\n */\n\nconst isFunction = function (obj) {\n return is(obj) === \"Function\";\n};\n/**\n * Test if an object is a Storage object\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Storage, otherwise false\n */\n\nconst isStorage = function (obj) {\n return is(obj) === \"Storage\";\n};\n/**\n * Test if an object is an Object\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is of type Object, otherwise false\n */\n\nconst isObject = function (obj) {\n return is(obj) === \"Object\";\n};\n/**\n * Test if an object is the global window object\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is the window obj, otherwise false\n */\n\nconst isWindow = function (obj) {\n return obj && obj !== null && obj === window;\n};\n/**\n * Test if an object inherits from any other objects, used in extend\n * to protect against deep copies running out of memory and constructors\n * losing there prototypes when cloned\n * @param {object} obj The object to be tested\n * @returns {boolean} true if the object is plain false otherwise\n */\n\nconst isPlainObject = function (obj) {\n const hop = Object.prototype.hasOwnProperty; // Must be an Object.\n // Because of IE, we also have to check the presence of the constructor property.\n // Make sure that DOM nodes and window objects don't pass through, as well\n\n if (!obj || !isObject(obj) || obj.nodeType || isWindow(obj)) {\n return false;\n }\n\n try {\n // Not own constructor property must be Object\n if (obj.constructor && !hop.call(obj, \"constructor\") && !hop.call(obj.constructor.prototype, \"isPrototypeOf\")) {\n return false;\n }\n } catch (e) {\n /* istanbul ignore next */\n // IE8,9 Will throw exceptions on certain host objects\n return false;\n } // Own properties are enumerated firstly, so to speed up,\n // if last one is own, then all properties are own.\n\n\n let key;\n\n for (key in obj) {// empty\n }\n\n return key === undefined || hop.call(obj, key);\n};\n/**\n * Test if an object is a string with a length\n * @param {object} str The object to be tested\n * @returns {boolean} true if the object is a string with a length greater than 0\n */\n\nconst isNonEmptyString = function (str) {\n return isString(str) && Boolean(str.length);\n};\nconst isElement = function (element) {\n return element && element.nodeType === 1 && element.tagName || false;\n};\nfunction extend() {\n /* jshint forin: false */\n\n /* when doing a deep copy we want to copy prototype properties */\n let options;\n let src;\n let copy;\n let copyIsArray;\n let clone;\n let target = arguments[0] || {};\n const length = arguments.length;\n let deep = false;\n let i = 1; // Handle a deep copy situation\n\n if (typeof target === \"boolean\") {\n deep = target;\n target = arguments[1] || {}; // skip the boolean and the target\n\n i = 2;\n } // Handle case when target is a string or something (possible in deep copy)\n\n /* istanbul ignore else */\n\n\n if (typeof target !== \"object\" && !isFunction(target)) {\n target = {};\n } // do nothing if only one argument is passed (or 2 for a deep copy)\n\n /* istanbul ignore else */\n\n\n if (length === i) {\n return target;\n }\n\n for (; i < length; i++) {\n // Only deal with non-null/undefined values\n if ((options = arguments[i]) !== null) {\n // Extend the base object\n for (const name in options) {\n /* istanbul ignore next */\n // eslint-disable-next-line no-prototype-builtins\n if (options.hasOwnProperty(name)) {\n src = target[name];\n copy = options[name]; // Prevent never-ending loop\n\n if (target === copy) {\n continue;\n } // Recurse if we're merging arrays\n\n\n if (deep && copy && (isPlainObject(copy) || isArray(copy))) {\n copyIsArray = isArray(copy);\n\n if (copyIsArray) {\n copyIsArray = false;\n clone = src && isArray(src) ? src : [];\n } else {\n clone = src && isObject(src) ? src : {};\n } // Never move original objects, clone them\n\n\n target[name] = extend(deep, clone, copy); // Don't bring in undefined values\n } else if (copy !== undefined) {\n target[name] = copy;\n }\n }\n }\n }\n } // Return the modified object\n\n\n return target;\n}\n/**\n * Create an object hash from a delimited string\n * Beware all properties on the resulting object will have string values.\n * @param {string} str The string to transform\n * @param {string|regexp} delimiter The character that delimits each name/value pair\n * @param {string} pairing The character that separates the name from the value\n * @return {object}\n *\n */\n\nconst hash = function (str, delimiter, pairing) {\n let pair;\n let value;\n const hashObj = {};\n\n if (str && str.split) {\n str = str.split(delimiter);\n\n for (let idx = 0, l = str.length; idx < l; idx += 1) {\n value = str[idx];\n pair = value.split(pairing);\n\n if (pair.length > 1) {\n hashObj[pair[0].trim()] = pair.slice(1).join(pairing);\n }\n }\n }\n\n return hashObj;\n};\n/**\n * Takes a script URL as a string value, creates a new script element, sets the src and attaches to the page\n * The async value of the script can be set by the seccond parameter, which is a boolean\n * Note, we should use protocol-relative URL paths to ensure we don't run into http/https issues\n * @param {string} scriptUrl The url to the script file to be added\n * @param {boolean} async Set the async attribute on the script tag\n * @param {function} callback A function to run when the script loads\n * @param {function} errorcb A function to run if the script fails to load\n * @returns {HTMLElement} the created script tag\n */\n\nconst attach = function (scriptUrl, async, callback, errorcb, autoRemove) {\n const tag = document.createElement(\"script\");\n const node = document.getElementsByTagName(\"script\")[0];\n let hasRun = false;\n\n function processCallback(callback) {\n /* istanbul ignore else */\n if (!hasRun) {\n callback.call();\n hasRun = true;\n /* istanbul ignore else */\n\n if (autoRemove) {\n tag.parentElement.removeChild(tag);\n }\n }\n }\n\n tag.setAttribute(\"src\", scriptUrl);\n tag.setAttribute(\"o-ads\", \"\");\n /* istanbul ignore else */\n\n if (async) {\n tag.async = \"true\";\n }\n /* istanbul ignore else */\n\n\n if (isFunction(callback)) {\n /* istanbul ignore if - legacy IE code, won't test */\n if (hop.call(tag, \"onreadystatechange\")) {\n tag.onreadystatechange = function () {\n if (tag.readyState === \"loaded\") {\n processCallback(callback);\n }\n };\n } else {\n tag.onload = function () {\n processCallback(callback);\n };\n }\n }\n /* istanbul ignore else */\n\n\n if (isFunction(errorcb)) {\n tag.onerror = function () {\n processCallback(errorcb);\n };\n } // Use insert before, append child has issues with script tags in some browsers.\n\n\n node.parentNode.insertBefore(tag, node);\n return tag;\n};\n/**\n * return the current documents referrer or an empty string if non exists\n * This method enables us to mock the referrer in our tests reliably and doesn't really serve any other purpose\n * @returns {string} document.referrer\n */\n\n/* istanbul ignore next - cannot reliably test value of referer */\n\nconst getReferrer = function () {\n return document.referrer || \"\";\n};\n/**\n * Remove hyphens from a string and upper case the following letter\n * @param {string} string the string to parse\n * @returns {string}\n */\n\nconst dehyphenise = function (string) {\n return string.replace(/(-)([a-z])/g, function (match, hyphen, letter) {\n return letter.toUpperCase();\n });\n};\n/**\n * remove prefixes from o-ads data attributes and dehyphenise the name\n * @param {string|} name the name of the attribute to parse\n * @returns {string}\n */\n\nconst parseAttributeName = function (attribute) {\n const name = isString(attribute) ? attribute : attribute.name;\n return dehyphenise(name.replace(/(data-)?o-ads-/, \"\"));\n};\n/**\n * return the current documents url or an empty string if non exists\n * This method enables us to mock the document location string in our tests reliably and doesn't really serve any other purpose\n * @returns {string}\n */\n\n/* istanbul ignore next - cannot reliably test value of location */\n\nconst getLocation = function () {\n return document.location.href || \"\";\n};\n/**\n * return the current documents search or an empty string if non exists\n * also strips the initial ? from the search string for easier parsing\n * This method enables us to mock the search string in our tests reliably and doesn't really serve any other purpose\n * @returns {string}\n */\n\nconst getQueryString = function () {\n return document.location.search.substring(1) || \"\";\n};\n/**\n * Get a query string parameter by name from a url\n * @param name\n * @param url\n * @returns {string | null}\n */\n\nconst getQueryParamByName = function (name, url) {\n url = url || window.location.href;\n name = name.replace(/[[\\]]/g, \"\\\\$&\");\n const regex = new RegExp(\"[?&]\" + name + \"(=([^]*)|&|#|$)\");\n const results = regex.exec(url);\n\n if (!results) {\n return null;\n }\n\n if (!results[2]) {\n return \"\";\n }\n\n return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n};\n/**\n * returns a timestamp of the current date/time in the format YYYYMMDDHHMMSS\n * @returns {string}\n */\n\nconst getTimestamp = function () {\n const now = new Date();\n return [now.getFullYear(), `0${now.getMonth() + 1}`.slice(-2), `0${now.getDate()}`.slice(-2), `0${now.getHours()}`.slice(-2), `0${now.getMinutes()}`.slice(-2), `0${now.getSeconds()}`.slice(-2)].join(\"\");\n};\n/**\n * Given the window object of an iframe this method returns the o-ads slot name\n * that rendered the iframe, if the iframe was not rendered by o-ads this will\n * return false\n * @param {window} a window object\n * @returns {String|Boolean}\n */\n\nconst iframeToSlotName = function (iframeWindow) {\n // capture all iframes in the page in a live node list\n const iframes = document.getElementsByTagName(\"iframe\");\n let slotName;\n let node;\n let i = iframes.length; // Figure out which iframe DOM node we have the window for\n\n while (i--) {\n /* istanbul ignore else */\n if (iframes[i].contentWindow === iframeWindow) {\n node = iframes[i];\n break;\n }\n }\n /* istanbul ignore else */\n\n\n if (node) {\n // find the closest parent with a data-o-ads-name attribute, that's our slot name\n while (node.parentNode) {\n slotName = node.getAttribute(\"data-o-ads-name\");\n /* istanbul ignore else */\n\n if (slotName) {\n return slotName;\n }\n\n node = node.parentNode;\n }\n }\n\n return false;\n};\nconst buildObjectFromArray = function buildObjectFromArray(targetObject) {\n return targetObject.reduce((prev, data) => {\n prev[data.key] = data.value;\n return prev;\n }, {});\n};\nconst cookie = function (name) {\n const val = document.cookie.match(`(^|;)\\\\s*${name}\\\\s*=\\\\s*([^;]+)`);\n return val ? val.pop() : null;\n};\nconst getVersion = () => version ;\nconst metricsSampleThreshold = Math.random();\nfunction inSample(sampleSize) {\n return typeof sampleSize === \"undefined\" || sampleSize > metricsSampleThreshold;\n}\nvar utils = {\n on,\n off,\n once,\n broadcast,\n messenger,\n responsive: init$2,\n log,\n isArray,\n isString,\n isFunction,\n isStorage,\n isObject,\n isWindow,\n isPlainObject,\n isNonEmptyString,\n isElement,\n extend,\n hash,\n attach,\n getReferrer,\n dehyphenise,\n parseAttributeName,\n getLocation,\n getQueryString,\n getQueryParamByName,\n getTimestamp,\n iframeToSlotName,\n buildObjectFromArray,\n cookie,\n getVersion,\n setupMetrics,\n clearPerfMarks,\n markPageChange,\n inSample,\n perfMark,\n buildPerfmarkSuffix\n};\n\n//TODO remove all ft.com specific stuff so we can remove this as a global\n/**\n * Default configuration set in the constructor.\n */\n\nconst defaults = {\n formats: {\n PartnerContent: {\n sizes: [\"fluid\"]\n },\n MediumRectangle: {\n sizes: [300, 250]\n },\n Rectangle: {\n sizes: [180, 50]\n },\n WideSkyscraper: {\n sizes: [160, 600]\n },\n Leaderboard: {\n sizes: [728, 90]\n },\n SuperLeaderboard: {\n sizes: [[970, 90], [970, 66]]\n },\n HalfPage: {\n sizes: [300, 600]\n },\n Billboard: {\n sizes: [970, 250]\n },\n Portrait: {\n sizes: [300, 1050]\n },\n AdhesionBanner: {\n sizes: [320, 50]\n },\n MicroBar: {\n sizes: [88, 31]\n },\n Button2: {\n sizes: [120, 60]\n },\n Responsive: {\n sizes: [2, 2]\n }\n },\n responsive: {\n extra: [1025, 0],\n //Reasonable width to show a Billboard (desktop)\n large: [1000, 0],\n //reasonable width to show SuperLeaderboard (tablet landscape)\n medium: [760, 0],\n //reasonable width to show a leaderboard (tablet portrait)\n small: [0, 0] //Mobile\n\n },\n flags: {\n refresh: true,\n inview: true\n },\n displayLabelWithBorders: false\n};\n\nfunction fetchDeclaritiveConfig() {\n let results = {};\n const scripts = Array.from(document.querySelectorAll(\"script[data-o-ads-config]\"));\n scripts.forEach(script => {\n results = window.JSON ? utils.extend(results, JSON.parse(script.innerHTML)) : \"UNSUPPORTED\";\n });\n return results;\n}\n/**\n * @private\n * @function\n * fetchCanonicalURL Grabs the canonical URL from the page meta if it exists.\n */\n\n\nfunction fetchCanonicalURL() {\n let canonical;\n const canonicalTag = document.querySelector('link[rel=\"canonical\"]');\n\n if (canonicalTag) {\n canonical = canonicalTag.href;\n }\n\n return {\n canonical: canonical\n };\n}\n/**\n * Defines a store for configuration information and returns a getter/setter method for access.\n * @class\n * @constructor\n */\n\n\nfunction Config() {\n this.store = {};\n}\n\nConfig.prototype.access = function (k, v) {\n let result;\n\n if (utils.isPlainObject(k)) {\n utils.extend(true, this.store, k);\n result = this.store;\n } else if (typeof v === \"undefined\") {\n if (typeof k === \"undefined\") {\n result = this.store;\n } else {\n result = this.store[k];\n }\n } else {\n this.store[k] = v;\n result = v;\n }\n\n return result;\n};\n\nConfig.prototype.clear = function (key) {\n if (key) {\n delete this.store[key];\n } else {\n this.store = {};\n }\n};\n\nConfig.prototype.init = function () {\n this.store = utils.extend(true, {}, defaults, fetchCanonicalURL(), fetchDeclaritiveConfig());\n return this.store;\n};\n\nconst config = new Config();\nvar config$1 = config.access.bind(config);\nconst init$1 = config.init.bind(config);\nconst clear = config.clear.bind(config);\n\nconst VALID_SIZE_STRINGS = [\"fluid\"];\nconst VALID_COLLAPSE_MODES = [\"before\", \"after\", \"never\"];\nconst attributeParsers = {\n sizes: function (value, sizes) {\n if (value === false || value === \"false\") {\n return false;\n } else if (utils.isArray(sizes)) {\n /* istanbul ignore else */\n const regex = /(\\d+)x(\\d+)/;\n value.split(\",\").filter(size => size.length).forEach(size => {\n if (regex.test(size)) {\n size.replace(regex, function (match, width, height) {\n sizes.push([parseInt(width, 10), parseInt(height, 10)]);\n });\n } else if (VALID_SIZE_STRINGS.indexOf(size) >= 0) {\n sizes.push(size);\n }\n });\n }\n\n return sizes;\n },\n formats: function (value, sizes) {\n if (value === false || value === \"false\") {\n sizes = false;\n } else {\n const mapping = config$1().formats;\n const formats = utils.isArray(value) ? value : value.split(\",\");\n formats.forEach(format => {\n if (mapping && mapping[format]) {\n format = mapping[format];\n\n if (utils.isArray(format.sizes[0]) || VALID_SIZE_STRINGS.indexOf(format.sizes[0]) >= 0) {\n format.sizes.forEach(size => {\n sizes.push(size);\n });\n } else {\n sizes.push(format.sizes);\n }\n } else {\n utils.log.error(`Slot configured with unknown format ${format}`);\n }\n });\n }\n\n return sizes;\n },\n responsiveSizes: function (name, value, sizes) {\n const screenName = name.replace(/^sizes/, \"\").toLowerCase();\n /* istanbul ignore else\t*/\n\n if (!utils.isPlainObject(sizes)) {\n sizes = {};\n }\n\n sizes[screenName] = attributeParsers.sizes(value, sizes[screenName] || []);\n return sizes;\n },\n responsiveFormats: function (name, value, sizes) {\n const screenName = name.replace(/^formats/, \"\").toLowerCase();\n /* istanbul ignore else\t*/\n\n if (!utils.isPlainObject(sizes)) {\n sizes = {};\n }\n\n sizes[screenName] = attributeParsers.formats(value, []);\n return sizes;\n },\n lazyLoadThreshold: function (value) {\n return value.split(\",\").map(Number);\n },\n targeting: function (value, targeting) {\n value = utils.hash(value, \";\", \"=\");\n utils.extend(targeting, value);\n return targeting;\n },\n base: function (value) {\n /* istanbul ignore else\t*/\n if (value === \"\" || value === \"true\") {\n value = true;\n } else if (value === \"false\") {\n value = false;\n }\n\n return value;\n },\n collapseEmpty: function (value) {\n const isUnknownAttribute = VALID_COLLAPSE_MODES.indexOf(value) === -1;\n\n if (isUnknownAttribute) {\n utils.log.warn(`Invalid attribute ${value} used for collapse-empty attribute, please use 'before', 'after' or 'never'`);\n return undefined;\n }\n\n return value;\n }\n};\n\nconst convertLazyLoadBooleanToObject = obj => {\n if (obj.lazyLoad === true) {\n obj.lazyLoad = {};\n }\n};\n\nconst onChangeBreakpoint = event => {\n const slot = event.detail.slot;\n slot.screensize = event.detail.screensize;\n\n if (slot.hasValidSize()) {\n slot.uncollapse();\n } else {\n slot.collapse();\n slot.clear();\n }\n};\n/**\n * The Slot class.\n * @class\n * @constructor\n */\n\n\nfunction Slot(container, screensize, initLazyLoading) {\n const renderEvent = \"slotRenderStart\";\n const cfg = config$1();\n let slotConfig = config$1(\"slots\") || {}; // store the container\n\n this.container = container; // the current responsive screensize\n\n /* istanbul ignore else\t*/\n\n if (screensize) {\n this.screensize = screensize;\n } // init slot dom structure\n\n\n this.outer = this.addContainer(container, {\n class: \"o-ads__outer\",\n \"aria-hidden\": \"true\",\n tabindex: \"-1\"\n });\n this.inner = this.addContainer(this.outer, {\n class: \"o-ads__inner\"\n }); // make sure the slot has a name\n\n this.setName();\n slotConfig = slotConfig[this.name] || {}; // default configuration properties\n\n this.server = \"gpt\";\n this.defer = false; // global slots configuration\n\n this.targeting = slotConfig.targeting || {};\n this.sizes = slotConfig.sizes || [];\n this.center = slotConfig.center || false;\n this.label = slotConfig.label || false;\n this.outOfPage = slotConfig.outOfPage || false;\n this.companion = slotConfig.companion === false ? false : true;\n this.collapseEmpty = slotConfig.collapseEmpty;\n /* istanbul ignore else */\n\n if (utils.isArray(slotConfig.formats)) {\n attributeParsers.formats(slotConfig.formats, this.sizes);\n } else if (utils.isPlainObject(slotConfig.formats)) {\n this.sizes = {};\n Object.keys(slotConfig.formats).forEach(screenName => {\n this.sizes[screenName] = attributeParsers.formats(slotConfig.formats[screenName], []);\n });\n }\n\n if (typeof slotConfig.lazyLoad !== \"undefined\") {\n this.lazyLoad = slotConfig.lazyLoad;\n } else {\n this.lazyLoad = config$1(\"lazyLoad\") || false;\n }\n\n const outerEl = container.querySelector(\".o-ads__outer\");\n\n if (outerEl && cfg.displayLabelWithBorders && this.container.getAttribute(\"data-o-ads-label\")) {\n const allowedLabels = [\"left\", \"center\", \"right\"];\n const adsLabelPos = this.container.getAttribute(\"data-o-ads-label\");\n utils.once(renderEvent, () => {\n const modifier = allowedLabels.indexOf(adsLabelPos) ? adsLabelPos : \"left\";\n outerEl.classList.add(\"o-ads--label-with-borders\", `o-ads--label-with-borders--${modifier}`);\n });\n } // extend with imperative configuration options\n\n\n this.parseAttributeConfig();\n /* istanbul ignore else\t*/\n\n if (!this.sizes.length && !utils.isPlainObject(this.sizes)) {\n utils.log.error(\"slot %s has no configured sizes!\", this.name);\n return false;\n } // Either retrieve the existing IntersectionObserver, or tell slots.js to create a new one.\n\n\n this.lazyLoadObserver = initLazyLoading(this.lazyLoad);\n this.initLazyLoad();\n this.centerContainer();\n this.labelContainer();\n this.initResponsive();\n}\n/**\n * parse slot attribute config\n */\n\n\nSlot.prototype.parseAttributeConfig = function () {\n Array.from(this.container.attributes).forEach(attribute => {\n const name = utils.parseAttributeName(attribute.name);\n const value = attribute.value;\n\n if (name === \"formats\") {\n this[name] = attributeParsers[name](value, this.sizes);\n } else if (name === \"collapseEmpty\") {\n this.collapseEmpty = attributeParsers.collapseEmpty(value);\n } else if (name === \"lazyLoadThreshold\" && this.lazyLoad) {\n convertLazyLoadBooleanToObject(this);\n this.lazyLoad.threshold = attributeParsers.lazyLoadThreshold(value);\n } else if (name === \"lazyLoadViewportMargin\" && this.lazyLoad) {\n convertLazyLoadBooleanToObject(this);\n this.lazyLoad.viewportMargin = attributeParsers.base(value);\n } else if (attributeParsers[name]) {\n this[name] = attributeParsers[name](value, this[name]);\n } else if (/^formats\\w*/.test(name)) {\n this.sizes = attributeParsers.responsiveFormats(name, value, this.sizes);\n } else if (/^sizes\\w*/.test(name)) {\n this.sizes = attributeParsers.responsiveSizes(name, value, this.sizes);\n } // eslint-disable-next-line no-prototype-builtins\n else if (this.hasOwnProperty(name)) {\n this[name] = attributeParsers.base(value);\n }\n });\n};\n\nSlot.prototype.getAttributes = function () {\n const attributes = {};\n Array.from(this.container.attributes).forEach(attribute => {\n attributes[utils.parseAttributeName(attribute)] = attribute.value;\n });\n this.attributes = attributes;\n return this;\n};\n/**\n *\tLoad a slot when it appears in the viewport\n */\n\n\nSlot.prototype.initLazyLoad = function () {\n /* istanbul ignore else */\n if (this.lazyLoadObserver && this.lazyLoad) {\n this.defer = true;\n this.lazyLoadObserver.observe(this.container); //Master/Companion ads don't work with lazy loading, so if a master ad loads trigger\n\n /* istanbul ignore else */\n\n if (this.companion) {\n utils.once(\"masterLoaded\", () => {\n if (this.hasValidSize()) {\n this.render();\n }\n }, this.container);\n }\n }\n\n return this;\n};\n\nSlot.prototype.render = function () {\n this.fire(\"slotCanRender\");\n /* istanbul ignore else */\n\n if (this.lazyLoadObserver) {\n this.lazyLoadObserver.unobserve(this.container);\n }\n};\n/**\n *\tListen to responsive breakpoints and collapse slots\n * where the configured size is set to false\n */\n\n\nSlot.prototype.initResponsive = function () {\n /* istanbul ignore else */\n if (utils.isPlainObject(this.sizes)) {\n /* istanbul ignore else */\n if (!this.hasValidSize()) {\n this.collapse();\n }\n\n utils.on(\"breakpoint\", onChangeBreakpoint, this.container);\n }\n\n return this;\n};\n/**\n * Maximise the slot when size is 100x100\n */\n\n\nSlot.prototype.maximise = function (size) {\n if (size && Number(size[0]) === 100 && Number(size[1]) === 100) {\n this.fire(\"resize\", {\n size: [\"100%\", \"100%\"]\n });\n }\n};\n/**\n *\tIf the slot doesn't have a name give it one\n */\n\n\nSlot.prototype.setName = function () {\n this.name = this.container.getAttribute(\"data-o-ads-name\") || this.container.getAttribute(\"o-ads-name\");\n\n if (!this.name) {\n this.name = `o-ads-slot-${Math.floor(Math.random() * 10000)}`;\n this.container.setAttribute(\"data-o-ads-name\", this.name);\n }\n\n return this;\n};\n/**\n * add the empty class to the slot\n */\n\n\nSlot.prototype.collapse = function () {\n this.container.classList.add(\"o-ads--empty\");\n this.setFormatLoaded(false);\n document.body.classList.add(`o-ads-no-${this.name}`);\n utils.broadcast(\"collapsed\", this);\n return this;\n};\n/**\n * add the additional class to the slot\n */\n\n\nSlot.prototype.addClass = function (className) {\n this.container.classList.add(`o-ads-${className}`);\n utils.broadcast(\"slotClassAdded\", this);\n return this;\n};\n/**\n * sets a classname of the format\n */\n\n\nSlot.prototype.setFormatLoaded = function (format) {\n this.container.setAttribute(\"data-o-ads-loaded\", format);\n return this;\n};\n/**\n * remove the empty class from the slot\n */\n\n\nSlot.prototype.uncollapse = function () {\n this.container.classList.remove(\"o-ads--empty\");\n document.body.classList.remove(`o-ads-no-${this.name}`);\n return this;\n};\n/**\n * call the ad server clear method on the slot if one exists\n */\n\n\nSlot.prototype.clear = function () {\n /* istanbul ignore else */\n if (utils.isFunction(this[\"clearSlot\"])) {\n this.clearSlot();\n }\n\n return this;\n};\n/**\n * call the ad server destroySlot method on the slot if one exists\n */\n\n\nSlot.prototype.destroy = function () {\n /* istanbul ignore else */\n if (utils.isFunction(this[\"destroySlot\"])) {\n utils.off(\"breakpoint\", onChangeBreakpoint, this.container);\n this.destroySlot();\n\n if (this.outer.parentElement === this.container) {\n this.container.removeChild(this.outer);\n } else {\n console.error(\"Error destroying ad slot. The parent node has already been removed.\"); // eslint-disable-line no-console\n }\n }\n\n return this;\n};\n/**\n * call the ad server impression URL for an out of page slot if it has been configured correctly for delayed impressions\n */\n\n\nSlot.prototype.submitImpression = function () {\n /* istanbul ignore else */\n if (utils.isFunction(this[\"submitGptImpression\"])) {\n this.submitGptImpression();\n }\n\n return this;\n};\n/**\n *\tfire an event on the slot\n */\n\n\nSlot.prototype.fire = function (name, data) {\n const gpt = this.gpt || {};\n const details = {\n name: this.name || \"\",\n pos: this.targeting && this.targeting.pos || \"\",\n size: gpt.size || \"\",\n creativeId: gpt.creativeId || \"\",\n slot: this\n };\n\n if (typeof gpt.isEmpty === \"boolean\") {\n details.isEmpty = gpt.isEmpty;\n }\n\n if (utils.isPlainObject(data)) {\n utils.extend(details, data);\n }\n\n utils.broadcast(name, details, this.container);\n return this;\n};\n/**\n *\tadd a div tag into the current slot container\n **/\n\n\nSlot.prototype.addContainer = function (node, attrs) {\n let container = \"
\";\n node.insertAdjacentHTML(\"beforeend\", container);\n return node.lastChild;\n};\n\nSlot.prototype.hasValidSize = function (screensize) {\n screensize = screensize || this.screensize;\n\n if (screensize && utils.isPlainObject(this.sizes)) {\n return this.sizes[screensize] !== false;\n }\n\n return true;\n};\n/**\n * Add a center class to the main container\n */\n\n\nSlot.prototype.centerContainer = function () {\n if (this.center) {\n this.container.classList.add(\"o-ads--center\");\n }\n\n return this;\n};\n/**\n * Add a label class to the main container\n */\n\n\nSlot.prototype.labelContainer = function () {\n let className;\n\n if (this.label === true || this.label === \"left\") {\n className = \"label-left\";\n } else if (this.label === \"right\") {\n className = \"label-right\";\n }\n\n if (className && !config$1(\"displayLabelWithBorders\")) {\n this.container.classList.add(`o-ads--${className}`);\n }\n\n return this;\n};\n\n/** @typedef {import(\"$typings/index\")} Advertising */\n\n/**\n * @param {Advertising.Slot} slot\n * @returns {string}\n */\nfunction getSlotSizes(slot) {\n if (!Array.isArray(slot.sizes)) return \"responsive slot\";\n const sizes = [];\n\n for (const size of slot.sizes) {\n sizes.push(Array.isArray(size) ? size.join(\"×\") : size);\n }\n\n return sizes.join(\", \");\n}\n/**\n * @param {Advertising.Slot} slot\n * @returns {string}\n */\n\n\nfunction getSlotTargeting({\n targeting\n}) {\n const params = [];\n\n for (const [key, val] of Object.entries(targeting || {})) {\n params.push(`${key}=${val}`);\n }\n\n return params.join(\", \");\n}\n/**\n * @param {Advertising.Slot} slot\n * @returns {string}\n */\n\n\nfunction getSlotGPTSize({\n gpt\n}) {\n if (typeof gpt === \"undefined\") return \"gpt is undefined\";\n if (gpt.isEmpty) return \"empty\";\n if (!Array.isArray(gpt.size)) return \"N/A\";\n return gpt.size.join(\"×\");\n}\n/**\n * Use a type predicate to distinguish between the `Slots` instance's properties\n * @type {(o: Advertising.Slot | IntersectionObserver) => o is Advertising.Slot }\n */\n\n\nconst isSlot = o => \"name\" in o;\n/**\n * @param {(Advertising.Slot | IntersectionObserver)[]} slots\n */\n\n\nfunction debug$1(slots) {\n const data = [];\n\n for (const slot of slots) {\n if (isSlot(slot)) {\n var _slot$gpt, _slot$gpt2, _slot$gpt3;\n\n const row = {\n name: slot.name,\n \"unit name\": (_slot$gpt = slot.gpt) === null || _slot$gpt === void 0 ? void 0 : _slot$gpt.unitName,\n \"creative id\": ((_slot$gpt2 = slot.gpt) === null || _slot$gpt2 === void 0 ? void 0 : _slot$gpt2.creativeId) || \"N/A\",\n \"line item id\": ((_slot$gpt3 = slot.gpt) === null || _slot$gpt3 === void 0 ? void 0 : _slot$gpt3.lineItemId) || \"N/A\",\n size: getSlotGPTSize(slot),\n sizes: getSlotSizes(slot),\n targeting: getSlotTargeting(slot)\n };\n data.push(row);\n }\n }\n\n console.group(\"Creatives\");\n console.table(data);\n console.groupEnd();\n return data;\n}\n\n/* eslint no-inner-declarations: 1 */\nlet screensize = null;\n/**\n * The Slots instance tracks all ad slots on the page\n * configures global page events used by a slot and\n * provides utlity methods that act on all slots\n * @constructor\n */\n\nfunction Slots() {//eslint-disable-line no-empty\n}\n\nfunction invokeMethodOnSlots(names, method, callback) {\n let slots = [];\n names = names || Object.keys(this);\n /* istanbul ignore else\t*/\n\n if (utils.isNonEmptyString(names)) {\n slots.push(names);\n } else if (utils.isArray(names)) {\n slots = names;\n }\n\n slots.forEach(run.bind(null, this, method));\n\n if (utils.isFunction(callback)) {\n callback.call(this, slots);\n }\n\n return this;\n}\n/*\n * Either run a method or fire an event on the named slot.\n * @private\n * @param slots the slots object\n */\n\n\nfunction run(slots, action, name) {\n const slot = slots[name];\n\n if (slot) {\n if (utils.isFunction(slot[action])) {\n slot[action]();\n } else {\n if (utils.isFunction(slot.fire)) {\n slot.fire(action);\n } else {\n utils.log.warn(\"Attempted to %s on a non-slot %s\", action, name);\n }\n }\n } else {\n utils.log.warn(\"Attempted to %s non-existant slot %s\", action, name);\n }\n}\n\nfunction findFormatBySize(size) {\n if (!size) {\n return false;\n }\n\n const formats = config$1(\"formats\");\n\n for (const prop in formats) {\n /* istanbul ignore else\t*/\n // eslint-disable-next-line no-prototype-builtins\n if (formats.hasOwnProperty(prop)) {\n let sizes = formats[prop].sizes;\n sizes = utils.isArray(sizes[0]) ? sizes : [sizes];\n const match = sizes.filter(function (s) {\n return s[0] === parseInt(size[0], 10) && s[1] === parseInt(size[1], 10);\n });\n\n if (match.length) {\n return prop;\n }\n }\n }\n}\n/**\n * Given a slot name or an array of slot names will collapse the slots using the collapse method on the slot\n */\n\n\nSlots.prototype.collapse = function (names) {\n return invokeMethodOnSlots.call(this, names, \"collapse\");\n};\n/**\n * Given a slot name or an array of slot names will uncollapse the slots using the uncollapse method on the slot\n */\n\n\nSlots.prototype.uncollapse = function (names) {\n return invokeMethodOnSlots.call(this, names, \"uncollapse\");\n};\n/**\n * Given a slot name or an array of slot names of slotnames will refresh the slots using the refresh method on the slot\n */\n\n\nSlots.prototype.refresh = function (names) {\n return invokeMethodOnSlots.call(this, names, \"refresh\");\n};\n/**\n * Given a slot name or an array of slot names will clear the slots using the clear method on the slot\n */\n\n\nSlots.prototype.clear = function (names) {\n return invokeMethodOnSlots.call(this, names, \"clear\");\n};\n/**\n * Given a slot name or an array of slot names will destroy the slots using the destroySlot method on the slot and remove the reference to the slot\n */\n\n\nSlots.prototype.destroy = function (names) {\n return invokeMethodOnSlots.call(this, names, \"destroy\", function (names) {\n names.forEach(name => {\n this[name] = null;\n delete this[name];\n });\n });\n};\n/**\n * Given a slot name will submit a delayed impression for the slot\n */\n\n\nSlots.prototype.submitImpression = function (name) {\n return invokeMethodOnSlots.call(this, name, \"submitImpression\");\n};\n/**\n * Confirms a container in the page exists and creates a Slot object\n */\n\n\nSlots.prototype.initSlot = function (container) {\n // if container is a string this is a legacy implementation using ids\n // find the element and remove the ID in favour of a data attribute\n if (utils.isString(container)) {\n container = document.getElementById(container) || document.querySelector(`[data-o-ads-name=\"${container}\"]`);\n\n if (container && container.id) {\n container.setAttribute(\"data-o-ads-name\", container.id);\n container.removeAttribute(\"id\");\n }\n } // if not an element or we can't find it in the DOM exit\n\n\n if (!utils.isElement(container)) {\n utils.log.error(\"slot container must be an element!\", container);\n return false;\n } // add the aria hidden attribute\n\n\n container.setAttribute(\"aria-hidden\", \"true\"); // pass the method to retrieve or create the single IntersectionObserver instance\n\n const slot = new Slot(container, screensize, this.initLazyLoading.bind(this));\n /* istanbul ignore else\t*/\n\n if (slot && !this[slot.name]) {\n this[slot.name] = slot;\n slot.fire(\"slotReady\");\n } else if (this[slot.name]) {\n utils.log.error(\"slot %s is already defined!\", slot.name);\n }\n\n return slot;\n};\n\nSlots.prototype.initRefresh = function () {\n if (config$1(\"flags\").refresh && config$1(\"refresh\")) {\n const data = config$1(\"refresh\");\n this.refreshCount = 0;\n /* istanbul ignore else\t*/\n\n if (data.time && !data.inview) {\n const refresh = () => {\n /* istanbul ignore else */\n if (!data.max || this.refreshCount++ < data.max) {\n this.refresh();\n } else if (this.refreshCount >= data.max) {\n clearInterval(refresh);\n }\n };\n\n setInterval(refresh, (parseFloat(data.time) || 1) * 1000);\n }\n }\n\n return this;\n};\n/*\n *\tlistens for the rendered event from a slot and fires the slotExpand event,\n * after extending the slot with information from the server.\n */\n\n\nSlots.prototype.initRendered = function () {\n utils.on(\"slotRenderStart\", function (slots, event) {\n const slot = slots[event.detail.name];\n /* istanbul ignore else\t*/\n\n if (slot) {\n utils.extend(slot[slot.server], event.detail[slot.server]);\n const size = event.detail.gpt.size;\n const format = findFormatBySize(size);\n slot.setFormatLoaded(format);\n slot.maximise(size);\n slot.fire(\"slotExpand\", event.detail);\n }\n }.bind(null, this));\n return this;\n};\n/*\n * if responsive configuration exists listen for breakpoint changes\n */\n\n\nSlots.prototype.initResponsive = function () {\n const breakpoints = config$1(\"responsive\");\n /* istanbul ignore else\t*/\n\n if (utils.isObject(breakpoints)) {\n screensize = utils.responsive(breakpoints, onBreakpointChange.bind(null, this));\n }\n\n return this;\n};\n/*\n * called when a responsive breakpoint is crossed though window resizing or orientation change.\n */\n\n\nfunction onBreakpointChange(slots, screensize) {\n slots.forEach(function (slot) {\n /* istanbul ignore else\t*/\n if (slot) {\n // ADS-766 if format name is Responsive then we have requested a responsive creative and do not want to request new ads at different breakpoints\n\n /* istanbul ignore else\t*/\n const isCurrentlyResponsive = slot.container && slot.container.getAttribute(\"data-o-ads-loaded\") === \"Responsive\";\n const stillWantsResponsive = slot.sizes[screensize] && slot.sizes[screensize].filter(size => findFormatBySize(size) === \"Responsive\").length > 0;\n\n if (isCurrentlyResponsive && stillWantsResponsive) {\n return false;\n }\n\n slot.screensize = screensize;\n slot.fire(\"breakpoint\", {\n screensize: screensize\n });\n }\n });\n}\n/*\n * Initialise the postMessage API\n */\n\n\nSlots.prototype.initPostMessage = function () {\n // Listen for messages coming from ads\n window.addEventListener(\"message\", pmHandler.bind(null, this), false);\n\n function pmHandler(slots, event) {\n const data = utils.messenger.parse(event.data);\n /* istanbul ignore else\tdon't process messages with a non oAds type*/\n\n if (data.type && (/^oAds\\./.test(data.type) || /^touch/.test(data.type))) {\n const type = data.type.replace(\"oAds.\", \"\"); // Make sure the message is coming from an identified ad slot\n\n const slotName = utils.iframeToSlotName(event.source.window);\n const slot = slots[slotName] || false;\n\n if (!slot) {\n utils.log.error(\"Message received from unidentified slot\");\n return;\n } // TODO: Remove adIframeLoaded once we can tag onto GPTs `slotRenderEnded` event\n\n\n if (type === \"adIframeLoaded\") {\n slot.fire(\"slotRenderEnded\");\n } else if (type === \"slotClass\" && data.slotClass) {\n slot.addClass(data.slotClass);\n } // Received message to Collapse ad slot.\n else if (type === \"collapse\") {\n slot.fire(\"slotCollapsed\");\n slot.collapse();\n } // Received touch events from ad slot iframe\n\n /* istanbul ignore else*/\n else if (/^touch/.test(data.type)) {\n slot.fire(\"touch\", data);\n } else {\n utils.log.error(\"Unknown message received from o-ads-embed\");\n }\n }\n }\n}; // remove any observers tied to elements no longer in the DOM\n// e.g. app page has been swiped out from the gallery\n\n\nSlots.prototype.flushLazyLoading = function () {\n this.lazyLoadingObservers = this.lazyLoadingObservers.filter(observer => {\n return Boolean(!observer.root || document.contains(observer.root));\n });\n};\n\nSlots.prototype.initLazyLoading = function (slotConfig) {\n const lazyLoadingConfig = config$1(\"lazyLoad\") || slotConfig | {};\n this.lazyLoadingObservers = this.lazyLoadingObservers || [];\n this.flushLazyLoading(); // find any pre-existing observers\n\n let lazyLoadingObserver = this.lazyLoadingObservers.find(observer => {\n // deliberately double-equals to match null and undefined where the viewport is being observed\n return lazyLoadingConfig.root == observer.root; // eslint-disable-line eqeqeq\n });\n\n function onChange(changes) {\n //Execute the changes in the order they appear on the page. This is because the top slot often determines what the lower slots display.\n\n /* istanbul ignore next */\n changes.filter(a => a.intersectionRect.height || a.intersectionRect.width || a.intersectionRect.top || a.intersectionRect.left).sort((a, b) => a.intersectionRect.top - b.intersectionRect.top).forEach(change => {\n const slotName = change.target.getAttribute(\"data-o-ads-name\");\n /* istanbul ignore else */\n\n if (slotName) {\n invokeMethodOnSlots.call(this, slotName, \"render\");\n }\n });\n } // If we don't already have an instance of the observer, and it is enabled globally or on a slot (force), then create one.\n\n /* istanbul ignore else\t*/\n\n\n if (\"IntersectionObserver\" in window && !lazyLoadingObserver && Boolean(lazyLoadingConfig)) {\n const options = {};\n /* istanbul ignore else\t*/\n\n if (typeof lazyLoadingConfig === \"object\") {\n /* istanbul ignore else\t*/\n if (lazyLoadingConfig.viewportMargin) {\n options.rootMargin = lazyLoadingConfig.viewportMargin;\n }\n /* istanbul ignore else\t*/\n\n\n if (lazyLoadingConfig.threshold) {\n options.threshold = lazyLoadingConfig.threshold;\n }\n\n options.root = lazyLoadingConfig.root || null;\n }\n\n lazyLoadingObserver = new IntersectionObserver(onChange.bind(this), options);\n this.lazyLoadingObservers.push(lazyLoadingObserver);\n }\n\n return lazyLoadingObserver;\n};\n\nSlots.prototype.forEach = function (fn) {\n Object.keys(this).forEach(name => {\n const slot = this[name];\n /* istanbul ignore else\t*/\n\n if (slot instanceof Slot) {\n fn.call(this, slot);\n }\n });\n return this;\n};\n/*\n * Initialise slots\n */\n\n\nSlots.prototype.init = function () {\n this.initRefresh();\n this.initRendered();\n this.initResponsive();\n this.initPostMessage();\n this.initLazyLoading();\n};\n\nSlots.prototype.debug = function () {\n debug$1(Object.values(this));\n};\n\nvar slots = new Slots();\n\nlet parameters = {};\n\nfunction Targeting() {} //eslint-disable-line no-empty-function\n\n\nTargeting.prototype.get = function () {\n const methods = {\n socialReferrer: this.getSocialReferrer,\n timestamp: this.timestamp,\n responsive: this.responsive\n };\n utils.extend(parameters, this.socialFlow(), this.getVersion());\n\n for (const item in methods) {\n /* istanbul ignore else */\n // eslint-disable-next-line no-prototype-builtins\n if (methods.hasOwnProperty(item)) {\n utils.extend(parameters, methods[item]());\n }\n }\n\n return parameters;\n};\n\nTargeting.prototype.add = function (obj) {\n /* istanbul ignore else */\n if (utils.isPlainObject(obj)) {\n utils.extend(parameters, obj);\n }\n};\n\nTargeting.prototype.remove = function (key) {\n /* istanbul ignore else */\n if (parameters[key]) {\n delete parameters[key];\n }\n};\n\nTargeting.prototype.clear = function () {\n parameters = {};\n};\n\nTargeting.prototype.getVersion = function () {\n if (config$1(\"passOAdsVersion\")) {\n return {\n OADS_VERSION: utils.getVersion()\n };\n }\n};\n/**\n * If there is a query parameter called socialflow=xxx, we need to add it\n * as a tag\n */\n\n\nTargeting.prototype.socialFlow = function () {\n const sf = utils.getQueryParamByName(\"socialflow\");\n\n if (sf) {\n return {\n socialflow: sf\n };\n }\n};\n\nTargeting.prototype.getSocialReferrer = function () {\n let codedValue;\n const referrer = utils.getReferrer(); // TODO: add on.ft.com\n\n const lookup = {\n \"t.co\": \"twi\",\n \"facebook.com\": \"fac\",\n \"linkedin.com\": \"lin\",\n \"drudgereport.com\": \"dru\",\n \"dianomi.com\": \"dia\",\n google: \"goo\"\n };\n Object.keys(lookup).forEach(url => {\n const refererRegex = new RegExp(`^http(|s)://(www.)*(${url})`);\n /* istanbul ignore else */\n\n if (refererRegex.test(referrer)) {\n codedValue = lookup[url];\n }\n });\n return codedValue && {\n socref: codedValue\n } || {};\n};\n\nTargeting.prototype.searchTerm = function () {\n const qs = utils.hash(utils.getQueryString(), /&|;/, \"=\");\n let keywords = qs.q || qs.s || qs.query || qs.queryText || qs.searchField || undefined;\n /* istanbul ignore else\t*/\n\n if (keywords && keywords !== \"\") {\n keywords = unescape(keywords).toLowerCase().replace(/[';^+]/g, \" \").replace(/\\s+/g, \" \").trim();\n }\n\n return {\n kw: keywords\n };\n};\n\nTargeting.prototype.timestamp = function () {\n return {\n ts: utils.getTimestamp()\n };\n};\n\nTargeting.prototype.responsive = function () {\n return config$1(\"responsive\") ? {\n res: utils.responsive.getCurrent()\n } : {};\n};\n\nTargeting.prototype.debug = function () {\n const log = utils.log;\n const parameters = this.get();\n /* istanbul ignore else */\n\n if (Object.keys(parameters).length !== 0) {\n log.start(\"Targeting\");\n log.attributeTable(this.get());\n log.end();\n }\n};\n\nvar targeting = new Targeting();\n\nconst SEARCH_PARAMS = [\"q\", \"kw\"];\n/**\n * @typedef {{ [key: string]: string[] }} FilterDict\n */\n\n/**\n * Remove unwanted params from nested query strings\n *\n * @param {string} nestedParams the URIencoded nested params\n * @param {string[]} keysToStrip the parameters to remove\n *\n * @return {string} [return description]\n */\n\nfunction filterNestedParams(nestedParams, keysToStrip) {\n if (!keysToStrip || keysToStrip.length < 1) {\n return nestedParams;\n }\n\n const childParams = new URLSearchParams(nestedParams);\n\n for (const key of keysToStrip) {\n childParams.delete(key);\n }\n\n return childParams.toString();\n}\n/**\n * Purge a URL of sensitive data in query strings\n *\n * Given the URL\n * ```url\n * https://www.ft.com/search?q=goog&cust_params=a%3D1%26b%3D2%26c%3D3%26d%3D4\n * ```\n * Supplying an object in the form\n * ```\n * {\n * root: ['q', 'kw'],\n * cust_params: ['a', 'c']\n * }\n * ```\n * will remove `q` from the main query string and `a`, `c` from the nested params\n * under `cust_params`:\n * ```url\n * https://www.ft.com/search?cust_params=b=2%26d%3D4\n * ```\n *\n * @param {Object} params\n * @param {string | Location} params.href The base URL or `window.location`\n * @param {FilterDict} params.filters The dictionary of params to be removed\n *\n * @return {string} A URL that has been stripped of the supplied params\n */\n\nfunction stripUrlParams({\n href,\n filters\n}) {\n // @ts-ignore: URL absolutely accepts Location!\n const url = new URL(href);\n\n for (const [param, filter] of Object.entries(filters)) {\n if (param === \"root\") {\n // Strip parameters from the main query string\n for (const key of filter) {\n url.searchParams.delete(key);\n }\n } else {\n // Handle nested parameters\n const nestedParams = url.searchParams.get(param);\n\n if (nestedParams) {\n url.searchParams.set(param, filterNestedParams(nestedParams, filter));\n }\n }\n }\n\n return url.href;\n}\n\n/*globals googletag: true */\nconst DEFAULT_LAZY_LOAD = {\n fetchMarginPercent: 500,\n renderMarginPercent: 200,\n mobileScaling: 2.0\n};\nconst DEFAULT_COLLAPSE_MODE = \"never\";\nlet breakpoints = false;\n/*\n//###########################\n// Initialisation handlers ##\n//###########################\n*/\n\n/*\n * Initialise Google publisher tags functionality\n */\n\nfunction init() {\n const gptConfig = config$1(\"gpt\") || {};\n breakpoints = config$1(\"responsive\");\n loadGPT();\n utils.on(\"slotReady\", onReady.bind(null, slotMethods));\n utils.on(\"slotCanRender\", onRender);\n utils.on(\"refresh\", onRefresh);\n utils.on(\"resize\", onResize);\n googletag.cmd.push(setup.bind(null, gptConfig));\n}\n/*\n * initalise the googletag global namespace and add the google publish tags library to the page\n */\n\n\nfunction loadGPT() {\n if (!window.googletag) {\n // set up a place holder for the gpt code downloaded from google\n window.googletag = {}; // this is a command queue used by GPT any methods added to it will be\n // executed when GPT code is available, if GPT is already available they\n // will be executed immediately\n\n window.googletag.cmd = [];\n }\n\n utils.attach(\"//securepubads.g.doubleclick.net/tag/js/gpt.js\", true, () => {\n utils.broadcast(\"serverScriptLoaded\");\n }, err => {\n utils.broadcast(\"adServerLoadError\", err);\n });\n}\n/*\n//#################################\n// Global configuration handlers ##\n//#################################\n*/\n\n/*\n * Configure the GPT library for the current page\n * this method is pushed onto the googletag command queue and run\n * when the library is available\n */\n\n\nfunction setup(gptConfig) {\n const nonPersonalized = config$1(\"nonPersonalized\") ? 1 : 0;\n googletag.pubads().addEventListener(\"slotRenderEnded\", onRenderEnded);\n enableCompanions(gptConfig);\n setRenderingMode(gptConfig);\n setPageTargeting(targeting.get());\n setPageCollapseEmpty(); // eslint-disable-next-line no-prototype-builtins\n\n if (gptConfig.hasOwnProperty(\"enableLazyLoad\")) {\n enableLazyLoad(gptConfig.enableLazyLoad);\n }\n\n const url = stripUrlParams({\n href: window.location.href,\n filters: {\n root: SEARCH_PARAMS\n }\n });\n googletag.enableServices();\n googletag.pubads().setTargeting(\"url\", url);\n googletag.pubads().setRequestNonPersonalizedAds(nonPersonalized);\n return true;\n}\n/**\n * Enables GPT's Lazy Loading for serving ads only when it's necessary.\n * \t\tThe lazy load config ooptions are:\n *\n * \t\t\t- fetchMarginPercent,\t\tminimum distance from the current viewport a slot\n * \t\t\t\t\tmust be before we fetch the ad as a percentage of viewport size.\n * \t\t\t\t\t0 means \"when the slot enters the viewport\",\n * \t\t\t\t\t100 means \"when the ad is 1 viewport away\"\n *\n * \t\t\t- renderMarginPercent,\tminimum distance from the current viewport a slot\n * \t\t\t\t\tmust be before we render an ad.\n * \t\t\t\t\tThis allows for prefetching the ad, but waiting to render and\n * \t\t\t\t\tdownload other subresources. The value works just like\n * \t\t\t\t\tfetchMarginPercent as a percentage of viewport.\n *\n * \t\t\t- mobileScaling,\t\t\t\ta multiplier applied to margins on mobile devices.\n * \t\t\t\t\tThis allows varying margins on mobile vs. desktop. For example,\n * \t\t\t\t\ta mobileScaling of 2.0 will multiply all margins by 2 on mobile\n * \t\t\t\t\tdevices, increasing the minimum distance a slot can be before\n * \t\t\t\t\tfetching and rendering.\n *\n * @param {object|boolean} lazyLoadConf The lazy load config object or a boolean.\n * @returns {boolean} true if the object is of type Array, otherwise false\n */\n\n\nfunction enableLazyLoad(lazyLoadConf) {\n if (lazyLoadConf && (typeof lazyLoadConf === \"object\" || typeof lazyLoadConf === \"boolean\")) {\n const opts = Object.assign({}, DEFAULT_LAZY_LOAD, typeof lazyLoadConf === \"object\" ? lazyLoadConf : {});\n window.googletag.pubads().enableLazyLoad(opts);\n } else {\n utils.log.warn(\"lazyLoadConf must be either an object or a boolean\", lazyLoadConf);\n }\n}\n/*\n * set the gpt rendering mode to either sync or async\n * default is async\n */\n\n\nfunction setRenderingMode(gptConfig) {\n const rendering = gptConfig.rendering;\n\n if (rendering === \"sync\") {\n googletag.pubads().enableSyncRendering();\n } else if (rendering === \"sra\") {\n googletag.pubads().enableSingleRequest();\n } else {\n googletag.pubads().enableAsyncRendering();\n }\n}\n/**\n * Adds page targeting to GPT ad calls\n * @name setPageTargeting\n * @memberof GPT\n * @lends GPT\n */\n\n\nfunction setPageTargeting(targetingData) {\n if (utils.isPlainObject(targetingData)) {\n googletag.cmd.push(() => {\n const pubads = googletag.pubads();\n Object.keys(targetingData).forEach(key => {\n // Convert to string as boolean values are invalid arguments for GPT setTargeting()\n pubads.setTargeting(key, String(targetingData[key]));\n });\n });\n } else {\n /* istanbul ignore next */\n utils.log.warn(\"invalid targeting object passed\", targetingData);\n }\n\n return targetingData;\n}\n/**\n * Removes page targeting for a specified key from GPT ad calls\n */\n\n\nfunction clearPageTargetingForKey(key) {\n if (!window.googletag) {\n utils.log.warn(\"Attempting to clear page targeting before the GPT library has initialized\");\n return;\n }\n\n if (!key) {\n utils.log.warn(\"Refusing to unset all keys - a key must be specified\");\n return;\n }\n\n googletag.cmd.push(() => {\n googletag.pubads().clearTargeting(key);\n });\n}\n/**\n * Sets behaviour of empty slots can be 'after', 'before' or 'never'\n * * 'after' collapse slots that return an empty ad\n * * 'before' collapses all slots and only displays them when an ad is found\n * * 'never' does not collapse any empty slot, the collapseEmptyDivs method is not called in that case\n */\n\n\nfunction setPageCollapseEmpty() {\n const mode = config$1(\"collapseEmpty\");\n\n if (mode === \"before\") {\n googletag.pubads().collapseEmptyDivs(true);\n }\n\n if (mode === \"after\") {\n googletag.pubads().collapseEmptyDivs(false);\n }\n}\n/**\n * When companions are enabled we delay the rendering of ad slots until\n * either a master is returned or all slots are returned without a master\n */\n\n\nfunction enableCompanions(gptConfig) {\n if (gptConfig.companions) {\n googletag.pubads().disableInitialLoad();\n googletag.companionAds().setRefreshUnfilledSlots(true);\n }\n}\n/*\n//##################\n// Event handlers ##\n//##################\n*/\n\n/*\n * Event handler for when a slot is ready for an ad to rendered\n */\n\n\nfunction onReady(slotMethods, event) {\n const slot = event.detail.slot;\n /* istanbul ignore else */\n\n if (slot.server === \"gpt\") {\n slot.gpt = {}; // extend the slot with gpt methods\n\n utils.extend(slot, slotMethods); // setup the gpt configuration the ad\n\n googletag.cmd.push(() => {\n slot.defineSlot().addServices().setCollapseEmpty().setTargeting().setURL();\n\n if (!slot.defer && slot.hasValidSize()) {\n slot.display();\n }\n });\n }\n}\n/*\n * Render is called when a slot is not rendered when the ready event fires\n */\n\n\nfunction onRender(event) {\n const slot = event.detail.slot;\n /* istanbul ignore else */\n\n if (utils.isFunction(slot.display)) {\n slot.display();\n }\n}\n/*\n * refresh is called when a slot requests the ad be flipped\n */\n\n\nfunction onRefresh(event) {\n window.googletag.cmd.push(() => {\n const targeting = event.detail.targeting;\n\n if (utils.isPlainObject(targeting)) {\n Object.keys(targeting).forEach(name => {\n event.detail.slot.gpt.slot.setTargeting(name, targeting[name]);\n });\n }\n\n googletag.pubads().refresh([event.detail.slot.gpt.slot]);\n });\n return this;\n}\n\nfunction onResize(event) {\n const iframe = event.detail.slot.gpt.iframe;\n const size = event.detail.size;\n iframe.width = size[0];\n iframe.height = size[1];\n}\n/*\n * function passed to the gpt library that is run when an ad completes rendering\n */\n\n\nfunction onRenderEnded(event) {\n const data = {\n gpt: {}\n };\n const gptSlotId = event.slot.getSlotId();\n const domId = gptSlotId.getDomId().split(\"-\");\n const iframeId = `google_ads_iframe_${gptSlotId.getId()}`;\n data.type = domId.pop();\n data.name = domId.join(\"-\");\n data.size = event.size && event.size.length ? event.size.join() : \"\";\n data.creativeId = event.creativeId;\n const slotTargeting = event.slot.getTargetingMap && event.slot.getTargetingMap();\n\n if (slotTargeting && slotTargeting.pos) {\n data.pos = slotTargeting.pos.length ? slotTargeting.pos.join() : \"\";\n }\n\n const detail = data.gpt;\n detail.isEmpty = event.isEmpty;\n detail.size = event.size;\n detail.creativeId = event.creativeId;\n detail.lineItemId = event.lineItemId;\n detail.serviceName = event.serviceName;\n const iFrameEl = document.getElementById(iframeId);\n\n if (iFrameEl) {\n iFrameEl.setAttribute(\"tabindex\", \"-1\");\n iFrameEl.setAttribute(\"aria-hidden\", \"true\");\n iFrameEl.setAttribute(\"role\", \"presentation\");\n iFrameEl.setAttribute(\"title\", \"Advertisement\");\n detail.iframe = iFrameEl;\n } else {\n /* istanbul ignore next */\n utils.log.warn(\"No iFrame found matching GPT SlotID\");\n }\n\n utils.broadcast(\"slotRenderStart\", data);\n}\n/*\n//################\n// Slot methods ##\n//################\n* Set of methods extended on to the slot constructor for GPT served slots\n*/\n\n\nconst slotMethods = {\n /**\n * define a GPT slot\n */\n defineSlot: function () {\n window.googletag.cmd.push(() => {\n this.gpt.id = `${this.name}-gpt`;\n this.inner.setAttribute(\"id\", this.gpt.id);\n this.setUnitName();\n\n if (!this.outOfPage) {\n if (breakpoints && utils.isObject(this.sizes)) {\n this.initResponsive();\n this.gpt.slot = googletag.defineSlot(this.gpt.unitName, [0, 0], this.gpt.id).defineSizeMapping(this.gpt.sizes);\n } else {\n this.gpt.slot = googletag.defineSlot(this.gpt.unitName, this.sizes, this.gpt.id);\n }\n } else {\n this.gpt.slot = googletag.defineOutOfPageSlot(this.gpt.unitName, this.gpt.id);\n }\n });\n return this;\n },\n clearSlot: function (gptSlot) {\n if (window.googletag.pubadsReady && window.googletag.pubads) {\n gptSlot = gptSlot || this.gpt.slot;\n return googletag.pubads().clear([gptSlot]);\n } else {\n return false;\n }\n },\n initResponsive: function () {\n window.googletag.cmd.push(() => {\n utils.on(\"breakpoint\", event => {\n const slot = event.detail.slot;\n const screensize = event.detail.screensize;\n updatePageTargeting({\n res: screensize\n });\n\n if (slot.hasValidSize(screensize)) {\n /* istanbul ignore else */\n if (slot.gpt.iframe) {\n slot.fire(\"refresh\");\n } else if (!this.defer) {\n slot.display();\n }\n }\n }, this.container);\n const mapping = googletag.sizeMapping();\n Object.keys(breakpoints).forEach(breakpoint => {\n if (this.sizes[breakpoint]) {\n mapping.addSize(breakpoints[breakpoint], this.sizes[breakpoint]);\n }\n });\n this.gpt.sizes = mapping.build();\n });\n return this;\n },\n\n /**\n * Tell gpt to destroy the slot and its metadata\n */\n destroySlot: function (gptSlot) {\n if (window.googletag.pubadsReady && window.googletag.pubads) {\n gptSlot = gptSlot || this.gpt.slot;\n return googletag.destroySlots([gptSlot]);\n } else {\n return false;\n }\n },\n\n /*\n *\tTell gpt to request an ad\n */\n display: function () {\n window.googletag.cmd.push(() => {\n this.fire(\"slotGoRender\");\n googletag.display(this.gpt.id);\n });\n return this;\n },\n\n /**\n * Set the DFP unit name for the slot.\n */\n setUnitName: function () {\n window.googletag.cmd.push(() => {\n let unitName;\n const gpt = config$1(\"gpt\") || {};\n const attr = this.container.getAttribute(\"data-o-ads-gpt-unit-name\");\n\n if (utils.isNonEmptyString(attr)) {\n unitName = attr;\n } else if (utils.isNonEmptyString(gpt.unitName)) {\n unitName = gpt.unitName;\n } else {\n const network = gpt.network;\n const site = gpt.site;\n const zone = gpt.zone;\n unitName = `/${network}`;\n unitName += utils.isNonEmptyString(site) ? `/${site}` : \"\";\n unitName += utils.isNonEmptyString(zone) ? `/${zone}` : \"\";\n }\n\n this.gpt.unitName = unitName;\n });\n return this;\n },\n\n /**\n * Add the slot to the pub ads service and add a companion service if configured\n */\n addServices: function (gptSlot) {\n window.googletag.cmd.push(() => {\n const gpt = config$1(\"gpt\") || {};\n gptSlot = gptSlot || this.gpt.slot;\n gptSlot.addService(googletag.pubads());\n\n if (gpt.companions && this.companion !== false) {\n gptSlot.addService(googletag.companionAds());\n }\n });\n return this;\n },\n\n /**\n * Sets the GPT collapse empty mode for a given slot\n * values can be 'after', 'before', 'never'\n */\n setCollapseEmpty: function () {\n window.googletag.cmd.push(() => {\n const mode = this.collapseEmpty || config$1(\"collapseEmpty\") || DEFAULT_COLLAPSE_MODE;\n\n if (mode === \"before\") {\n this.gpt.slot.setCollapseEmptyDiv(true, true);\n } else if (mode === \"after\") {\n this.gpt.slot.setCollapseEmptyDiv(true);\n } else if (mode === \"never\") {\n this.gpt.slot.setCollapseEmptyDiv(false);\n }\n });\n return this;\n },\n submitGptImpression: function () {\n /* istanbul ignore next */\n function getImpressionURL(iframe) {\n const trackingUrlElement = iframe.contentWindow.document.querySelector(\"[data-o-ads-impression-url]\");\n\n if (trackingUrlElement) {\n return trackingUrlElement.dataset.oAdsImpressionUrl;\n } else {\n utils.log.warn(\"Impression URL not found, this is set via a creative template.\");\n return false;\n }\n }\n\n if (this.outOfPage && this.gpt.iframe) {\n const impressionURL = getImpressionURL(this.gpt.iframe);\n /* istanbul ignore next */\n\n if (impressionURL) {\n utils.attach(impressionURL, true, () => {\n utils.log.info(\"Impression Url requested\");\n }, () => {\n utils.log.info(\"CORS request to submit an impression failed\");\n }, true);\n }\n } else {\n utils.log.warn(\"Attempting to call submitImpression on a non-oop slot\");\n }\n },\n\n /**\n * Sets page url to be sent to google\n * prevents later url changes via javascript from breaking the ads\n */\n setURL: function (gptSlot) {\n window.googletag.cmd.push(() => {\n gptSlot = gptSlot || this.gpt.slot;\n const canonical = config$1(\"canonical\");\n gptSlot.set(\"page_url\", canonical ? canonical : utils.getLocation());\n });\n return this;\n },\n\n /**\n * Adds key values from a given object to the slot targeting\n */\n setTargeting: function (gptSlot) {\n window.googletag.cmd.push(() => {\n gptSlot = gptSlot || this.gpt.slot;\n /* istanbul ignore else */\n\n if (utils.isPlainObject(this.targeting)) {\n Object.keys(this.targeting).forEach(param => {\n gptSlot.setTargeting(param, this.targeting[param]);\n });\n }\n });\n return this;\n }\n};\n/*\n//####################\n// External methods ##\n//####################\n*/\n\n/**\n * The correlator is a random number added to ad calls.\n * It is used by the ad server to determine which impressions where served to the same page\n * Updating is used to tell the ad server to treat subsequent ad calls as being on a new page\n */\n\nfunction updateCorrelator() {\n utils.log.warn(\"[DEPRECATED]: Updatecorrelator is being phased out by google and removed from o-ads in future releases.\");\n googletag.cmd.push(() => {\n googletag.pubads().updateCorrelator();\n });\n}\n\nfunction getCorrelator() {\n if (window.googletag && window.googletag.pubads) {\n return googletag.pubads().getCorrelator();\n }\n}\n\nfunction clearPageTargeting() {\n if (window.googletag) {\n googletag.cmd.push(() => {\n googletag.pubads().clearTargeting();\n });\n } else {\n utils.log.warn(\"Attempting to clear page targeting before the GPT library has initialized\");\n }\n}\n\nfunction updatePageTargeting(override) {\n if (window.googletag) {\n const params = utils.isPlainObject(override) ? override : targeting.get();\n setPageTargeting(params);\n } else {\n utils.log.warn(\"Attempting to set page targeting before the GPT library has initialized\");\n }\n} //https://developers.google.com/doubleclick-gpt/common_implementation_mistakes#scenario-2:-checking-the-googletag-object-to-know-whether-gpt-is-ready\n\n\nfunction hasGPTLoaded() {\n if (window.googletag && window.googletag.apiReady) {\n return true;\n } else {\n return false;\n }\n}\n\nfunction debug() {\n const log = utils.log;\n const conf = config$1(\"gpt\");\n\n if (!conf) {\n return;\n }\n\n log.start(\"gpt\");\n log.attributeTable(conf);\n log.end();\n}\n\nvar gpt = {\n init,\n setup,\n updateCorrelator,\n getCorrelator,\n updatePageTargeting,\n clearPageTargeting,\n clearPageTargetingForKey,\n hasGPTLoaded,\n loadGPT,\n debug\n};\n\n/* eslint valid-jsdoc: 0 */\n\nfunction Ads() {\n addDOMEventListener();\n\n if (window && !window.oAds) {\n window.oAds = this;\n }\n}\n\nconfig$1.init = init$1;\nconfig$1.clear = clear; // bung all our modules on the protoype\n\nAds.prototype.config = config$1;\nAds.prototype.slots = slots;\nAds.prototype.gpt = gpt;\nAds.prototype.targeting = targeting;\nAds.prototype.utils = utils;\n/**\n * Initialises the ads library and all sub modules\n * @param options {object} a JSON object containing configuration for the current page\n */\n\nAds.prototype.init = function (options) {\n options = options || {};\n this.config.init();\n const configOptions = Object.assign(options, {\n nonPersonalized: !options.disableConsentCookie\n });\n this.config(configOptions);\n\n if (options.disableConsentCookie) {\n this.consents = {\n behavioral: true\n };\n } else {\n this.consents = getConsents();\n }\n\n if (this.consents.behavioral) {\n this.utils.broadcast(\"consentBehavioral\");\n }\n\n if (this.consents.programmatic) {\n this.utils.broadcast(\"consentProgrammatic\");\n }\n\n this.utils.broadcast(\"initialising\");\n this.targeting.add(this.config().targeting);\n return Promise.resolve(this.initLibrary());\n};\n/**\n * Update page level targeting data in o-ads and GPT\n */\n\n\nAds.prototype.updateTargeting = function (data) {\n this.targeting.add(data);\n this.gpt.updatePageTargeting(this.targeting.get());\n};\n\nAds.prototype.initLibrary = function () {\n this.slots.init();\n\n if (this.consents.programmatic) {\n this.config({\n nonPersonalized: false\n });\n this.targeting.add({\n cc: \"y\"\n });\n }\n\n this.gpt.init();\n this.utils.on(\"debug\", this.debug.bind(this));\n this.isInitialised = true;\n this.utils.broadcast(\"initialised\", this);\n removeDOMEventListener();\n return this;\n};\n\nAds.prototype.debug = function () {\n let remove = true;\n\n if (localStorage.getItem(\"oAds\")) {\n remove = false;\n } else {\n localStorage.setItem(\"oAds\", true);\n }\n\n this.gpt.debug();\n this.slots.debug();\n this.targeting.debug();\n\n if (remove) {\n localStorage.removeItem(\"oAds\");\n }\n};\n\nAds.prototype.version = function () {\n this.utils.log.warn(\"DEPRECATION NOTICE: Ads.version() will be deprecated in favour of Ads.getVersion()\");\n this.utils.log(`o-ads version: ${this.utils.getVersion()}`);\n};\n\nAds.prototype.getVersion = function () {\n return this.utils.getVersion();\n};\n\nconst initAll = function () {\n return ads.init().then(() => {\n const slots = Array.from(document.querySelectorAll(\".o-ads, [data-o-ads-name]\"));\n slots.forEach(ads.slots.initSlot.bind(ads.slots));\n });\n};\n\nAds.prototype.initAll = initAll;\n\nfunction getConsents() {\n // derive consent options from ft consent cookie\n const re = /FTConsent=([^;]+)/;\n const match = document.cookie.match(re);\n\n if (!match) {\n // cookie stasis or no consent cookie found\n return {\n behavioral: false,\n programmatic: false\n };\n }\n\n const consentCookie = decodeURIComponent(match[1]);\n return {\n behavioral: consentCookie.indexOf(\"behaviouraladsOnsite:on\") !== -1,\n programmatic: consentCookie.indexOf(\"programmaticadsOnsite:on\") !== -1\n };\n}\n\nfunction addDOMEventListener() {\n document.addEventListener(\"o.DOMContentLoaded\", initAll);\n}\n\nfunction removeDOMEventListener() {\n document.removeEventListener(\"o.DOMContentLoaded\", initAll);\n}\n\nconst ads = new Ads();\n\nexport { ads as default };\n","\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst initLibrary_1 = require(\"../shared/initLibrary\");\nconst oAds_1 = __importDefault(require(\"../shared/oAds\"));\nconst validateTrafficScript_1 = require(\"../shared/scripts/validateTrafficScript\");\nconst insertCustomOAdsParams_1 = __importDefault(require(\"../shared/scripts/insertCustomOAdsParams\"));\nconst insertUserCustomOAdsParams_1 = require(\"../shared/scripts/insertUserCustomOAdsParams\");\ninsertUserCustomOAdsParams_1.getUserCustomOAdsParams();\ninitLibrary_1.onDocumentLoaded(() => {\n window.dataLayer = window.dataLayer || [];\n validateTrafficScript_1.validateTrafficIasScript(true); // true is passed to enable IAS' ad refresh\n insertCustomOAdsParams_1.default();\n oAds_1.default();\n});\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.onDocumentLoaded = exports.onDocumentReady = void 0;\nfunction onDocumentReady(initLibrary) {\n if (document.readyState !== 'loading') {\n initLibrary();\n }\n else {\n document.addEventListener('DOMContentLoaded', () => {\n initLibrary();\n });\n }\n}\nexports.onDocumentReady = onDocumentReady;\nfunction onDocumentLoaded(initLibrary) {\n if (document.readyState == 'complete') {\n initLibrary();\n }\n else {\n window.addEventListener('load', () => {\n initLibrary();\n });\n }\n}\nexports.onDocumentLoaded = onDocumentLoaded;\n","\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\n// @ts-ignore\nconst ads_legacy_o_ads_1 = __importDefault(require(\"@financial-times/ads-legacy-o-ads\"));\nfunction initOAds() {\n // firing the o.DOMContentLoaded event should be made with caution because both legacy-o-ads and o-cookie-message listen for it\n ads_legacy_o_ads_1.default.initAll();\n}\nexports.default = initOAds;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.updateAdsConfig = exports.extractCookieAsObj = exports.extractStateFromDOM = void 0;\nconst utils_1 = require(\"../utils\");\nconst insertUserCustomOAdsParams_1 = require(\"./insertUserCustomOAdsParams\");\nconst snowplow_1 = require(\"./snowplow\");\nfunction insertCustomOAdsParams() {\n const oAdsConfig = exports.extractStateFromDOM('data-o-ads-config') || {};\n if (!oAdsConfig.targeting)\n oAdsConfig.targeting = {};\n setFTPageviewId(oAdsConfig);\n setUserData(oAdsConfig);\n setDomainUserId(oAdsConfig);\n setPtTargeting(oAdsConfig);\n setSiteTargeting(oAdsConfig);\n if (isPageArticle()) {\n setArticleData(oAdsConfig);\n }\n exports.updateAdsConfig(oAdsConfig);\n}\nexports.default = insertCustomOAdsParams;\nconst extractStateFromDOM = (nodeId) => {\n const node = document.getElementById(nodeId);\n return JSON.parse(decodeURIComponent(node === null || node === void 0 ? void 0 : node.innerHTML));\n};\nexports.extractStateFromDOM = extractStateFromDOM;\nconst extractCookieAsObj = (match) => {\n let cookie = undefined;\n try {\n cookie = match ? JSON.parse(window.atob(match)) : undefined;\n }\n catch (e) {\n console.error('Failed to parse cookie: ', match);\n }\n return cookie;\n};\nexports.extractCookieAsObj = extractCookieAsObj;\nconst updateAdsConfig = (oAdsConfig) => {\n const oAdsConfigElement = document.getElementById('data-o-ads-config');\n if (oAdsConfigElement) {\n oAdsConfigElement.innerHTML = JSON.stringify(oAdsConfig);\n }\n};\nexports.updateAdsConfig = updateAdsConfig;\nfunction isPageHome() {\n if (!window.dataLayer)\n return false;\n return window.dataLayer.some(entry => { var _a, _b; return ((_b = (_a = entry === null || entry === void 0 ? void 0 : entry.page) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.asset_type) == 'homepage'; });\n}\nfunction isPageTop() {\n if (!window.dataLayer)\n return false;\n return window.dataLayer.some(entry => { var _a, _b; return ((_b = (_a = entry === null || entry === void 0 ? void 0 : entry.page) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.asset_type) == 'top_page'; });\n}\nfunction isPageStream() {\n if (!window.dataLayer)\n return false;\n return window.dataLayer.some(entry => { var _a, _b; return ((_b = (_a = entry === null || entry === void 0 ? void 0 : entry.page) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.asset_type) == 'stream_page'; });\n}\nfunction isPageArticle() {\n if (!window.dataLayer)\n return false;\n return window.dataLayer.some(entry => !!entry.article);\n}\nfunction setFTPageviewId(oAdsConfig) {\n window.ft_pageview_id = window.ft_pageview_id || (Math.round(Math.random() * 10000000000000000));\n oAdsConfig.targeting.ft_pageview_id = window.ft_pageview_id;\n}\nfunction setUserData(oAdsConfig) {\n const specialistStateCookie = exports.extractCookieAsObj(utils_1.getCookie('specialist-state'));\n if (specialistStateCookie === null || specialistStateCookie === void 0 ? void 0 : specialistStateCookie.id)\n oAdsConfig.targeting.uuidId = specialistStateCookie === null || specialistStateCookie === void 0 ? void 0 : specialistStateCookie.id;\n if (specialistStateCookie === null || specialistStateCookie === void 0 ? void 0 : specialistStateCookie.type) {\n oAdsConfig.targeting.loggedin = specialistStateCookie.type === 'anonymous' ? 'No' : 'Yes';\n oAdsConfig.targeting.usertype = specialistStateCookie === null || specialistStateCookie === void 0 ? void 0 : specialistStateCookie.type;\n }\n if (insertUserCustomOAdsParams_1.isUserCustomOAdsParamsEnabled()) {\n oAdsConfig.targeting = Object.assign(Object.assign({}, oAdsConfig.targeting), (window._specialist_user_data || {}));\n }\n}\nfunction setDomainUserId(oAdsConfig) {\n const domainUserId = snowplow_1.getDomainUserId();\n if (domainUserId)\n oAdsConfig.targeting.domainUserId = snowplow_1.getDomainUserId();\n}\nfunction setArticleData(oAdsConfig) {\n var _a, _b, _c;\n const data = window.dataLayer.find(item => !!item.article);\n if (!data || !data.article || !data.article.data)\n return;\n const { article } = data;\n if (!oAdsConfig.targeting.primary_tag && ((_a = article === null || article === void 0 ? void 0 : article.data) === null || _a === void 0 ? void 0 : _a.content_category)) {\n oAdsConfig.targeting.primary_tag = (_b = article === null || article === void 0 ? void 0 : article.data) === null || _b === void 0 ? void 0 : _b.content_category;\n }\n if (!oAdsConfig.targeting.uuid && ((_c = article === null || article === void 0 ? void 0 : article.data) === null || _c === void 0 ? void 0 : _c.content_id)) {\n oAdsConfig.targeting.uuid = article.data.content_id;\n }\n}\nfunction setPtTargeting(oAdsConfig) {\n if (oAdsConfig.targeting.pt)\n return;\n if (isPageHome())\n oAdsConfig.targeting.pt = 'fro';\n if (isPageTop())\n oAdsConfig.targeting.pt = 'ind';\n if (isPageStream())\n oAdsConfig.targeting.pt = 'str';\n if (isPageArticle())\n oAdsConfig.targeting.pt = 'art';\n}\nfunction setSiteTargeting(oAdsConfig) {\n oAdsConfig.targeting.site = oAdsConfig.gpt.site;\n}\n","\"use strict\";\nvar __rest = (this && this.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getUserCustomOAdsParams = exports.isUserCustomOAdsParamsEnabled = void 0;\nconst utils_1 = require(\"../utils\");\nconst snowplow_1 = require(\"./snowplow\");\nconst CURRENT_VERSION = '2.1';\nconst USER_CUSTOM_AD_PARAMS = 'user-custom-ad-params';\nconst enabledTitles = ['pwm', 'fta', 'tb', 'brr', 'ic', 'fdi'];\nconst isUserCustomOAdsParamsEnabled = () => {\n const code = snowplow_1.getAppTitleCode();\n return code ? enabledTitles.includes(code) : false;\n};\nexports.isUserCustomOAdsParamsEnabled = isUserCustomOAdsParamsEnabled;\nconst isDemographicAdsEnabled = () => {\n const ftConsentCookieValue = utils_1.getCookie('FTConsent');\n return ftConsentCookieValue && decodeURIComponent(ftConsentCookieValue).indexOf('demographicadsOnsite:on') !== -1;\n};\nconst setWindowData = (_a) => {\n var { version, expiry } = _a, adsDemographics = __rest(_a, [\"version\", \"expiry\"]);\n return window._specialist_user_data = adsDemographics;\n};\nconst getUserCustomOAdsParams = () => {\n if (!exports.isUserCustomOAdsParamsEnabled() || !isDemographicAdsEnabled())\n return;\n const data = utils_1.getLocalStorageObject(USER_CUSTOM_AD_PARAMS);\n if (data)\n setWindowData(data);\n if (data && data.version === CURRENT_VERSION && new Date().getTime() < data.expiry)\n return;\n if (window.fetch === undefined || !snowplow_1.getDomainUserId())\n return;\n let endpoint = '/api/user/adsdemographic';\n // ensure the cross origin succces for the IC markets subdomain\n const requestOptions = { credentials: 'include' };\n if (window.location.hostname === 'markets.investorschronicle.co.uk') {\n endpoint = '/api/user/adsdemographic';\n }\n fetch(endpoint, requestOptions)\n .then(res => res.json())\n .then(userData => {\n // if no meaningful data was returned - don't cache and don't target\n if (!userData || Object.keys(userData).every(key => !userData[key]))\n return;\n userData.version = CURRENT_VERSION;\n const EXPIRY_TIME_MS = 7 * 24 * 60 * 60 * 1000; // 7 Days\n utils_1.updateLocalStorageWithExpiry(USER_CUSTOM_AD_PARAMS, userData, EXPIRY_TIME_MS);\n setWindowData(userData);\n })\n .catch(e => console.warn('Error getting user demographic data', e));\n};\nexports.getUserCustomOAdsParams = getUserCustomOAdsParams;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getDomainUserId = exports.getAppTitleCode = exports.titleCookies = void 0;\nconst utils_1 = require(\"../utils\");\nconst titles = {\n brr: 'bankingriskandregulation.com',\n fdi: 'fdiintelligence.com',\n fta: 'ftadviser.com',\n ic: 'investorschronicle.co.uk',\n pwm: 'pwmnet.com',\n sv: 'sustainableviews.com',\n tb: 'thebanker.com',\n};\nexports.titleCookies = {\n brr: 'sp_ft_id.c447',\n fdi: 'sp_ft_id.ca7e',\n fta: 'sp_ft_id.f776',\n ic: 'sp_ft_id.a53d',\n pwm: 'sp_ft_id.4a89',\n sv: 'sp_ft_id.7f6d',\n tb: 'sp_ft_id.5be3',\n};\nlet code;\nfunction getAppTitleCode() {\n var _a;\n if (!code) {\n code = (_a = Object.entries(titles).find(([_, value]) => window.location.hostname.endsWith(value))) === null || _a === void 0 ? void 0 : _a[0];\n }\n return code;\n}\nexports.getAppTitleCode = getAppTitleCode;\nconst getTitleCookieId = () => {\n const titleCode = getAppTitleCode();\n return titleCode ? exports.titleCookies[titleCode] : null;\n};\nconst getDomainUserId = () => {\n const cookieId = getTitleCookieId();\n if (!cookieId) {\n return '';\n }\n const domainUserIdCookie = utils_1.getCookie(cookieId);\n if (!domainUserIdCookie) {\n return '';\n }\n return domainUserIdCookie.split('.')[0];\n};\nexports.getDomainUserId = getDomainUserId;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.validateTrafficIasScript = void 0;\n// @ts-nocheck\nconst IAS_SCRIPT_URL = \"https://cdn.adsafeprotected.com/iasPET.1.js\";\nconst IAS_PUB_ID = \"931682\";\nconst IASPET_TIMEOUT = 1000;\nconst IAS_SCRIPT_ID = \"ads-script-ias\";\nlet slotDisplayQueue = [];\nfunction attachIasScript(refresh) {\n window.__iasPET = window.__iasPET || {};\n window.__iasPET.queue = window.__iasPET.queue || [];\n window.__iasPET.pubId = IAS_PUB_ID;\n const existingScript = document.getElementById(IAS_SCRIPT_ID);\n if (existingScript) {\n return;\n }\n const script = document.createElement(\"script\");\n script.defer = true;\n script.src = IAS_SCRIPT_URL;\n script.id = IAS_SCRIPT_ID;\n document.head.appendChild(script);\n refresh && updateIasConfig();\n}\nfunction updateIasConfig() {\n window.__iasAdRefreshConfig = window.__iasAdRefreshConfig || {};\n window.__iasAdRefreshConfig.refreshTargeting = {\n enabled: true,\n targetingKey: 'rfv',\n };\n window.__iasAdRefreshConfig.excludeList = {\n pos: ['skins', 'searchsponsor', 'startrading', 'newssubs']\n };\n}\nfunction requestAds() {\n const displaySlot = (slot) => () => {\n slot.fire(\"slotGoRender\");\n window.googletag.display(slot.gpt.id);\n };\n slotDisplayQueue.forEach((slot) => {\n const fn = displaySlot(slot);\n if (slot.displayCalled)\n window.googletag.cmd.push(fn);\n else\n slot.display = () => window.googletag.cmd.push(fn);\n });\n}\nconst __iasPETTimeoutRequestAds = setTimeout(requestAds, IASPET_TIMEOUT);\nfunction iasDataHandler() {\n clearTimeout(__iasPETTimeoutRequestAds);\n window.__iasPET.setTargetingForGPT();\n requestAds();\n}\nconst prepareAndPushPETSlot = (event) => {\n var _a;\n if ((_a = event === null || event === void 0 ? void 0 : event.detail) === null || _a === void 0 ? void 0 : _a.slot) {\n const slot = event.detail.slot;\n slotDisplayQueue.push(slot);\n if (slot.display) {\n slot.display = () => {\n slot.displayCalled = true;\n };\n }\n }\n else {\n return;\n }\n window.googletag.cmd.push(() => {\n const gptSlots = window.googletag.pubads().getSlots();\n const iasPETSlots = gptSlots.map((slot) => {\n const sizes = slot.getSizes().map((size) => {\n if (size.getWidth && size.getHeight)\n return [size.getWidth(), size.getHeight()];\n else\n return [1, 1];\n });\n return {\n adSlotId: slot.getSlotElementId(),\n size: sizes,\n adUnitPath: slot.getAdUnitPath(),\n };\n });\n window.__iasPET.queue.push({\n adSlots: iasPETSlots,\n dataHandler: iasDataHandler,\n });\n });\n};\nconst validateTrafficIasScript = (refresh) => {\n attachIasScript(refresh);\n document.addEventListener(\"oAds.slotReady\", prepareAndPushPETSlot);\n};\nexports.validateTrafficIasScript = validateTrafficIasScript;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getCookie = exports.parseJSONSafe = exports.getLocalStorageObject = exports.updateLocalStorageWithExpiry = exports.getDocumentHeight = exports.getWindowYScroll = exports.getWindowHeight = exports.debounce = exports.waitFor = void 0;\n/**\n * Timeout function to wait for specific condition\n * before a passed functon is executed\n */\nconst waitFor = (isReady) => new Promise((resolve, reject) => {\n setTimeout(() => {\n if (isReady())\n return resolve();\n exports.waitFor(isReady).then(resolve);\n }, 10);\n});\nexports.waitFor = waitFor;\n/**\n * Debounce function with 100ms default delay\n */\nfunction debounce(fn, ms = 100) {\n let timeoutId;\n return function (...args) {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => fn.apply(this, args), ms);\n };\n}\nexports.debounce = debounce;\n;\n/**\n * Get current browser view pane height\n */\nfunction getWindowHeight() {\n return window.innerHeight ||\n document.documentElement.clientHeight ||\n document.body.clientHeight || 0;\n}\nexports.getWindowHeight = getWindowHeight;\n/**\n* Get current absolute window scroll position\n*/\nfunction getWindowYScroll() {\n return window.pageYOffset ||\n document.body.scrollTop ||\n document.documentElement.scrollTop || 0;\n}\nexports.getWindowYScroll = getWindowYScroll;\n/**\n* Get current absolute document height\n*/\nfunction getDocumentHeight() {\n return Math.max(document.body.scrollHeight || 0, document.documentElement.scrollHeight || 0, document.body.offsetHeight || 0, document.documentElement.offsetHeight || 0, document.body.clientHeight || 0, document.documentElement.clientHeight || 0);\n}\nexports.getDocumentHeight = getDocumentHeight;\n// localStorage utils\n/**\n * Adding JSON item in the localStorage with expiry time\n */\nconst updateLocalStorageWithExpiry = (key, data, expiryMs) => {\n localStorage.setItem(key, JSON.stringify(Object.assign(Object.assign({}, data), { expiry: new Date().getTime() + expiryMs })));\n};\nexports.updateLocalStorageWithExpiry = updateLocalStorageWithExpiry;\n/**\n * Getting a localStorage stringfied object\n */\nconst getLocalStorageObject = (key) => {\n const item = localStorage.getItem(key);\n return item ? exports.parseJSONSafe(item) : null;\n};\nexports.getLocalStorageObject = getLocalStorageObject;\n/**\n * Parse a string to JSON without failure\n */\nconst parseJSONSafe = (str) => {\n try {\n return JSON.parse(str);\n }\n catch (e) {\n return null;\n }\n};\nexports.parseJSONSafe = parseJSONSafe;\nconst getCookie = (name) => {\n const rawCookie = document.cookie;\n const match = rawCookie.match(new RegExp('(^| )' + name + '=([^;]+)'));\n return match ? match[2] : null;\n};\nexports.getCookie = getCookie;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tif(__webpack_module_cache__[moduleId]) {\n\t\treturn __webpack_module_cache__[moduleId].exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// startup\n// Load entry module\n// This entry module is referenced by other modules so it can't be inlined\n__webpack_require__(400);\n"],"sourceRoot":""}