{"version":3,"sources":["webpack:///./node_modules/@financial-times/ads-legacy-o-ads/dist/ads-legacy-o-ads.js"],"names":["perfMark","name","performance","window","LUX","msPerformance","webkitPerformance","mozPerformance","mark","clearMarks","buildPerfmarkSuffix","eventDetailsObj","suffix","_typeof","pos","size","creativeId","join","broadcast","eventName","data","target","document","body","documentElement","concat","opts","bubbles","cancelable","detail","length","toString","dispatchEvent","CustomEvent","on","callback","addEventListener","off","removeEventListener","once","event","srcElement","getMarksForEvents","events","markNames","map","getEntriesByName","marks","forEach","mName","pMarks","markName","replace","Math","round","startTime","mNameNoSuffix","pMarks2","clearPerfMarks","metricsDefinitions","groupsToClear","_ref","getEntriesByType","relevantGroupsMarks","filter","group","includes","spoorAction","eventsToClear","apply","_toConsumableArray","_ref2","match","getNavigationPerfMarks","desiredMarks","utils","isArray","navMarksArray","navMarks","setupMetrics","definitions","disableSampling","Array","eDef","inSample","sampleSize","triggers","trigger","sendMetricsOnEvent","this","log","warn","eMarkMap","listenOnInitialised","sendMetrics","multiple","eventDetails","navigation","Object","assign","eventPayload","category","action","timings","advert","correlator","oAds","gpt","getCorrelator","creative","isEmpty","markPageChange","breakpoints$1","current","messenger","post","message","source","JSON","stringify","arguments","top","postMessage","parse","e","getNearestBreakpoint","winner","dims","oViewport","getSize","keys","breakpoint","breakpointDims","width","height","fire","setCurrent","getCurrent","init$2","brps","cb","isFunction","listenTo","type","argsIndex","indexOf","args","slice","call","isOn","console","setThrottleInterval","localStorage","getItem","location","search","error","info","start","groupCollapsed","end","groupEnd","table","columns","attributeTable","object","item","key","value","isObject","hop","prototype","hasOwnProperty","is","undefined","obj","isString","isStorage","isWindow","isPlainObject","nodeType","constructor","isNonEmptyString","str","Boolean","isElement","element","tagName","extend","options","src","copy","clone","deep","i","hash","delimiter","pairing","pair","hashObj","split","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","dehyphenise","string","hyphen","letter","toUpperCase","parseAttributeName","attribute","getLocation","href","getQueryString","substring","getQueryParamByName","url","results","RegExp","exec","decodeURIComponent","getTimestamp","now","Date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","iframeToSlotName","iframeWindow","slotName","iframes","contentWindow","getAttribute","buildObjectFromArray","targetObject","reduce","prev","cookie","val","pop","getVersion","metricsSampleThreshold","random","responsive","defaults","formats","PartnerContent","sizes","MediumRectangle","Rectangle","WideSkyscraper","Leaderboard","SuperLeaderboard","HalfPage","Billboard","Portrait","AdhesionBanner","MicroBar","Button2","Responsive","extra","large","medium","small","flags","refresh","inview","displayLabelWithBorders","fetchDeclaritiveConfig","from","querySelectorAll","script","innerHTML","fetchCanonicalURL","canonical","canonicalTag","querySelector","Config","store","access","k","v","result","clear","init","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","_objectSpread","Error","params","URLSearchParams","fromEntries","_ref3","base","collapseEmpty","convertLazyLoadBooleanToObject","lazyLoad","onChangeBreakpoint","slot","screensize","hasValidSize","uncollapse","collapse","Slot","container","initLazyLoading","_this","cfg","slotConfig","outer","addContainer","class","inner","firstChild","setName","server","defer","center","label","outOfPage","companion","outerEl","allowedLabels","adsLabelPos","modifier","classList","add","parseAttributeConfig","lazyLoadObserver","initLazyLoad","centerContainer","labelContainer","initResponsive","getSlotSizes","_step","_iterator","_createForOfIteratorHelper","s","n","done","err","f","getSlotTargeting","_ref4","_i","_Object$entries","entries","_Object$entries$_i","_slicedToArray","getSlotGPTSize","_ref5","_this2","attributes","threshold","viewportMargin","getAttributes","_this3","observe","render","unobserve","maximise","floor","setFormatLoaded","addClass","className","remove","clearSlot","destroy","destroySlot","submitImpression","submitGptImpression","details","attrs","attr","insertAdjacentHTML","lastChild","isSlot","o","debug$1","slots","_step2","_iterator2","_slot$gpt","_slot$gpt2","_slot$gpt3","row","unitName","lineItemId","Slots","invokeMethodOnSlots","names","method","run","findFormatBySize","prop","onBreakpointChange","isCurrentlyResponsive","stillWantsResponsive","_this4","initSlot","getElementById","id","removeAttribute","initRefresh","_this5","refreshCount","time","setInterval","max","clearInterval","parseFloat","initRendered","breakpoints","initPostMessage","slotClass","flushLazyLoading","lazyLoadingObservers","observer","root","contains","lazyLoadingConfig","lazyLoadingObserver","find","rootMargin","IntersectionObserver","changes","_this6","a","intersectionRect","left","sort","b","change","fn","_this7","debug","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","_step3","childParams","_iterator3","delete","stripUrlParams","_ref6","filters","URL","_i2","_Object$entries2","_Object$entries2$_i","param","_step4","_iterator4","searchParams","set","DEFAULT_LAZY_LOAD","fetchMarginPercent","renderMarginPercent","mobileScaling","gptConfig","loadGPT","onReady","slotMethods","onRender","onRefresh","onResize","googletag","cmd","setup","nonPersonalized","pubads","onRenderEnded","enableCompanions","setRenderingMode","setPageTargeting","setPageCollapseEmpty","enableLazyLoad","enableServices","setTargeting","setRequestNonPersonalizedAds","lazyLoadConf","rendering","enableSyncRendering","enableSingleRequest","enableAsyncRendering","targetingData","String","clearPageTargetingForKey","clearTargeting","mode","collapseEmptyDivs","companions","disableInitialLoad","companionAds","setRefreshUnfilledSlots","defineSlot","addServices","setCollapseEmpty","setURL","display","iframe","_slotTargeting$pos","gptSlotId","getSlotId","domId","getDomId","iframeId","getId","slotTargeting","getTargetingMap","isPromotedContent","serviceName","iFrameEl","_this8","setUnitName","defineOutOfPageSlot","defineSizeMapping","gptSlot","pubadsReady","_this9","updatePageTargeting","sizeMapping","addSize","build","destroySlots","_this10","_this11","network","site","zone","_this12","addService","_this13","setCollapseEmptyDiv","impressionURL","trackingUrlElement","dataset","oAdsImpressionUrl","_this14","_this15","updateCorrelator","clearPageTargeting","override","hasGPTLoaded","apiReady","conf","Ads","addDOMEventListener","configOptions","disableConsentCookie","consents","behavioral","getConsents","programmatic","Promise","resolve","initLibrary","updateTargeting","cc","isInitialised","removeDOMEventListener","setItem","removeItem","version","initAll","ads","then","consentCookie","reactHotLoader","leaveModule","reactHotLoaderGlobal","default","register","module"],"mappings":"kkHAWMA,EAAW,SAAAC,GAEf,IAAMC,EAAcC,OAAOC,KAAOD,OAAOD,aAAeC,OAAOE,eAAiBF,OAAOG,mBAAqBH,OAAOI,eAC/GL,GAAeA,EAAYM,OAC7BN,EAAYO,WAAWR,GACvBC,EAAYM,KAAKP,KAMrB,SAASS,EAAoBC,GAC3B,IAAIC,EAAS,GAIb,OAHID,GAA8C,WAA3BE,EAAOF,IAAgC,QAASA,GAAmB,SAAUA,IAClGC,EAAS,KAAO,CAACD,EAAgBG,IAAKH,EAAgBV,KAAMU,EAAgBI,KAAMJ,EAAgBK,YAAYC,KAAK,OAE9GL,EAST,SAASM,EAAUC,EAAWC,EAAMC,GAElCA,EAASA,GAAUC,SAASC,MAAQD,SAASE,gBAC7CL,EAAY,QAAHM,OAAWN,GACpB,IAAMO,EAAO,CACXC,SAAS,EACTC,YAAY,EACZC,OAAQT,GASJR,EAASF,EAPqB,WAAhBG,EAAOO,IAAqB,QAASA,EACzB,CAC9BN,IAAKM,EAAKN,IACVb,KAAMmB,EAAKnB,KACXc,KAAMK,EAAKL,MAAQK,EAAKL,KAAKe,OAASV,EAAKL,KAAKgB,WAAa,GAC7Df,WAAYI,EAAKJ,YACf,IAGJhB,EADiBmB,EAAYP,GAE7BS,EAAOW,cAAc,IAAIC,YAAYd,EAAWO,IASlD,SAASQ,EAAGjC,EAAMkC,EAAUd,GAC1BpB,EAAO,QAAHwB,OAAWxB,IAEfoB,EAASA,GAAUC,SAASC,MAAQD,SAASE,iBACtCY,iBAAiBnC,EAAMkC,GAShC,SAASE,EAAIpC,EAAMkC,EAAUd,GAC3BpB,EAAO,QAAHwB,OAAWxB,IAEfoB,EAASA,GAAUC,SAASC,MAAQD,SAASE,iBACtCc,oBAAoBrC,EAAMkC,GASnC,SAASI,EAAKtC,EAAMkC,EAAUd,GAY5Ba,EAAGjC,GAXa,SAAUuC,IAEXA,EAAMnB,QAAUmB,EAAMC,YAC9BH,oBAAoBrC,EAAO,QAAHwB,OAAWxB,GAAQkC,GAC5CA,IACFA,EAASK,GAGTL,EAAW,QAGGd,GAGpB,SAASqB,EAAkBC,EAAQ/B,GACjC,IAAMgC,EAAYD,EAAOE,KAAI,SAAA1B,GAAS,MAAI,QAAUA,EAAYP,KAChE,IAAKV,cAAgBA,YAAY4C,iBAE/B,MAAO,GAET,IAAMC,EAAQ,GAoBd,OAnBAH,EAAUI,SAAQ,SAAUC,GAC1B,IAAMC,EAAShD,YAAY4C,iBAAiBG,GACtCE,EAAWF,EAAMG,QAAQ,QAAS,IAAIA,QAAQxC,EAAQ,IAC5D,GAAIsC,GAAUA,EAAOpB,OAEnBiB,EAAMI,GAAYE,KAAKC,MAAMJ,EAAO,GAAGK,gBAMzC,GAAI3C,EAAQ,CACV,IAAM4C,EAAgBP,EAAMG,QAAQxC,EAAQ,IACtC6C,EAAUvD,YAAY4C,iBAAiBU,GACzCC,GAAWA,EAAQ3B,SACrBiB,EAAMI,GAAYE,KAAKC,MAAMG,EAAQ,GAAGF,gBAIvCR,EAET,SAASW,EAAeC,EAAoBC,GAAe,IAAAC,EACzD,GAAK3D,aAAgBA,YAAY4D,iBAAjC,CAGA,IACMC,EADiBJ,EAAmBK,QAAO,SAAAC,GAAK,OAAIL,EAAcM,SAASD,EAAME,gBAC5CtB,KAAI,SAAAoB,GAAK,OAAIA,EAAMlB,SAExDqB,GAAgBP,EAAA,IAAGpC,OAAM4C,MAAAR,EAAAS,EAAIP,IACjB7D,YAAY4D,iBAAiB,QACrCd,SAAQ,SAAAuB,GAEZ,IADJtE,EAAIsE,EAAJtE,KAEAmE,EAAcpB,SAAQ,SAAA7B,GAChBlB,EAAKuE,MAAM,QAAD/C,OAASN,KACrBjB,YAAYO,WAAWR,UAO/B,SAASwE,EAAuBC,GAC9B,IAAKxE,cAAgBA,YAAY4D,mBAAqBa,GAAMC,QAAQF,GAElE,MAAO,GAET,IAAMG,EAAgB3E,YAAY4D,iBAAiB,cAC7CgB,EAAWH,GAAMC,QAAQC,IAAkBA,EAAc,IAAM,GAC/D9B,EAAQ,GAId,OAHA2B,EAAa1B,SAAQ,SAAUG,GAC7BJ,EAAMI,GAA0C,iBAAvB2B,EAAS3B,GAAyBE,KAAKC,MAAMwB,EAAS3B,IAAa,KAEvFJ,EAET,SAASgC,EAAaC,EAAa7C,EAAU8C,GACtCC,MAAMN,QAAQI,GAInBA,EAAYhC,SAAQ,SAAUmC,IACxBF,GAAmBN,GAAMS,SAASD,EAAKE,eACxBH,MAAMN,QAAQO,EAAKG,UAAYH,EAAKG,SAAW,IACvDtC,SAAQ,SAAUuC,GACzBC,EAAmB,QAAUD,EAASJ,EAAMhD,SAPhDsD,KAAKC,IAAIC,KAAK,8EAYlB,SAASH,EAAmBrE,EAAWyE,EAAUzD,GAC/Cb,SAASc,iBAAiBjB,GAAW,SAAS0E,EAAoBrD,GAChEsD,EAAYF,EAAUpD,EAAMX,OAAQM,GAC/ByD,EAASG,UACZzE,SAASgB,oBAAoBnB,EAAW0E,MAI9C,SAASC,EAAYF,EAAUI,EAAc7D,GAC3C,IAAMvB,EAAS+D,GAAMjE,oBAAoBsF,GACnCjD,EAAQL,EAAkBkD,EAAS7C,MAAOnC,GAChD,GAAIgF,EAASK,WAAY,CACvB,IAAMnB,EAAWL,EAAuBmB,EAASK,YACjDC,OAAOC,OAAOpD,EAAO+B,GAEvB,IAAMsB,EAAe,CACnBC,SAAU,MACVC,OAAQV,EAASzB,YACjBoC,QAAS,CACPxD,MAAOA,IAGXqD,EAAaI,OAAS,CACpBC,WAAYtG,OAAOuG,KAAKC,IAAIC,iBAE1BZ,GAAgB,QAASA,IAC3BI,EAAaS,SAAW,CACtB5G,KAAM+F,EAAa/F,KACnBa,IAAKkF,EAAalF,IAClBC,KAAMiF,EAAajF,MAAQiF,EAAajF,KAAKgB,WAC7Cf,WAAYgF,EAAahF,YAAc,GAEL,kBAAzBgF,EAAac,UACtBV,EAAaS,SAASC,QAAUd,EAAac,UAGjD3E,EAASiE,GAEX,SAASW,EAAe/B,EAAapB,GACnCF,EAAesB,EAAapB,GAC5Be,GAAMzD,UAAU,cASlB,IAsBIiB,EACA6E,EACAC,EAxBAC,EAAY,CACdC,KAAM,SAAUC,EAASC,GACvBD,EAA6B,iBAAZA,EAAuBA,EAAUE,KAAKC,UAAUH,IACjEC,EAASG,UAAU,IAAMrH,OAAOsH,KACzBC,YAAYN,EAAS,MAE9BO,MAAO,SAAUP,GAEf,GAAuB,iBAAZA,GAAuC,MAAfA,EAAQ,GACzC,OAAOA,EAIT,IACE,OAAOE,KAAKK,MAAMP,GAClB,MAAOQ,GAEP,OAAOR,KAQb,SAASS,IACP,IAAIC,EACEC,EAAOC,IAAUC,SAAQ,GAU/B,OADA/B,OAAOgC,KAAKlB,GAAehE,SAR3B,SAA+BmF,GAC7B,IAAMC,EAAiBpB,EAAcmB,GACjCJ,EAAKM,OAASD,EAAe,IAAML,EAAKO,QAAUF,EAAe,MAC9DN,GAAUM,EAAe,IAAMpB,EAAcc,GAAQ,MACxDA,EAASK,MAKRL,EAET,SAASS,IACP,IAAMT,EAASD,IACXZ,IAAYa,IACdU,EAAWV,GACX3F,EAAS2F,IAGb,SAASU,EAAWvI,GAClBgH,EAAUhH,EAEZ,SAASwI,IACP,OAAOxB,EAET,SAASyB,EAAOC,EAAMC,GACpB,QAAKjE,GAAMkE,WAAWD,KAItB5B,EAAgB2B,EAChBxG,EAAWyG,EACXJ,EAAWX,KACXvG,SAASC,KAAKa,iBAAiB,wBAAyBmG,GACxDjH,SAASC,KAAKa,iBAAiB,mBAAoBmG,GACnDP,IAAUc,SAAS,eACnBd,IAAUc,SAAS,UACZL,KAqBT,SAAS/C,IACP,IAAIqD,EACAC,GACiD,IAAjD,sBAAsBC,QAAQzB,UAAU,KAC1CuB,EAAO,MACPC,EAAY,IAEZD,EAAOvB,UAAU,GACjBwB,EAAY,GAEd,IAAME,EAAO,GAAGC,MAAMC,KAAK5B,UAAWwB,GAClCtD,EAAI2D,KAAKN,IACX5I,OAAOmJ,QAAQP,GAAM1E,MAAMlE,OAAOmJ,QAASJ,GA/B/ClB,IAAUuB,oBAuCV,IAAMF,EAAO,SAAUN,GAGrB,OADcS,cAAgBA,aAAaC,QAAQ,UAAsD,IAA3CC,SAASC,OAAOV,QAAQ,gBACtE9I,OAAOmJ,SAAWnJ,OAAOmJ,QAAQP,IAM7CpD,EAAO,WACX,IAAMuD,EAAO,CAAC,QAAQzH,OAAO,GAAG0H,MAAMC,KAAK5B,UAAW,IACtD9B,EAAIrB,MAAM,KAAM6E,IAMZU,EAAQ,WACZ,IAAMV,EAAO,CAAC,SAASzH,OAAO,GAAG0H,MAAMC,KAAK5B,UAAW,IACvD9B,EAAIrB,MAAM,KAAM6E,IAMZW,EAAO,WACX,IAAMX,EAAO,CAAC,QAAQzH,OAAO,GAAG0H,MAAMC,KAAK5B,UAAW,IACtD9B,EAAIrB,MAAM,KAAM6E,IAOZY,EAAQ,SAAU7F,GACjByB,EAAI2D,KAAK,mBAGdlJ,OAAOmJ,QAAQS,eAAe9F,GAAS,UAMnC+F,EAAM,WACLtE,EAAI2D,KAAK,aAGdlJ,OAAOmJ,QAAQW,YAEXC,EAAQ,SAAU9I,EAAM+I,GACxBzE,EAAI2D,KAAK,QAAUlJ,OAAOmJ,UACxBA,QAAQY,MACVZ,QAAQY,MAAM9I,EAAM+I,GAEpBb,QAAQ5D,IAAItE,KAIZgJ,EAAiB,SAAUC,EAAQF,GACvC,GAAIzE,EAAI2D,KAAK,QAAUlJ,OAAOmJ,QAC5B,GAAIe,GAAUf,QAAQY,MAAO,CAC3B,IAAM9I,EAAO8E,OAAOgC,KAAKmC,GAAQxH,KAAI,SAAAyH,GAOnC,MAAO,CACLC,IAAKD,EACLE,MAPE5F,EAAQyF,EAAOC,KAAUG,EAASJ,EAAOC,IACrChD,KAAKC,UAAU8C,EAAOC,IAEtBD,EAAOC,OAOjBhB,QAAQY,MAAM9I,EAAM+I,QAEpBb,QAAQ5D,IAAI2E,IAaZK,EAAMxE,OAAOyE,UAAUC,eAmB7B,SAASC,EAAGR,GACV,IAAMtB,EAAO7C,OAAOyE,UAAU5I,SAASqH,KAAKiB,GAAQ7F,MAAM,sBAAsB,GAChF,OAAe,OAAX6F,EACK,YACaS,IAAXT,EACF,YAEAtB,EAzBXL,EAAOD,WAAaA,EACpB/C,EAAIoE,MAAQA,EACZpE,EAAIsE,IAAMA,EACVtE,EAAI2D,KAAOA,EACX3D,EAAImE,KAAOA,EACXnE,EAAIC,KAAOA,EACXD,EAAIkE,MAAQA,EACZlE,EAAIwE,MAAQA,EACZxE,EAAI0E,eAAiBA,EA0BrB,IAAMxF,EAAU,SAAUmG,GACxB,MAAmB,UAAZF,EAAGE,IAQNC,EAAW,SAAUD,GACzB,MAAmB,WAAZF,EAAGE,IAQNlC,EAAa,SAAUkC,GAC3B,MAAmB,aAAZF,EAAGE,IAQNE,EAAY,SAAUF,GAC1B,MAAmB,YAAZF,EAAGE,IAQNN,EAAW,SAAUM,GACzB,MAAmB,WAAZF,EAAGE,IAQNG,EAAW,SAAUH,GACzB,OAAOA,GAAe,OAARA,GAAgBA,IAAQ5K,QAUlCgL,EAAgB,SAAUJ,GAC9B,IAqBIR,EArBEG,EAAMxE,OAAOyE,UAAUC,eAK7B,IAAKG,IAAQN,EAASM,IAAQA,EAAIK,UAAYF,EAASH,GACrD,OAAO,EAET,IAEE,GAAIA,EAAIM,cAAgBX,EAAItB,KAAK2B,EAAK,iBAAmBL,EAAItB,KAAK2B,EAAIM,YAAYV,UAAW,iBAC3F,OAAO,EAET,MAAO/C,GAGP,OAAO,EAMT,IAAK2C,KAAOQ,GAGZ,YAAeD,IAARP,GAAqBG,EAAItB,KAAK2B,EAAKR,IAQtCe,GAAmB,SAAUC,GACjC,OAAOP,EAASO,IAAQC,QAAQD,EAAIzJ,SAEhC2J,GAAY,SAAUC,GAC1B,OAAOA,GAAgC,IAArBA,EAAQN,UAAkBM,EAAQC,UAAW,GAEjE,SAASC,KAGP,IAAIC,EACAC,EACAC,EAEAC,EACA3K,EAASmG,UAAU,IAAM,GACvB1F,EAAS0F,UAAU1F,OACrBmK,GAAO,EACPC,EAAI,EAmBR,GAhBsB,kBAAX7K,IACT4K,EAAO5K,EACPA,EAASmG,UAAU,IAAM,GAGzB0E,EAAI,GAKgB,WAAlBrL,EAAOQ,IAAwBwH,EAAWxH,KAC5CA,EAAS,IAKPS,IAAWoK,EACb,OAAO7K,EAET,KAAO6K,EAAIpK,EAAQoK,IAEjB,GAAiC,QAA5BL,EAAUrE,UAAU0E,IAEvB,IAAK,IAAMjM,KAAQ4L,EAGjB,GAAIA,EAAQjB,eAAe3K,GAAO,CAKhC,GAJA6L,EAAMzK,EAAOpB,GAIToB,KAHJ0K,EAAOF,EAAQ5L,IAIb,SAIEgM,GAAQF,IAASZ,EAAcY,IAASnH,EAAQmH,KACpCnH,EAAQmH,KAEN,EACdC,EAAQF,GAAOlH,EAAQkH,GAAOA,EAAM,IAEpCE,EAAQF,GAAOrB,EAASqB,GAAOA,EAAM,GAIvCzK,EAAOpB,GAAQ2L,GAAOK,EAAMD,EAAOD,SAGjBjB,IAATiB,IACT1K,EAAOpB,GAAQ8L,GAQzB,OAAO1K,EAYT,IAAM8K,GAAO,SAAUZ,EAAKa,EAAWC,GACrC,IAAIC,EAEEC,EAAU,GAChB,GAAIhB,GAAOA,EAAIiB,MAEb,IAAK,IAAIC,EAAM,EAAGC,GADlBnB,EAAMA,EAAIiB,MAAMJ,IACUtK,OAAQ2K,EAAMC,EAAGD,GAAO,GAEhDH,EADQf,EAAIkB,GACCD,MAAMH,IACVvK,OAAS,IAChByK,EAAQD,EAAK,GAAGK,QAAUL,EAAKnD,MAAM,GAAGlI,KAAKoL,IAInD,OAAOE,GAaHK,GAAS,SAAUC,EAAWC,EAAO3K,EAAU4K,EAASC,GAC5D,IAAMC,EAAM3L,SAAS4L,cAAc,UAC7BC,EAAO7L,SAAS8L,qBAAqB,UAAU,GACjDC,GAAS,EACb,SAASC,EAAgBnL,GAElBkL,IACHlL,EAASiH,OACTiE,GAAS,EAELL,GACFC,EAAIM,cAAcC,YAAYP,IAkCpC,OA9BAA,EAAIQ,aAAa,MAAOZ,GACxBI,EAAIQ,aAAa,QAAS,IAEtBX,IACFG,EAAIH,MAAQ,QAGVjE,EAAW1G,KAETuI,EAAItB,KAAK6D,EAAK,sBAChBA,EAAIS,mBAAqB,WACA,WAAnBT,EAAIU,YACNL,EAAgBnL,IAIpB8K,EAAIW,OAAS,WACXN,EAAgBnL,KAMlB0G,EAAWkE,KACbE,EAAIY,QAAU,WACZP,EAAgBP,KAIpBI,EAAKW,WAAWC,aAAad,EAAKE,GAC3BF,GASHe,GAAc,WAClB,OAAO1M,SAAS2M,UAAY,IAQxBC,GAAc,SAAUC,GAC5B,OAAOA,EAAO/K,QAAQ,eAAe,SAAUoB,EAAO4J,EAAQC,GAC5D,OAAOA,EAAOC,kBASZC,GAAqB,SAAUC,GACnC,IAAMvO,EAAO+K,EAASwD,GAAaA,EAAYA,EAAUvO,KACzD,OAAOiO,GAAYjO,EAAKmD,QAAQ,iBAAkB,MAS9CqL,GAAc,WAClB,OAAOnN,SAASoI,SAASgF,MAAQ,IAS7BC,GAAiB,WACrB,OAAOrN,SAASoI,SAASC,OAAOiF,UAAU,IAAM,IAS5CC,GAAsB,SAAU5O,EAAM6O,GAC1CA,EAAMA,GAAO3O,OAAOuJ,SAASgF,KAC7BzO,EAAOA,EAAKmD,QAAQ,SAAU,QAC9B,IACM2L,EADQ,IAAIC,OAAO,OAAS/O,EAAO,qBACnBgP,KAAKH,GAC3B,OAAKC,EAGAA,EAAQ,GAGNG,mBAAmBH,EAAQ,GAAG3L,QAAQ,MAAO,MAF3C,GAHA,MAYL+L,GAAe,WACnB,IAAMC,EAAM,IAAIC,KAChB,MAAO,CAACD,EAAIE,cAAe,IAAA7N,OAAI2N,EAAIG,WAAa,GAAIpG,OAAO,GAAI,IAAA1H,OAAI2N,EAAII,WAAYrG,OAAO,GAAI,IAAA1H,OAAI2N,EAAIK,YAAatG,OAAO,GAAI,IAAA1H,OAAI2N,EAAIM,cAAevG,OAAO,GAAI,IAAA1H,OAAI2N,EAAIO,cAAexG,OAAO,IAAIlI,KAAK,KAUnM2O,GAAmB,SAAUC,GAQjC,IANA,IACIC,EACA3C,EAFE4C,EAAUzO,SAAS8L,qBAAqB,UAG1ClB,EAAI6D,EAAQjO,OAGToK,KAEL,GAAI6D,EAAQ7D,GAAG8D,gBAAkBH,EAAc,CAC7C1C,EAAO4C,EAAQ7D,GACf,MAIJ,GAAIiB,EAEF,KAAOA,EAAKW,YAAY,CAGtB,GAFAgC,EAAW3C,EAAK8C,aAAa,mBAG3B,OAAOH,EAET3C,EAAOA,EAAKW,WAGhB,OAAO,GAEHoC,GAAuB,SAA8BC,GACzD,OAAOA,EAAaC,QAAO,SAACC,EAAMjP,GAEhC,OADAiP,EAAKjP,EAAKmJ,KAAOnJ,EAAKoJ,MACf6F,IACN,KAECC,GAAS,SAAUrQ,GACvB,IAAMsQ,EAAMjP,SAASgP,OAAO9L,MAAM,YAAD/C,OAAaxB,EAAI,qBAClD,OAAOsQ,EAAMA,EAAIC,MAAQ,MAErBC,GAAa,WAAH,MAvaF,UAwaRC,GAAyBrN,KAAKsN,SACpC,SAASvL,GAASC,GAChB,YAA6B,IAAfA,GAA8BA,EAAaqL,GAE3D,IAAI/L,GAAQ,CACVzC,KACAG,MACAE,OACArB,YACAgG,YACA0J,WAAYlI,EACZhD,MACAd,UACAoG,WACAnC,aACAoC,YACAR,WACAS,WACAC,gBACAG,oBACAG,aACAG,UACAO,QACAS,UACAoB,eACAE,eACAK,sBACAE,eACAE,kBACAE,uBACAM,gBACAS,oBACAM,wBACAI,UACAG,cACA1L,eACArB,iBACAqD,iBACA3B,YACApF,WACAU,uBAQImQ,GAAW,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,KAGfJ,WAAY,CACViB,MAAO,CAAC,KAAM,GAEdC,MAAO,CAAC,IAAM,GAEdC,OAAQ,CAAC,IAAK,GAEdC,MAAO,CAAC,EAAG,IAGbC,MAAO,CACLC,SAAS,EACTC,QAAQ,GAEVC,yBAAyB,GAE3B,SAASC,KACP,IAAItD,EAAU,GAKd,OAJgB7J,MAAMoN,KAAKhR,SAASiR,iBAAiB,8BAC7CvP,SAAQ,SAAAwP,GACdzD,EAAU5O,OAAOmH,KAAO3C,GAAMiH,OAAOmD,EAASzH,KAAKK,MAAM6K,EAAOC,YAAc,iBAEzE1D,EAQT,SAAS2D,KACP,IAAIC,EACEC,EAAetR,SAASuR,cAAc,yBAI5C,OAHID,IACFD,EAAYC,EAAalE,MAEpB,CACLiE,UAAWA,GASf,SAASG,KACPrN,KAAKsN,MAAQ,GAEfD,GAAOnI,UAAUqI,OAAS,SAAUC,EAAGC,GACrC,IAAIC,EAcJ,OAbIxO,GAAMwG,cAAc8H,IACtBtO,GAAMiH,QAAO,EAAMnG,KAAKsN,MAAOE,GAC/BE,EAAS1N,KAAKsN,YACQ,IAANG,EAEdC,OADe,IAANF,EACAxN,KAAKsN,MAELtN,KAAKsN,MAAME,IAGtBxN,KAAKsN,MAAME,GAAKC,EAChBC,EAASD,GAEJC,GAETL,GAAOnI,UAAUyI,MAAQ,SAAU7I,GAC7BA,SACK9E,KAAKsN,MAAMxI,GAElB9E,KAAKsN,MAAQ,IAGjBD,GAAOnI,UAAU0I,KAAO,WAEtB,OADA5N,KAAKsN,MAAQpO,GAAMiH,QAAO,EAAM,GAAIiF,GAAU6B,KAAqBL,MAC5D5M,KAAKsN,OAEd,IAAMO,GAAS,IAAIR,GACfS,GAAWD,GAAON,OAAOQ,KAAKF,IAC5BG,GAASH,GAAOD,KAAKG,KAAKF,IAC1BF,GAAQE,GAAOF,MAAMI,KAAKF,IAE1BI,GAAqB,CAAC,SACtBC,GAAuB,CAAC,SAAU,QAAS,SAC3CC,GAAmB,CACvB5C,MAAO,SAAUxG,EAAOwG,GACtB,IAAc,IAAVxG,GAA6B,UAAVA,EACrB,OAAO,EACF,GAAI7F,GAAMC,QAAQoM,GAAQ,CAE/B,IAAM6C,EAAQ,cACdrJ,EAAMgC,MAAM,KAAKxI,QAAO,SAAAjD,GAAI,OAAIA,EAAKe,UAAQkB,SAAQ,SAAAjC,GAC/C8S,EAAMC,KAAK/S,GACbA,EAAKqC,QAAQyQ,GAAO,SAAUrP,EAAO6D,EAAOC,GAC1C0I,EAAM+C,KAAK,CAACC,SAAS3L,EAAO,IAAK2L,SAAS1L,EAAQ,SAE3CoL,GAAmBzK,QAAQlI,IAAS,GAC7CiQ,EAAM+C,KAAKhT,MAIjB,OAAOiQ,GAETF,QAAS,SAAUtG,EAAOwG,GACxB,IAAc,IAAVxG,GAA6B,UAAVA,EACrBwG,GAAQ,MACH,CACL,IAAMiD,EAAUV,KAAWzC,QACrBA,EAAUnM,GAAMC,QAAQ4F,GAASA,EAAQA,EAAMgC,MAAM,KAC3DsE,EAAQ9N,SAAQ,SAAAkR,GACVD,GAAWA,EAAQC,IACrBA,EAASD,EAAQC,GACbvP,GAAMC,QAAQsP,EAAOlD,MAAM,KAAO0C,GAAmBzK,QAAQiL,EAAOlD,MAAM,KAAO,EACnFkD,EAAOlD,MAAMhO,SAAQ,SAAAjC,GACnBiQ,EAAM+C,KAAKhT,MAGbiQ,EAAM+C,KAAKG,EAAOlD,QAGpBrM,GAAMe,IAAIkE,MAAM,uCAADnI,OAAwCyS,OAI7D,OAAOlD,GAETmD,gBAAiB,SAAUlU,EAAMuK,EAAOwG,GACtC,IAAMoD,EAAanU,EAAKmD,QAAQ,SAAU,IAAIiR,cAM9C,OAJK1P,GAAMwG,cAAc6F,KACvBA,EAAQ,IAEVA,EAAMoD,GAAcR,GAAiB5C,MAAMxG,EAAOwG,EAAMoD,IAAe,IAChEpD,GAETsD,kBAAmB,SAAUrU,EAAMuK,EAAOwG,GACxC,IAAMoD,EAAanU,EAAKmD,QAAQ,WAAY,IAAIiR,cAMhD,OAJK1P,GAAMwG,cAAc6F,KACvBA,EAAQ,IAEVA,EAAMoD,GAAcR,GAAiB9C,QAAQtG,EAAO,IAC7CwG,GAETuD,kBAAmB,SAAU/J,GAC3B,OAAOA,EAAMgC,MAAM,KAAK3J,IAAI2R,SAiB9BC,UAAW,SAAUjK,GAAuB,IAAhBiK,EAASjN,UAAA1F,OAAA,QAAAgJ,IAAAtD,UAAA,GAAAA,UAAA,GAAG,GACtC,IAAKgD,GAA0B,IAAjBA,EAAM1I,OAAc,OAAO2S,EACzC,IACE,GAAIjK,EAAMtG,SAAS,KAKjB,MAJAuQ,EAASC,IAAA,GACJD,GACA9P,GAAMwH,KAAK3B,EAAO,IAAK,MAEtB,IAAImK,MAAM,4DAADlT,OAA6D+I,EAAK,cAEnF,IAAMoK,EAAS,IAAIC,gBAAgBrK,GACnCiK,EAASC,IAAA,GACJD,GACAvO,OAAO4O,YAAYF,IAExB,MAAAG,GAEC,IADD3N,EAAO2N,EAAP3N,QAEAkC,QAAQ3D,KAAKyB,GAEf,OAAOqN,GAETO,KAAM,SAAUxK,GAOd,MALc,KAAVA,GAA0B,SAAVA,EAClBA,GAAQ,EACW,UAAVA,IACTA,GAAQ,GAEHA,GAETyK,cAAe,SAAUzK,GAEvB,IADoE,IAAzCmJ,GAAqB1K,QAAQuB,GAKxD,OAAOA,EAHL7F,GAAMe,IAAIC,KAAK,qBAADlE,OAAsB+I,EAAK,kFAMzC0K,GAAiC,SAAAnK,IAChB,IAAjBA,EAAIoK,WACNpK,EAAIoK,SAAW,KAGbC,GAAqB,SAAA5S,GACzB,IAAM6S,EAAO7S,EAAMX,OAAOwT,KAC1BA,EAAKC,WAAa9S,EAAMX,OAAOyT,WAC3BD,EAAKE,eACPF,EAAKG,cAELH,EAAKI,WACLJ,EAAKjC,UAST,SAASsC,GAAKC,EAAWL,EAAYM,GAAiB,IAAAC,EAAA,KAE9CC,EAAMvC,KACRwC,EAAaxC,GAAS,UAAY,GAGtC9N,KAAKkQ,UAAYA,EAIbL,IACF7P,KAAK6P,WAAaA,GAIpB7P,KAAKuQ,MAAQvQ,KAAKkQ,UAAU9C,cAAc,iBACrCpN,KAAKuQ,QACRvQ,KAAKuQ,MAAQvQ,KAAKwQ,aAAaN,EAAW,CACxCO,MAAO,kBAGXzQ,KAAK0Q,MAAQ1Q,KAAKuQ,MAAMI,WACnB3Q,KAAK0Q,QACR1Q,KAAK0Q,MAAQ1Q,KAAKwQ,aAAaxQ,KAAKuQ,MAAO,CACzCE,MAAO,kBAKXzQ,KAAK4Q,UACLN,EAAaA,EAAWtQ,KAAKxF,OAAS,GAGtCwF,KAAK6Q,OAAS,MACd7Q,KAAK8Q,OAAQ,EAGb9Q,KAAKgP,UAAYsB,EAAWtB,WAAa,GACzChP,KAAKuL,MAAQ+E,EAAW/E,OAAS,GACjCvL,KAAK+Q,OAAST,EAAWS,SAAU,EACnC/Q,KAAKgR,MAAQV,EAAWU,QAAS,EACjChR,KAAKiR,UAAYX,EAAWW,YAAa,EACzCjR,KAAKkR,WAAqC,IAAzBZ,EAAWY,UAC5BlR,KAAKwP,cAAgBc,EAAWd,cAE5BtQ,GAAMC,QAAQmR,EAAWjF,SAC3B8C,GAAiB9C,QAAQiF,EAAWjF,QAASrL,KAAKuL,OACzCrM,GAAMwG,cAAc4K,EAAWjF,WACxCrL,KAAKuL,MAAQ,GACb9K,OAAOgC,KAAK6N,EAAWjF,SAAS9N,SAAQ,SAAAoR,GACtCyB,EAAK7E,MAAMoD,GAAcR,GAAiB9C,QAAQiF,EAAWjF,QAAQsD,GAAa,aAGnD,IAAxB2B,EAAWZ,SACpB1P,KAAK0P,SAAWY,EAAWZ,SAE3B1P,KAAK0P,SAAW5B,GAAS,cAAe,EAE1C,IAAMqD,EAAUjB,EAAU9C,cAAc,iBACxC,GAAI+D,GAAWd,EAAI1D,yBAA2B3M,KAAKkQ,UAAU1F,aAAa,oBAAqB,CAC7F,IAAM4G,EAAgB,CAAC,OAAQ,SAAU,SACnCC,EAAcrR,KAAKkQ,UAAU1F,aAAa,oBAChDtL,GAAMpC,KA7DY,mBA6DM,WACtB,IAAMwU,EAAWF,EAAc5N,QAAQ6N,GAAeA,EAAc,OACpEF,EAAQI,UAAUC,IAAI,4BAA6B,8BAAFxV,OAAgCsV,OAOrF,GAFAtR,KAAKyR,wBAEAzR,KAAKuL,MAAMlP,SAAW6C,GAAMwG,cAAc1F,KAAKuL,OAElD,OADArM,GAAMe,IAAIkE,MAAM,mCAAoCnE,KAAKxF,OAClD,EAITwF,KAAK0R,iBAAmBvB,EAAgBnQ,KAAK0P,UAC7C1P,KAAK2R,eACL3R,KAAK4R,kBACL5R,KAAK6R,iBACL7R,KAAK8R,iBAyQP,SAASC,GAAanC,GACpB,IAAKnQ,MAAMN,QAAQyQ,EAAKrE,OAAQ,MAAO,kBACvC,IAC6ByG,EADvBzG,EAAQ,GAAG0G,EAAAC,EACEtC,EAAKrE,OAAK,IAA7B,IAAA0G,EAAAE,MAAAH,EAAAC,EAAAG,KAAAC,MAA+B,KAApB/W,EAAI0W,EAAAjN,MACbwG,EAAM+C,KAAK7O,MAAMN,QAAQ7D,GAAQA,EAAKE,KAAK,KAAOF,IACnD,MAAAgX,GAAAL,EAAA9P,EAAAmQ,GAAA,QAAAL,EAAAM,IACD,OAAOhH,EAAM/P,KAAK,MAOpB,SAASgX,GAAgBC,GAIvB,IAFC,IADDzD,EAASyD,EAATzD,UAEMG,EAAS,GACfuD,EAAA,EAAAC,EAAyBlS,OAAOmS,QAAQ5D,GAAa,IAAG0D,EAAAC,EAAAtW,OAAAqW,IAAE,CAArD,IAAAG,EAAAC,EAAAH,EAAAD,GAAA,GAAO5N,EAAG+N,EAAA,GAAE/H,EAAG+H,EAAA,GAClB1D,EAAOb,KAAK,GAADtS,OAAI8I,EAAG,KAAA9I,OAAI8O,IAExB,OAAOqE,EAAO3T,KAAK,MAOrB,SAASuX,GAAcC,GAEpB,IADD9R,EAAG8R,EAAH9R,IAEA,YAAmB,IAARA,EAA4B,mBACnCA,EAAIG,QAAgB,QACnB5B,MAAMN,QAAQ+B,EAAI5F,MAChB4F,EAAI5F,KAAKE,KAAK,KADgB,MAnSvCyU,GAAK/K,UAAUuM,qBAAuB,WAAY,IAAAwB,EAAA,KAChDxT,MAAMoN,KAAK7M,KAAKkQ,UAAUgD,YAAY3V,SAAQ,SAAAwL,GAC5C,IAAMvO,EAAO0E,GAAM4J,mBAAmBC,EAAUvO,MAC1CuK,EAAQgE,EAAUhE,MACX,YAATvK,EACFyY,EAAKzY,GAAQ2T,GAAiB3T,GAAMuK,EAAOkO,EAAK1H,OAC9B,kBAAT/Q,EACTyY,EAAKzD,cAAgBrB,GAAiBqB,cAAczK,GAClC,sBAATvK,GAAgCyY,EAAKvD,UAC9CD,GAA+BwD,GAC/BA,EAAKvD,SAASyD,UAAYhF,GAAiBW,kBAAkB/J,IAC3C,2BAATvK,GAAqCyY,EAAKvD,UACnDD,GAA+BwD,GAC/BA,EAAKvD,SAAS0D,eAAiBjF,GAAiBoB,KAAKxK,IAC5CoJ,GAAiB3T,GAC1ByY,EAAKzY,GAAQ2T,GAAiB3T,GAAMuK,EAAOkO,EAAKzY,IACvC,cAAc6T,KAAK7T,GAC5ByY,EAAK1H,MAAQ4C,GAAiBU,kBAAkBrU,EAAMuK,EAAOkO,EAAK1H,OACzD,YAAY8C,KAAK7T,GAC1ByY,EAAK1H,MAAQ4C,GAAiBO,gBAAgBlU,EAAMuK,EAAOkO,EAAK1H,OAGzD0H,EAAK9N,eAAe3K,KAC3ByY,EAAKzY,GAAQ2T,GAAiBoB,KAAKxK,QAIzCkL,GAAK/K,UAAUmO,cAAgB,WAC7B,IAAMH,EAAa,GAKnB,OAJAzT,MAAMoN,KAAK7M,KAAKkQ,UAAUgD,YAAY3V,SAAQ,SAAAwL,GAC5CmK,EAAWhU,GAAM4J,mBAAmBC,IAAcA,EAAUhE,SAE9D/E,KAAKkT,WAAaA,EACXlT,MAMTiQ,GAAK/K,UAAUyM,aAAe,WAAY,IAAA2B,EAAA,KAgBxC,OAdItT,KAAK0R,kBAAoB1R,KAAK0P,WAChC1P,KAAK8Q,OAAQ,EACb9Q,KAAK0R,iBAAiB6B,QAAQvT,KAAKkQ,WAI/BlQ,KAAKkR,WACPhS,GAAMpC,KAAK,gBAAgB,WACrBwW,EAAKxD,gBACPwD,EAAKE,WAENxT,KAAKkQ,YAGLlQ,MAETiQ,GAAK/K,UAAUsO,OAAS,WACtBxT,KAAK8C,KAAK,iBAEN9C,KAAK0R,kBACP1R,KAAK0R,iBAAiB+B,UAAUzT,KAAKkQ,YAQzCD,GAAK/K,UAAU4M,eAAiB,WAS9B,OAPI5S,GAAMwG,cAAc1F,KAAKuL,SAEtBvL,KAAK8P,gBACR9P,KAAKgQ,WAEP9Q,GAAMzC,GAAG,aAAckT,GAAoB3P,KAAKkQ,YAE3ClQ,MAMTiQ,GAAK/K,UAAUwO,SAAW,SAAUpY,GAC9BA,GAA4B,MAApByT,OAAOzT,EAAK,KAAmC,MAApByT,OAAOzT,EAAK,KACjD0E,KAAK8C,KAAK,SAAU,CAClBxH,KAAM,CAAC,OAAQ,WAQrB2U,GAAK/K,UAAU0L,QAAU,WAMvB,OALA5Q,KAAKxF,KAAOwF,KAAKkQ,UAAU1F,aAAa,oBAAsBxK,KAAKkQ,UAAU1F,aAAa,cACrFxK,KAAKxF,OACRwF,KAAKxF,KAAO,cAAHwB,OAAiB4B,KAAK+V,MAAsB,IAAhB/V,KAAKsN,WAC1ClL,KAAKkQ,UAAUlI,aAAa,kBAAmBhI,KAAKxF,OAE/CwF,MAMTiQ,GAAK/K,UAAU8K,SAAW,WAKxB,OAJAhQ,KAAKkQ,UAAUqB,UAAUC,IAAI,gBAC7BxR,KAAK4T,iBAAgB,GACrB/X,SAASC,KAAKyV,UAAUC,IAAI,YAADxV,OAAagE,KAAKxF,OAC7C0E,GAAMzD,UAAU,YAAauE,MACtBA,MAMTiQ,GAAK/K,UAAU2O,SAAW,SAAUC,GAGlC,OAFA9T,KAAKkQ,UAAUqB,UAAUC,IAAI,SAADxV,OAAU8X,IACtC5U,GAAMzD,UAAU,iBAAkBuE,MAC3BA,MAMTiQ,GAAK/K,UAAU0O,gBAAkB,SAAUnF,GAEzC,OADAzO,KAAKkQ,UAAUlI,aAAa,oBAAqByG,GAC1CzO,MAMTiQ,GAAK/K,UAAU6K,WAAa,WAG1B,OAFA/P,KAAKkQ,UAAUqB,UAAUwC,OAAO,gBAChClY,SAASC,KAAKyV,UAAUwC,OAAO,YAAD/X,OAAagE,KAAKxF,OACzCwF,MAMTiQ,GAAK/K,UAAUyI,MAAQ,WAKrB,OAHIzO,GAAMkE,WAAWpD,KAAgB,YACnCA,KAAKgU,YAEAhU,MAMTiQ,GAAK/K,UAAU+O,QAAU,WAYvB,OAVI/U,GAAMkE,WAAWpD,KAAkB,eACrCd,GAAMtC,IAAI,aAAc+S,GAAoB3P,KAAKkQ,WACjDlQ,KAAKkU,cACDlU,KAAKuQ,MAAMzI,gBAAkB9H,KAAKkQ,UACpClQ,KAAKkQ,UAAUnI,YAAY/H,KAAKuQ,OAEhC1M,QAAQM,MAAM,wEAIXnE,MAMTiQ,GAAK/K,UAAUiP,iBAAmB,WAKhC,OAHIjV,GAAMkE,WAAWpD,KAA0B,sBAC7CA,KAAKoU,sBAEApU,MAMTiQ,GAAK/K,UAAUpC,KAAO,SAAUtI,EAAMmB,GACpC,IAAMuF,EAAMlB,KAAKkB,KAAO,GAClBmT,EAAU,CACd7Z,KAAMwF,KAAKxF,MAAQ,GACnBa,IAAK2E,KAAKgP,WAAahP,KAAKgP,UAAU3T,KAAO,GAC7CC,KAAM4F,EAAI5F,MAAQ,GAClBC,WAAY2F,EAAI3F,YAAc,GAC9BqU,KAAM5P,MASR,MAP2B,kBAAhBkB,EAAIG,UACbgT,EAAQhT,QAAUH,EAAIG,SAEpBnC,GAAMwG,cAAc/J,IACtBuD,GAAMiH,OAAOkO,EAAS1Y,GAExBuD,GAAMzD,UAAUjB,EAAM6Z,EAASrU,KAAKkQ,WAC7BlQ,MAMTiQ,GAAK/K,UAAUsL,aAAe,SAAU9I,EAAM4M,GAC5C,IAAIpE,EAAY,QAUhB,OARIoE,GACF7T,OAAOgC,KAAK6R,GAAO/W,SAAQ,SAAUgX,GACnC,IAAMxP,EAAQuP,EAAMC,GACpBrE,GAAa,GAAJlU,OAAOuY,EAAI,KAAAvY,OAAI+I,EAAK,QAGjCmL,GAAa,UACbxI,EAAK8M,mBAAmB,YAAatE,GAC9BxI,EAAK+M,WAEdxE,GAAK/K,UAAU4K,aAAe,SAAUD,GAEtC,QADAA,EAAaA,GAAc7P,KAAK6P,cACd3Q,GAAMwG,cAAc1F,KAAKuL,SACP,IAA3BvL,KAAKuL,MAAMsE,IAQtBI,GAAK/K,UAAU0M,gBAAkB,WAI/B,OAHI5R,KAAK+Q,QACP/Q,KAAKkQ,UAAUqB,UAAUC,IAAI,iBAExBxR,MAMTiQ,GAAK/K,UAAU2M,eAAiB,WAC9B,IAAIiC,EASJ,OARmB,IAAf9T,KAAKgR,OAAiC,SAAfhR,KAAKgR,MAC9B8C,EAAY,aACY,UAAf9T,KAAKgR,QACd8C,EAAY,eAEVA,IAAchG,GAAS,4BACzB9N,KAAKkQ,UAAUqB,UAAUC,IAAI,UAADxV,OAAW8X,IAElC9T,MAiDT,IAAM0U,GAAS,SAAAC,GAAC,MAAI,SAAUA,GAK9B,SAASC,GAAQC,GACf,IACwBC,EADlBnZ,EAAO,GAAGoZ,EAAA7C,EACG2C,GAAK,IAAxB,IAAAE,EAAA5C,MAAA2C,EAAAC,EAAA3C,KAAAC,MAA0B,KAAfzC,EAAIkF,EAAA/P,MACb,GAAI2P,GAAO9E,GAAO,CAChB,IAAIoF,EAAWC,EAAYC,EACrBC,EAAM,CACV3a,KAAMoV,EAAKpV,KACX,YAAwC,QAA1Bwa,EAAYpF,EAAK1O,WAA+B,IAAd8T,OAAuB,EAASA,EAAUI,SAC1F,eAA4C,QAA3BH,EAAarF,EAAK1O,WAAgC,IAAf+T,OAAwB,EAASA,EAAW1Z,aAAe,MAC/G,gBAA6C,QAA3B2Z,EAAatF,EAAK1O,WAAgC,IAAfgU,OAAwB,EAASA,EAAWG,aAAe,MAChH/Z,KAAMyX,GAAenD,GACrBrE,MAAOwG,GAAanC,GACpBZ,UAAWwD,GAAiB5C,IAE9BjU,EAAK2S,KAAK6G,KAEb,MAAA7C,GAAAyC,EAAA5S,EAAAmQ,GAAA,QAAAyC,EAAAxC,IAID,OAHA1O,QAAQrF,MAAM,aACdqF,QAAQY,MAAM9I,GACdkI,QAAQW,WACD7I,EAIT,IAAIkU,GAAa,KAQjB,SAASyF,MAGT,SAASC,GAAoBC,EAAOC,EAAQ/Y,GAC1C,IAAImY,EAAQ,GAaZ,OAZAW,EAAQA,GAAS/U,OAAOgC,KAAKzC,MAGzBd,GAAM2G,iBAAiB2P,GACzBX,EAAMvG,KAAKkH,GACFtW,GAAMC,QAAQqW,KACvBX,EAAQW,GAEVX,EAAMtX,QAAQmY,GAAI3H,KAAK,KAAM/N,KAAMyV,IAC/BvW,GAAMkE,WAAW1G,IACnBA,EAASiH,KAAK3D,KAAM6U,GAEf7U,KAQT,SAAS0V,GAAIb,EAAOhU,EAAQrG,GAC1B,IAAMoV,EAAOiF,EAAMra,GACfoV,EACE1Q,GAAMkE,WAAWwM,EAAK/O,IACxB+O,EAAK/O,KAED3B,GAAMkE,WAAWwM,EAAK9M,MACxB8M,EAAK9M,KAAKjC,GAEV3B,GAAMe,IAAIC,KAAK,mCAAoCW,EAAQrG,GAI/D0E,GAAMe,IAAIC,KAAK,uCAAwCW,EAAQrG,GAGnE,SAASmb,GAAiBra,GACxB,IAAKA,EACH,OAAO,EAET,IAAM+P,EAAUyC,GAAS,WACzB,IAAK,IAAM8H,KAAQvK,EAGjB,GAAIA,EAAQlG,eAAeyQ,GAAO,CAChC,IAAIrK,EAAQF,EAAQuK,GAAMrK,MAK1B,IAJAA,EAAQrM,GAAMC,QAAQoM,EAAM,IAAMA,EAAQ,CAACA,IACvBhN,QAAO,SAAU4T,GACnC,OAAOA,EAAE,KAAO5D,SAASjT,EAAK,GAAI,KAAO6W,EAAE,KAAO5D,SAASjT,EAAK,GAAI,OAE5De,OACR,OAAOuZ,GA0If,SAASC,GAAmBhB,EAAOhF,GACjCgF,EAAMtX,SAAQ,SAAUqS,GAEtB,GAAIA,EAAM,CAGR,IAAMkG,EAAwBlG,EAAKM,WAAkE,eAArDN,EAAKM,UAAU1F,aAAa,qBACtEuL,EAAuBnG,EAAKrE,MAAMsE,IAAeD,EAAKrE,MAAMsE,GAAYtR,QAAO,SAAAjD,GAAI,MAA+B,eAA3Bqa,GAAiBra,MAAwBe,OAAS,EAC/I,GAAIyZ,GAAyBC,EAC3B,OAAO,EAETnG,EAAKC,WAAaA,EAClBD,EAAK9M,KAAK,aAAc,CACtB+M,WAAYA,QA/IpByF,GAAMpQ,UAAU8K,SAAW,SAAUwF,GACnC,OAAOD,GAAoB5R,KAAK3D,KAAMwV,EAAO,aAM/CF,GAAMpQ,UAAU6K,WAAa,SAAUyF,GACrC,OAAOD,GAAoB5R,KAAK3D,KAAMwV,EAAO,eAM/CF,GAAMpQ,UAAUuH,QAAU,SAAU+I,GAClC,OAAOD,GAAoB5R,KAAK3D,KAAMwV,EAAO,YAM/CF,GAAMpQ,UAAUyI,MAAQ,SAAU6H,GAChC,OAAOD,GAAoB5R,KAAK3D,KAAMwV,EAAO,UAM/CF,GAAMpQ,UAAU+O,QAAU,SAAUuB,GAClC,OAAOD,GAAoB5R,KAAK3D,KAAMwV,EAAO,WAAW,SAAUA,GAAO,IAAAQ,EAAA,KACvER,EAAMjY,SAAQ,SAAA/C,GACZwb,EAAKxb,GAAQ,YACNwb,EAAKxb,UAQlB8a,GAAMpQ,UAAUiP,iBAAmB,SAAU3Z,GAC3C,OAAO+a,GAAoB5R,KAAK3D,KAAMxF,EAAM,qBAM9C8a,GAAMpQ,UAAU+Q,SAAW,SAAU/F,GAYnC,GATIhR,GAAMqG,SAAS2K,KACjBA,EAAYrU,SAASqa,eAAehG,IAAcrU,SAASuR,cAAc,qBAADpR,OAAsBkU,EAAS,SACtFA,EAAUiG,KACzBjG,EAAUlI,aAAa,kBAAmBkI,EAAUiG,IACpDjG,EAAUkG,gBAAgB,QAKzBlX,GAAM8G,UAAUkK,GAEnB,OADAhR,GAAMe,IAAIkE,MAAM,qCAAsC+L,IAC/C,EAIT,IAAMN,EAAO,IAAIK,GAAKC,EAAWL,GAAY7P,KAAKmQ,gBAAgBpC,KAAK/N,OAQvE,OANI4P,IAAS5P,KAAK4P,EAAKpV,OACrBwF,KAAK4P,EAAKpV,MAAQoV,EAClBA,EAAK9M,KAAK,cACD9C,KAAK4P,EAAKpV,OACnB0E,GAAMe,IAAIkE,MAAM,8BAA+ByL,EAAKpV,MAE/CoV,GAET0F,GAAMpQ,UAAUmR,YAAc,WAAY,IAAAC,EAAA,KACxC,GAAIxI,GAAS,SAASrB,SAAWqB,GAAS,WAAY,CACpD,IAAMnS,EAAOmS,GAAS,WAGtB,GAFA9N,KAAKuW,aAAe,EAEhB5a,EAAK6a,OAAS7a,EAAK+Q,OAAQ,CAS7B+J,aARgB,SAAVhK,KAEC9Q,EAAK+a,KAAOJ,EAAKC,eAAiB5a,EAAK+a,IAC1CJ,EAAK7J,UACI6J,EAAKC,cAAgB5a,EAAK+a,KACnCC,cAAclK,KAGkC,KAA9BmK,WAAWjb,EAAK6a,OAAS,KAGnD,OAAOxW,MAOTsV,GAAMpQ,UAAU2R,aAAe,WAa7B,OAZA3X,GAAMzC,GAAG,kBAAmB,SAAUoY,EAAO9X,GAC3C,IAAM6S,EAAOiF,EAAM9X,EAAMX,OAAO5B,MAEhC,GAAIoV,EAAM,CACR1Q,GAAMiH,OAAOyJ,EAAKA,EAAKiB,QAAS9T,EAAMX,OAAOwT,EAAKiB,SAClD,IAAMvV,EAAOyB,EAAMX,OAAO8E,IAAI5F,KACxBmT,EAASkH,GAAiBra,GAChCsU,EAAKgE,gBAAgBnF,GACrBmB,EAAK8D,SAASpY,GACdsU,EAAK9M,KAAK,aAAc/F,EAAMX,UAEhC2R,KAAK,KAAM/N,OACNA,MAMTsV,GAAMpQ,UAAU4M,eAAiB,WAC/B,IAAMgF,EAAchJ,GAAS,cAK7B,OAHI5O,GAAM8F,SAAS8R,KACjBjH,GAAa3Q,GAAMiM,WAAW2L,EAAajB,GAAmB9H,KAAK,KAAM/N,QAEpEA,MA4BTsV,GAAMpQ,UAAU6R,gBAAkB,WAEhCrc,OAAOiC,iBAAiB,UACxB,SAAmBkY,EAAO9X,GACxB,IAAMpB,EAAOuD,GAAMuC,UAAUS,MAAMnF,EAAMpB,MAEzC,GAAIA,EAAK2H,OAAS,UAAU+K,KAAK1S,EAAK2H,OAAS,SAAS+K,KAAK1S,EAAK2H,OAAQ,CACxE,IAAMA,EAAO3H,EAAK2H,KAAK3F,QAAQ,QAAS,IAElC0M,EAAWnL,GAAMiL,iBAAiBpN,EAAM6E,OAAOlH,QAC/CkV,EAAOiF,EAAMxK,KAAa,EAChC,IAAKuF,EAEH,YADA1Q,GAAMe,IAAIkE,MAAM,2CAGlB,OAAQb,GAEN,IAAK,iBACHsM,EAAK9M,KAAK,mBACV,MACF,IAAK,YACCnH,EAAKqb,WACPpH,EAAKiE,SAASlY,EAAKqb,WAErB,MAEF,IAAK,WACHpH,EAAK9M,KAAK,iBACV8M,EAAKI,WACL,MAEF,IAAK,mBACHJ,EAAK9M,KAAK,wBACV,MACF,QAEM,SAASuL,KAAK1S,EAAK2H,MACrBsM,EAAK9M,KAAK,QAASnH,GAEnBuD,GAAMe,IAAIkE,MAAM,gDArCmB4J,KAAK,KAAM/N,OAAO,IA8CjEsV,GAAMpQ,UAAU+R,iBAAmB,WACjCjX,KAAKkX,qBAAuBlX,KAAKkX,qBAAqB3Y,QAAO,SAAA4Y,GAC3D,OAAOpR,SAASoR,EAASC,MAAQvb,SAASwb,SAASF,EAASC,WAGhE9B,GAAMpQ,UAAUiL,gBAAkB,SAAUG,GAC1C,IAAMgH,EAAoBxJ,GAAS,aAAewC,EAAa,GAC/DtQ,KAAKkX,qBAAuBlX,KAAKkX,sBAAwB,GACzDlX,KAAKiX,mBAEL,IAAIM,EAAsBvX,KAAKkX,qBAAqBM,MAAK,SAAAL,GAEvD,OAAOG,EAAkBF,MAAQD,EAASC,QAgB5C,GAAI,yBAA0B1c,SAAW6c,GAAuBxR,QAAQuR,GAAoB,CAC1F,IAAMlR,EAAU,GAGiB,WAA7BhL,EAAOkc,KAELA,EAAkBlE,iBACpBhN,EAAQqR,WAAaH,EAAkBlE,gBAGrCkE,EAAkBnE,YACpB/M,EAAQ+M,UAAYmE,EAAkBnE,WAExC/M,EAAQgR,KAAOE,EAAkBF,MAAQ,MAE3CG,EAAsB,IAAIG,qBA5B5B,SAAkBC,GAAS,IAAAC,EAAA,KAGzBD,EAAQpZ,QAAO,SAAAsZ,GAAC,OAAIA,EAAEC,iBAAiBjV,QAAUgV,EAAEC,iBAAiBlV,OAASiV,EAAEC,iBAAiB9V,KAAO6V,EAAEC,iBAAiBC,QAAMC,MAAK,SAACH,EAAGI,GAAC,OAAKJ,EAAEC,iBAAiB9V,IAAMiW,EAAEH,iBAAiB9V,OAAKzE,SAAQ,SAAA2a,GACtM,IAAM7N,EAAW6N,EAAOtc,OAAO4O,aAAa,mBAExCH,GACFkL,GAAoB5R,KAAKiU,EAAMvN,EAAU,cAqBW0D,KAAK/N,MAAOoG,GACpEpG,KAAKkX,qBAAqB5I,KAAKiJ,GAEjC,OAAOA,GAETjC,GAAMpQ,UAAU3H,QAAU,SAAU4a,GAAI,IAAAC,EAAA,KAQtC,OAPA3X,OAAOgC,KAAKzC,MAAMzC,SAAQ,SAAA/C,GACxB,IAAMoV,EAAOwI,EAAK5d,GAEdoV,aAAgBK,IAClBkI,EAAGxU,KAAKyU,EAAMxI,MAGX5P,MAMTsV,GAAMpQ,UAAU0I,KAAO,WACrB5N,KAAKqW,cACLrW,KAAK6W,eACL7W,KAAK8R,iBACL9R,KAAK+W,kBACL/W,KAAKmQ,mBAEPmF,GAAMpQ,UAAUmT,MAAQ,WACtBzD,GAAQnU,OAAO6X,OAAOtY,QAExB,IAAI6U,GAAQ,IAAIS,GAEZiD,GAAa,GACjB,SAASC,MAETA,GAAUtT,UAAUuT,IAAM,WACxB,IAAMC,EAAU,CACdC,eAAgB3Y,KAAK4Y,kBACrBC,UAAW7Y,KAAK6Y,UAChB1N,WAAYnL,KAAKmL,YAGnB,IAAK,IAAMtG,KADX3F,GAAMiH,OAAOoS,GAAYvY,KAAK8Y,aAAc9Y,KAAKgL,cAC9B0N,EAGbA,EAAQvT,eAAeN,IACzB3F,GAAMiH,OAAOoS,GAAYG,EAAQ7T,MAGrC,OAAO0T,IAETC,GAAUtT,UAAUsM,IAAM,SAAUlM,GAE9BpG,GAAMwG,cAAcJ,IACtBpG,GAAMiH,OAAOoS,GAAYjT,IAG7BkT,GAAUtT,UAAU6O,OAAS,SAAUjP,GAEjCyT,GAAWzT,WACNyT,GAAWzT,IAGtB0T,GAAUtT,UAAUyI,MAAQ,WAC1B4K,GAAa,IAEfC,GAAUtT,UAAU8F,WAAa,WAC/B,GAAI8C,GAAS,mBACX,MAAO,CACLiL,aAAc7Z,GAAM8L,eAS1BwN,GAAUtT,UAAU4T,WAAa,WAC/B,IAAME,EAAK9Z,GAAMkK,oBAAoB,cACrC,GAAI4P,EACF,MAAO,CACLC,WAAYD,IAIlBR,GAAUtT,UAAU0T,kBAAoB,WACtC,IAAIM,EACE1Q,EAAWtJ,GAAMqJ,cAEjB4Q,EAAS,CACb,OAAQ,MACR,eAAgB,MAChB,eAAgB,MAChB,mBAAoB,MACpB,cAAe,MACfC,OAAQ,OASV,OAPA3Y,OAAOgC,KAAK0W,GAAQ5b,SAAQ,SAAA8L,GACL,IAAIE,OAAO,uBAADvN,OAAwBqN,EAAG,MAEzCgF,KAAK7F,KACpB0Q,EAAaC,EAAO9P,OAGjB6P,GAAc,CACnBG,OAAQH,IACL,IAEPV,GAAUtT,UAAUoU,WAAa,WAC/B,IAAMC,EAAKra,GAAMwH,KAAKxH,GAAMgK,iBAAkB,MAAO,KACjDsQ,EAAWD,EAAGE,GAAKF,EAAGpH,GAAKoH,EAAGG,OAASH,EAAGI,WAAaJ,EAAGK,kBAAevU,EAM7E,OAHImU,GAAyB,KAAbA,IACdA,EAAWK,SAASL,GAAU5K,cAAcjR,QAAQ,UAAW,KAAKA,QAAQ,OAAQ,KAAKuJ,QAEpF,CACL4S,GAAIN,IAGRhB,GAAUtT,UAAU2T,UAAY,WAC9B,MAAO,CACLkB,GAAI7a,GAAMwK,iBAGd8O,GAAUtT,UAAUiG,WAAa,WAC/B,OAAO2C,GAAS,cAAgB,CAC9BkM,IAAK9a,GAAMiM,WAAWnI,cACpB,IAENwV,GAAUtT,UAAUmT,MAAQ,WAC1B,IAAMpY,EAAMf,GAAMe,IACZsY,EAAavY,KAAKyY,MAEe,IAAnChY,OAAOgC,KAAK8V,GAAYlc,SAC1B4D,EAAIoE,MAAM,aACVpE,EAAI0E,eAAe3E,KAAKyY,OACxBxY,EAAIsE,QAGR,IAAIyK,GAAY,IAAIwJ,GAEdyB,GAAgB,CAAC,IAAK,MAc5B,SAASC,GAAmBC,EAAcC,GACxC,IAAKA,GAAeA,EAAY/d,OAAS,EACvC,OAAO8d,EAET,IAC6BE,EADvBC,EAAc,IAAIlL,gBAAgB+K,GAAcI,EAAArI,EACpCkI,GAAW,IAA7B,IAAAG,EAAApI,MAAAkI,EAAAE,EAAAnI,KAAAC,MAA+B,KAApBvN,EAAGuV,EAAAtV,MACZuV,EAAYE,OAAO1V,IACpB,MAAAwN,GAAAiI,EAAApY,EAAAmQ,GAAA,QAAAiI,EAAAhI,IACD,OAAO+H,EAAYhe,WA6BrB,SAASme,GAAcC,GAMrB,IAHC,IAFDzR,EAAIyR,EAAJzR,KACA0R,EAAOD,EAAPC,QAGMtR,EAAM,IAAIuR,IAAI3R,GACpB4R,EAAA,EAAAC,EAA8Bra,OAAOmS,QAAQ+H,GAAQE,EAAAC,EAAAze,OAAAwe,IAAE,CAAlD,IAAAE,EAAAjI,EAAAgI,EAAAD,GAAA,GAAOG,EAAKD,EAAA,GAAExc,EAAMwc,EAAA,GACvB,GAAc,SAAVC,EAAkB,CACpB,IACwBC,EADxBC,EAAAhJ,EACkB3T,GAAM,IAAxB,IAAA2c,EAAA/I,MAAA8I,EAAAC,EAAA9I,KAAAC,MAA0B,KAAfvN,EAAGmW,EAAAlW,MACZsE,EAAI8R,aAAaX,OAAO1V,IACzB,MAAAwN,GAAA4I,EAAA/Y,EAAAmQ,GAAA,QAAA4I,EAAA3I,SACI,CAEL,IAAM4H,EAAe9Q,EAAI8R,aAAa1C,IAAIuC,GACtCb,GACF9Q,EAAI8R,aAAaC,IAAIJ,EAAOd,GAAmBC,EAAc5b,KAInE,OAAO8K,EAAIJ,KAIb,IAAMoS,GAAoB,CACxBC,mBAAoB,IACpBC,oBAAqB,IACrBC,cAAe,GAGb1E,IAAc,EAUlB,SAASlJ,KACP,IAAM6N,EAAY3N,GAAS,QAAU,GACrCgJ,GAAchJ,GAAS,cACvB4N,KACAxc,GAAMzC,GAAG,YAAakf,GAAQ5N,KAAK,KAAM6N,KACzC1c,GAAMzC,GAAG,gBAAiBof,IAC1B3c,GAAMzC,GAAG,UAAWqf,IACpB5c,GAAMzC,GAAG,SAAUsf,IACnBC,UAAUC,IAAI3N,KAAK4N,GAAMnO,KAAK,KAAM0N,IAMtC,SAASC,KACFhhB,OAAOshB,YAEVthB,OAAOshB,UAAY,GAKnBthB,OAAOshB,UAAUC,IAAM,IAEzB/c,GAAMiI,OAAO,kDAAkD,GAAM,WACnEjI,GAAMzD,UAAU,yBACf,SAAA6W,GACDpT,GAAMzD,UAAU,oBAAqB6W,MAezC,SAAS4J,GAAMT,GACb,IAAMU,EAAkBrO,GAAS,mBAAqB,EAAI,EAC1DkO,UAAUI,SAASzf,iBAAiB,kBAAmB0f,IACvDC,GAAiBb,GACjBc,GAAiBd,GACjBe,GAAiBxN,GAAUyJ,OAC3BgE,KAGIhB,EAAUtW,eAAe,mBAC3BuX,GAAejB,EAAUiB,gBAE3B,IAAMrT,EAAMoR,GAAe,CACzBxR,KAAMvO,OAAOuJ,SAASgF,KACtB0R,QAAS,CACPvD,KAAM6C,MAMV,OAHA+B,UAAUW,iBACVX,UAAUI,SAASQ,aAAa,MAAOvT,GACvC2S,UAAUI,SAASS,6BAA6BV,IACzC,EA2BT,SAASO,GAAeI,GACtB,IAAIA,GAAyC,WAAxB1hB,EAAO0hB,IAAqD,kBAAjBA,EAI9D5d,GAAMe,IAAIC,KAAK,qDAAsD4c,OAJsB,CAC3F,IAAM7gB,EAAOwE,OAAOC,OAAO,GAAI2a,GAA2C,WAAxBjgB,EAAO0hB,GAA4BA,EAAe,IACpGpiB,OAAOshB,UAAUI,SAASM,eAAezgB,IAW7C,SAASsgB,GAAiBd,GACxB,IAAMsB,EAAYtB,EAAUsB,UACV,SAAdA,EACFf,UAAUI,SAASY,sBACI,QAAdD,EACTf,UAAUI,SAASa,sBAEnBjB,UAAUI,SAASc,uBAUvB,SAASV,GAAiBW,GAaxB,OAZIje,GAAMwG,cAAcyX,GACtBnB,UAAUC,IAAI3N,MAAK,WACjB,IAAM8N,EAASJ,UAAUI,SACzB3b,OAAOgC,KAAK0a,GAAe5f,SAAQ,SAAAuH,GAEjCsX,EAAOQ,aAAa9X,EAAKsY,OAAOD,EAAcrY,WAKlD5F,GAAMe,IAAIC,KAAK,kCAAmCid,GAE7CA,EAMT,SAASE,GAAyBvY,GAC3BpK,OAAOshB,UAIPlX,EAILkX,UAAUC,IAAI3N,MAAK,WACjB0N,UAAUI,SAASkB,eAAexY,MAJlC5F,GAAMe,IAAIC,KAAK,wDAJfhB,GAAMe,IAAIC,KAAK,6EAkBnB,SAASuc,KACP,IAAMc,EAAOzP,GAAS,iBACT,WAATyP,GACFvB,UAAUI,SAASoB,mBAAkB,GAE1B,UAATD,GACFvB,UAAUI,SAASoB,mBAAkB,GAQzC,SAASlB,GAAiBb,GACpBA,EAAUgC,aACZzB,UAAUI,SAASsB,qBACnB1B,UAAU2B,eAAeC,yBAAwB,IAarD,SAASjC,GAAQC,EAAa7e,GAC5B,IAAM6S,EAAO7S,EAAMX,OAAOwT,KAEN,QAAhBA,EAAKiB,SACPjB,EAAK1O,IAAM,GAGXhC,GAAMiH,OAAOyJ,EAAMgM,GAGnBI,UAAUC,IAAI3N,MAAK,WACjBsB,EAAKiO,aAAaC,cAAcC,mBAAmBnB,eAAeoB,UAC7DpO,EAAKkB,OAASlB,EAAKE,gBACtBF,EAAKqO,cAQb,SAASpC,GAAS9e,GAChB,IAAM6S,EAAO7S,EAAMX,OAAOwT,KAEtB1Q,GAAMkE,WAAWwM,EAAKqO,UACxBrO,EAAKqO,UAOT,SAASnC,GAAU/e,GAUjB,OATArC,OAAOshB,UAAUC,IAAI3N,MAAK,WACxB,IAAMU,EAAYjS,EAAMX,OAAO4S,UAC3B9P,GAAMwG,cAAcsJ,IACtBvO,OAAOgC,KAAKuM,GAAWzR,SAAQ,SAAA/C,GAC7BuC,EAAMX,OAAOwT,KAAK1O,IAAI0O,KAAKgN,aAAapiB,EAAMwU,EAAUxU,OAG5DwhB,UAAUI,SAAS3P,QAAQ,CAAC1P,EAAMX,OAAOwT,KAAK1O,IAAI0O,UAE7C5P,KAET,SAAS+b,GAAShf,GAChB,IAAMmhB,EAASnhB,EAAMX,OAAOwT,KAAK1O,IAAIgd,OAC/B5iB,EAAOyB,EAAMX,OAAOd,KAC1B4iB,EAAOtb,MAAQtH,EAAK,GACpB4iB,EAAOrb,OAASvH,EAAK,GAMvB,SAAS+gB,GAActf,GACrB,IAAIohB,EACExiB,EAAO,CACXuF,IAAK,IAEDkd,EAAYrhB,EAAM6S,KAAKyO,YACvBC,EAAQF,EAAUG,WAAWxX,MAAM,KACnCyX,EAAW,qBAAHxiB,OAAwBoiB,EAAUK,SAChD9iB,EAAK2H,KAAOgb,EAAMvT,MAClBpP,EAAKnB,KAAO8jB,EAAM9iB,KAAK,KACvBG,EAAKL,KAAOyB,EAAMzB,MAAQyB,EAAMzB,KAAKe,OAASU,EAAMzB,KAAKE,OAAS,GAClEG,EAAKJ,WAAawB,EAAMxB,WACxB,IAAMmjB,EAAgB3hB,EAAM6S,KAAK+O,iBAAmB5hB,EAAM6S,KAAK+O,kBAC/DhjB,EAAKN,IAAMoE,MAAMN,QAAQuf,aAAqD,EAASA,EAAcrjB,MAAqD,QAA5C8iB,EAAqBO,EAAcrjB,WAAwC,IAAvB8iB,GAAiCA,EAAmB9hB,OAASqiB,EAAcrjB,IAAIG,OAAS,GAC1P,IAAMojB,EAAoBjjB,EAAKN,IAAIoD,SAAS,UACtCrC,EAAST,EAAKuF,IACpB9E,EAAOiF,QAAUtE,EAAMsE,QACvBjF,EAAOd,KAAOyB,EAAMzB,KACpBc,EAAOb,WAAawB,EAAMxB,WAC1Ba,EAAOiZ,WAAatY,EAAMsY,WAC1BjZ,EAAOyiB,YAAc9hB,EAAM8hB,YAC3B,IAAMC,EAAWjjB,SAASqa,eAAesI,GACrCM,GACGF,IAEHE,EAAS9W,aAAa,WAAY,MAClC8W,EAAS9W,aAAa,cAAe,QACrC8W,EAAS9W,aAAa,OAAQ,iBAEhC8W,EAAS9W,aAAa,QAAS,iBAC/B5L,EAAO8hB,OAASY,GAGhB5f,GAAMe,IAAIC,KAAK,uCAEjBhB,GAAMzD,UAAU,kBAAmBE,GASrC,IAAMigB,GAAc,CAIlBiC,WAAY,WAAY,IAAAkB,EAAA,KAgBtB,OAfArkB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxByQ,EAAK7d,IAAIiV,GAAK,GAAHna,OAAM+iB,EAAKvkB,KAAI,QAC1BukB,EAAKrO,MAAM1I,aAAa,KAAM+W,EAAK7d,IAAIiV,IACvC4I,EAAKC,cACAD,EAAK9N,UAQR8N,EAAK7d,IAAI0O,KAAOoM,UAAUiD,oBAAoBF,EAAK7d,IAAIkU,SAAU2J,EAAK7d,IAAIiV,IAPtEW,IAAe5X,GAAM8F,SAAS+Z,EAAKxT,QACrCwT,EAAKjN,iBACLiN,EAAK7d,IAAI0O,KAAOoM,UAAU6B,WAAWkB,EAAK7d,IAAIkU,SAAU,CAAC,EAAG,GAAI2J,EAAK7d,IAAIiV,IAAI+I,kBAAkBH,EAAK7d,IAAIqK,QAExGwT,EAAK7d,IAAI0O,KAAOoM,UAAU6B,WAAWkB,EAAK7d,IAAIkU,SAAU2J,EAAKxT,MAAOwT,EAAK7d,IAAIiV,OAM5EnW,MAETgU,UAAW,SAAUmL,GACnB,SAAIzkB,OAAOshB,UAAUoD,cAAe1kB,OAAOshB,UAAUI,UACnD+C,EAAUA,GAAWnf,KAAKkB,IAAI0O,KACvBoM,UAAUI,SAASzO,MAAM,CAACwR,MAKrCrN,eAAgB,WAAY,IAAAuN,EAAA,KAyB1B,OAxBA3kB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxBpP,GAAMzC,GAAG,cAAc,SAAAM,GACrB,IAAM6S,EAAO7S,EAAMX,OAAOwT,KACpBC,EAAa9S,EAAMX,OAAOyT,WAChCyP,GAAoB,CAClBtF,IAAKnK,IAEHD,EAAKE,aAAaD,KAEhBD,EAAK1O,IAAIgd,OACXtO,EAAK9M,KAAK,WACAuc,EAAKvO,OACflB,EAAKqO,aAGRoB,EAAKnP,WACR,IAAM1B,EAAUwN,UAAUuD,cAC1B9e,OAAOgC,KAAKqU,IAAavZ,SAAQ,SAAAmF,GAC3B2c,EAAK9T,MAAM7I,IACb8L,EAAQgR,QAAQ1I,GAAYpU,GAAa2c,EAAK9T,MAAM7I,OAGxD2c,EAAKne,IAAIqK,MAAQiD,EAAQiR,WAEpBzf,MAKTkU,YAAa,SAAUiL,GACrB,SAAIzkB,OAAOshB,UAAUoD,cAAe1kB,OAAOshB,UAAUI,UACnD+C,EAAUA,GAAWnf,KAAKkB,IAAI0O,KACvBoM,UAAU0D,aAAa,CAACP,MAQnClB,QAAS,WAAY,IAAA0B,EAAA,KAKnB,OAJAjlB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxBqR,EAAK7c,KAAK,gBACVkZ,UAAUiC,QAAQ0B,EAAKze,IAAIiV,OAEtBnW,MAKTgf,YAAa,WAAY,IAAAY,EAAA,KAmBvB,OAlBAllB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxB,IAAI8G,EACElU,EAAM4M,GAAS,QAAU,GACzByG,EAAOqL,EAAK1P,UAAU1F,aAAa,4BACzC,GAAItL,GAAM2G,iBAAiB0O,GACzBa,EAAWb,OACN,GAAIrV,GAAM2G,iBAAiB3E,EAAIkU,UACpCA,EAAWlU,EAAIkU,aACV,CACL,IAAMyK,EAAU3e,EAAI2e,QACdC,EAAO5e,EAAI4e,KACXC,EAAO7e,EAAI6e,KACjB3K,EAAW,IAAHpZ,OAAO6jB,GACfzK,GAAYlW,GAAM2G,iBAAiBia,GAAQ,IAAH9jB,OAAO8jB,GAAS,GACxD1K,GAAYlW,GAAM2G,iBAAiBka,GAAQ,IAAH/jB,OAAO+jB,GAAS,GAE1DH,EAAK1e,IAAIkU,SAAWA,KAEfpV,MAKT8d,YAAa,SAAUqB,GAAS,IAAAa,EAAA,KAS9B,OARAtlB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxB,IAAMpN,EAAM4M,GAAS,QAAU,IAC/BqR,EAAUA,GAAWa,EAAK9e,IAAI0O,MACtBqQ,WAAWjE,UAAUI,UACzBlb,EAAIuc,aAAiC,IAAnBuC,EAAK9O,WACzBiO,EAAQc,WAAWjE,UAAU2B,mBAG1B3d,MAMT+d,iBAAkB,WAAY,IAAAmC,EAAA,KAW5B,OAVAxlB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxB,IAAMiP,EAAO2C,EAAK1Q,eAAiB1B,GAAS,kBArapB,QAsaX,WAATyP,EACF2C,EAAKhf,IAAI0O,KAAKuQ,qBAAoB,GAAM,GACtB,UAAT5C,EACT2C,EAAKhf,IAAI0O,KAAKuQ,qBAAoB,GAChB,UAAT5C,GACT2C,EAAKhf,IAAI0O,KAAKuQ,qBAAoB,MAG/BngB,MAEToU,oBAAqB,WAWnB,GAAIpU,KAAKiR,WAAajR,KAAKkB,IAAIgd,OAAQ,CACrC,IAAMkC,GAVkBlC,EAUele,KAAKkB,IAAIgd,QAT1CmC,EAAqBnC,EAAO3T,cAAc1O,SAASuR,cAAc,gCAE9DiT,EAAmBC,QAAQC,mBAElCrhB,GAAMe,IAAIC,KAAK,mEACR,IAMLkgB,GACFlhB,GAAMiI,OAAOiZ,GAAe,GAAM,WAChClhB,GAAMe,IAAImE,KAAK,+BACd,WACDlF,GAAMe,IAAImE,KAAK,kDACd,QAGLlF,GAAMe,IAAIC,KAAK,yDApBjB,IAA0Bge,EAClBmC,GA0BVrC,OAAQ,SAAUmB,GAAS,IAAAqB,EAAA,KAMzB,OALA9lB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxB6Q,EAAUA,GAAWqB,EAAKtf,IAAI0O,KAC9B,IAAM1C,EAAYY,GAAS,aAC3BqR,EAAQ/D,IAAI,WAAYlO,GAAwBhO,GAAM8J,kBAEjDhJ,MAKT4c,aAAc,SAAUuC,GAAS,IAAAsB,EAAA,KAU/B,OATA/lB,OAAOshB,UAAUC,IAAI3N,MAAK,WACxB6Q,EAAUA,GAAWsB,EAAKvf,IAAI0O,KAE1B1Q,GAAMwG,cAAc+a,EAAKzR,YAC3BvO,OAAOgC,KAAKge,EAAKzR,WAAWzR,SAAQ,SAAAyd,GAClCmE,EAAQvC,aAAa5B,EAAOyF,EAAKzR,UAAUgM,UAI1Chb,OAeX,SAAS0gB,KACPxhB,GAAMe,IAAIC,KAAK,2GACf8b,UAAUC,IAAI3N,MAAK,WACjB0N,UAAUI,SAASsE,sBAGvB,SAASvf,KACP,GAAIzG,OAAOshB,WAAathB,OAAOshB,UAAUI,OACvC,OAAOJ,UAAUI,SAASjb,gBAG9B,SAASwf,KACHjmB,OAAOshB,UACTA,UAAUC,IAAI3N,MAAK,WACjB0N,UAAUI,SAASkB,oBAGrBpe,GAAMe,IAAIC,KAAK,6EAGnB,SAASof,GAAoBsB,GACvBlmB,OAAOshB,UAETQ,GADetd,GAAMwG,cAAckb,GAAYA,EAAW5R,GAAUyJ,OAGpEvZ,GAAMe,IAAIC,KAAK,2EAInB,SAAS2gB,KACP,SAAInmB,OAAOshB,YAAathB,OAAOshB,UAAU8E,UAM3C,SAASzI,KACP,IAAMpY,EAAMf,GAAMe,IACZ8gB,EAAOjT,GAAS,OACjBiT,IAGL9gB,EAAIoE,MAAM,OACVpE,EAAI0E,eAAeoc,GACnB9gB,EAAIsE,OAEN,IAAIrD,GAAM,CACR0M,QACAsO,SACAwE,oBACAvf,iBACAme,uBACAqB,sBACAtD,4BACAwD,gBACAnF,WACArD,UAIF,SAAS2I,KACPC,KACIvmB,SAAWA,OAAOuG,OACpBvG,OAAOuG,KAAOjB,MAGlB8N,GAASF,KAAOI,GAChBF,GAASH,MAAQA,GAGjBqT,GAAI9b,UAAU2I,OAASC,GACvBkT,GAAI9b,UAAU2P,MAAQA,GACtBmM,GAAI9b,UAAUhE,IAAMA,GACpB8f,GAAI9b,UAAU8J,UAAYA,GAC1BgS,GAAI9b,UAAUhG,MAAQA,GAMtB8hB,GAAI9b,UAAU0I,KAAO,SAAUxH,GAC7BA,EAAUA,GAAW,GACrBpG,KAAK6N,OAAOD,OACZ,IAAMsT,EAAgBzgB,OAAOC,OAAO0F,EAAS,CAC3C+V,iBAAkB/V,EAAQ+a,uBAkB5B,OAhBAnhB,KAAK6N,OAAOqT,GACR9a,EAAQ+a,qBACVnhB,KAAKohB,SAAW,CACdC,YAAY,GAGdrhB,KAAKohB,SAAWE,KAEdthB,KAAKohB,SAASC,YAChBrhB,KAAKd,MAAMzD,UAAU,qBAEnBuE,KAAKohB,SAASG,cAChBvhB,KAAKd,MAAMzD,UAAU,uBAEvBuE,KAAKd,MAAMzD,UAAU,gBACrBuE,KAAKgP,UAAUwC,IAAIxR,KAAK6N,SAASmB,WAC1BwS,QAAQC,QAAQzhB,KAAK0hB,gBAM9BV,GAAI9b,UAAUyc,gBAAkB,SAAUhmB,GACxCqE,KAAKgP,UAAUwC,IAAI7V,GACnBqE,KAAKkB,IAAIoe,oBAAoBtf,KAAKgP,UAAUyJ,QAE9CuI,GAAI9b,UAAUwc,YAAc,WAe1B,OAdA1hB,KAAK6U,MAAMjH,OACP5N,KAAKohB,SAASG,eAChBvhB,KAAK6N,OAAO,CACVsO,iBAAiB,IAEnBnc,KAAKgP,UAAUwC,IAAI,CACjBoQ,GAAI,OAGR5hB,KAAKkB,IAAI0M,OACT5N,KAAKd,MAAMzC,GAAG,QAASuD,KAAKqY,MAAMtK,KAAK/N,OACvCA,KAAK6hB,eAAgB,EACrB7hB,KAAKd,MAAMzD,UAAU,cAAeuE,MACpC8hB,KACO9hB,MAETghB,GAAI9b,UAAUmT,MAAQ,WACpB,IAAItE,GAAS,EACThQ,aAAaC,QAAQ,QACvB+P,GAAS,EAEThQ,aAAage,QAAQ,QAAQ,GAE/B/hB,KAAKkB,IAAImX,QACTrY,KAAK6U,MAAMwD,QACXrY,KAAKgP,UAAUqJ,QACXtE,GACFhQ,aAAaie,WAAW,SAG5BhB,GAAI9b,UAAU+c,QAAU,WACtBjiB,KAAKd,MAAMe,IAAIC,KAAK,sFACpBF,KAAKd,MAAMe,IAAI,kBAADjE,OAAmBgE,KAAKd,MAAM8L,gBAE9CgW,GAAI9b,UAAU8F,WAAa,WACzB,OAAOhL,KAAKd,MAAM8L,cAEpB,IAAMkX,GAAU,WACd,OAAOC,GAAIvU,OAAOwU,MAAK,WACP3iB,MAAMoN,KAAKhR,SAASiR,iBAAiB,8BAC7CvP,QAAQ4kB,GAAItN,MAAMoB,SAASlI,KAAKoU,GAAItN,YAI9C,SAASyM,KAEP,IACMviB,EAAQlD,SAASgP,OAAO9L,MADnB,qBAEX,IAAKA,EAEH,MAAO,CACLsiB,YAAY,EACZE,cAAc,GAGlB,IAAMc,EAAgB5Y,mBAAmB1K,EAAM,IAC/C,MAAO,CACLsiB,YAAkE,IAAtDgB,EAAc7e,QAAQ,2BAClC+d,cAAqE,IAAvDc,EAAc7e,QAAQ,6BAGxC,SAASyd,KACPplB,SAASc,iBAAiB,qBAAsBulB,IAElD,SAASJ,KACPjmB,SAASgB,oBAAoB,qBAAsBqlB,IAtBrDlB,GAAI9b,UAAUgd,QAAUA,GAwBxB,IAE+BI,GAFtBC,GAAHJ,GAAM,IAAInB,IAEesB,GAAA,oBAAAE,0CAAAC,aAAApd,KAAAid,GAAAI,SAttFzBnoB,EAAQ,6GAAA+nB,GAAAI,SAWLznB,EAAmB,wHAAAqnB,GAAAI,SAcnBjnB,EAAS,8GAAA6mB,GAAAI,SA4BTjmB,EAAE,uGAAA6lB,GAAAI,SAaF9lB,EAAG,wGAAA0lB,GAAAI,SAaH5lB,EAAI,yGAAAwlB,GAAAI,SAeJzlB,EAAiB,sHAAAqlB,GAAAI,SA4BjBzkB,EAAc,mHAAAqkB,GAAAI,SAqBd1jB,EAAsB,2HAAAsjB,GAAAI,SAatBpjB,EAAY,iHAAAgjB,GAAAI,SAcZ3iB,EAAkB,uHAAAuiB,GAAAI,SAQlBriB,EAAW,gHAAAiiB,GAAAI,SA8BXphB,EAAc,mHAAAghB,GAAAI,SAWnBjhB,EAAS,8GAAA6gB,GAAAI,SAsBThmB,EAAQ,6GAAA4lB,GAAAI,SACRnhB,EAAa,kHAAA+gB,GAAAI,SACblhB,EAAO,4GAAA8gB,GAAAI,SACFtgB,EAAoB,yHAAAkgB,GAAAI,SAcpB5f,EAAI,yGAAAwf,GAAAI,SAOJ3f,EAAU,+GAAAuf,GAAAI,SAGV1f,EAAU,+GAAAsf,GAAAI,SAGVzf,EAAM,2GAAAqf,GAAAI,SAiCNziB,EAAG,wGAAAqiB,GAAAI,SAoBN9e,EAAI,yGAAA0e,GAAAI,SASJxiB,EAAI,yGAAAoiB,GAAAI,SAQJve,EAAK,0GAAAme,GAAAI,SAQLte,EAAI,yGAAAke,GAAAI,SASJre,EAAK,0GAAAie,GAAAI,SAULne,EAAG,wGAAA+d,GAAAI,SAMHje,EAAK,0GAAA6d,GAAAI,SASL/d,EAAc,mHAAA2d,GAAAI,SAuBN,SAAH,4GAAAJ,GAAAI,SAOLzd,EAAG,wGAAAqd,GAAAI,SAmBAtd,EAAE,uGAAAkd,GAAAI,SAgBLvjB,EAAO,4GAAAmjB,GAAAI,SASPnd,EAAQ,6GAAA+c,GAAAI,SASRtf,EAAU,+GAAAkf,GAAAI,SASVld,EAAS,8GAAA8c,GAAAI,SAST1d,EAAQ,6GAAAsd,GAAAI,SASRjd,EAAQ,6GAAA6c,GAAAI,SAWRhd,EAAa,kHAAA4c,GAAAI,SAkCb7c,GAAgB,qHAAAyc,GAAAI,SAGhB1c,GAAS,8GAAAsc,GAAAI,SAGNvc,GAAM,2GAAAmc,GAAAI,SAoFThc,GAAI,yGAAA4b,GAAAI,SA2BJvb,GAAM,2GAAAmb,GAAAI,SAsDNna,GAAW,gHAAA+Z,GAAAI,SASXja,GAAW,gHAAA6Z,GAAAI,SAWX5Z,GAAkB,uHAAAwZ,GAAAI,SAWlB1Z,GAAW,gHAAAsZ,GAAAI,SAUXxZ,GAAc,mHAAAoZ,GAAAI,SAUdtZ,GAAmB,wHAAAkZ,GAAAI,SAkBnBhZ,GAAY,iHAAA4Y,GAAAI,SAYZvY,GAAgB,qHAAAmY,GAAAI,SA6BhBjY,GAAoB,yHAAA6X,GAAAI,SAMpB7X,GAAM,2GAAAyX,GAAAI,SAIN1X,GAAU,+GAAAsX,GAAAI,SACVzX,GAAsB,2HAAAqX,GAAAI,SACnB/iB,GAAQ,6GAAA2iB,GAAAI,SAGbxjB,GAAK,0GAAAojB,GAAAI,SA4CHtX,GAAQ,6GAAAkX,GAAAI,SA0DL9V,GAAsB,2HAAA0V,GAAAI,SActBzV,GAAiB,sHAAAqV,GAAAI,SAgBjBrV,GAAM,2GAAAiV,GAAAI,SA+BT7U,GAAM,2GAAAyU,GAAAI,SACR5U,GAAQ,6GAAAwU,GAAAI,SACN1U,GAAM,2GAAAsU,GAAAI,SACN/U,GAAK,0GAAA2U,GAAAI,SAELzU,GAAkB,uHAAAqU,GAAAI,SAClBxU,GAAoB,yHAAAoU,GAAAI,SACpBvU,GAAgB,qHAAAmU,GAAAI,SAsHhBjT,GAA8B,mIAAA6S,GAAAI,SAK9B/S,GAAkB,uHAAA2S,GAAAI,SAgBfzS,GAAI,yGAAAqS,GAAAI,SA0VJ3Q,GAAY,iHAAAuQ,GAAAI,SAaZlQ,GAAgB,qHAAA8P,GAAAI,SAchB3P,GAAc,mHAAAuP,GAAAI,SAajBhO,GAAM,2GAAA4N,GAAAI,SAKH9N,GAAO,4GAAA0N,GAAAI,SAwBZ7S,GAAU,+GAAAyS,GAAAI,SAQLpN,GAAK,0GAAAgN,GAAAI,SAGLnN,GAAmB,wHAAA+M,GAAAI,SAsBnBhN,GAAG,wGAAA4M,GAAAI,SAgBH/M,GAAgB,qHAAA2M,GAAAI,SAyJhB7M,GAAkB,uHAAAyM,GAAAI,SA8IvB7N,GAAK,0GAAAyN,GAAAI,SAELnK,GAAU,+GAAA+J,GAAAI,SACLlK,GAAS,8GAAA8J,GAAAI,SA4Gd1T,GAAS,8GAAAsT,GAAAI,SAEPzI,GAAa,kHAAAqI,GAAAI,SAcVxI,GAAkB,uHAAAoI,GAAAI,SAqClBjI,GAAc,mHAAA6H,GAAAI,SAwBjBrH,GAAiB,sHAAAiH,GAAAI,SAKO,QAAH,0HAAAJ,GAAAI,SACvB5L,GAAW,gHAAAwL,GAAAI,SAUN9U,GAAI,yGAAA0U,GAAAI,SAcJhH,GAAO,4GAAA4G,GAAAI,SA4BPxG,GAAK,0GAAAoG,GAAAI,SAgDLhG,GAAc,mHAAA4F,GAAAI,SAcdnG,GAAgB,qHAAA+F,GAAAI,SAiBhBlG,GAAgB,qHAAA8F,GAAAI,SAmBhBrF,GAAwB,6HAAAiF,GAAAI,SAoBxBjG,GAAoB,yHAAA6F,GAAAI,SAcpBpG,GAAgB,qHAAAgG,GAAAI,SAgBhB/G,GAAO,4GAAA2G,GAAAI,SAqBP7G,GAAQ,6GAAAyG,GAAAI,SAWR5G,GAAS,8GAAAwG,GAAAI,SAYT3G,GAAQ,6GAAAuG,GAAAI,SAURrG,GAAa,kHAAAiG,GAAAI,SA4ChB9G,GAAW,gHAAA0G,GAAAI,SAsMRhC,GAAgB,qHAAA4B,GAAAI,SAMhBvhB,GAAa,kHAAAmhB,GAAAI,SAKb/B,GAAkB,uHAAA2B,GAAAI,SASlBpD,GAAmB,wHAAAgD,GAAAI,SASnB7B,GAAY,iHAAAyB,GAAAI,SAOZrK,GAAK,0GAAAiK,GAAAI,SAUVxhB,GAAG,wGAAAohB,GAAAI,SAcE1B,GAAG,wGAAAsB,GAAAI,SA0FNR,GAAO,4GAAAI,GAAAI,SAOJpB,GAAW,gHAAAgB,GAAAI,SAiBXzB,GAAmB,wHAAAqB,GAAAI,SAGnBZ,GAAsB,2HAAAQ,GAAAI,SAGzBP,GAAG,0GAAAI,GAAA,oBAAAC,0CAAAD,iBAAAld,IAAAkd,GAAAI,I","file":"3.e746a71b.js","sourcesContent":["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\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  if (performance && performance.mark) {\n    performance.clearMarks(name);\n    performance.mark(name);\n  }\n};\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\nfunction buildPerfmarkSuffix(eventDetailsObj) {\n  let suffix = \"\";\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  return suffix;\n}\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 */\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/**\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 */\nfunction on(name, callback, target) {\n  name = `oAds.${name}`;\n  /* istanbul ignore next: ignore the final fallback as hard trigger */\n  target = target || document.body || document.documentElement;\n  target.addEventListener(name, callback);\n}\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 */\nfunction off(name, callback, target) {\n  name = `oAds.${name}`;\n  /* istanbul ignore next: ignore the final fallback as hard trigger */\n  target = target || document.body || document.documentElement;\n  target.removeEventListener(name, callback);\n}\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 */\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    if (callback) {\n      callback(event);\n\n      // we set callback to null so if for some reason the listener isn't removed the callback will still only be called once\n      callback = null;\n    }\n  };\n  on(name, handler, target);\n}\n\nfunction getMarksForEvents(events, suffix) {\n  const markNames = events.map(eventName => \"oAds.\" + eventName + suffix);\n  if (!performance || !performance.getEntriesByName) {\n    /* istanbul ignore next  */\n    return {};\n  }\n  const marks = {};\n  markNames.forEach(function (mName) {\n    const pMarks = performance.getEntriesByName(mName);\n    const markName = mName.replace(\"oAds.\", \"\").replace(suffix, \"\");\n    if (pMarks && pMarks.length) {\n      // We don't need sub-millisecond precision\n      marks[markName] = Math.round(pMarks[0].startTime);\n      return;\n    }\n\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    if (suffix) {\n      const mNameNoSuffix = mName.replace(suffix, \"\");\n      const pMarks2 = performance.getEntriesByName(mNameNoSuffix);\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  const relevantGroups = metricsDefinitions.filter(group => groupsToClear.includes(group.spoorAction));\n  const relevantGroupsMarks = relevantGroups.map(group => group.marks);\n  // Because relevantGroupsMarks is a 2D array ...\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\n/* istanbul ignore next */\nfunction getNavigationPerfMarks(desiredMarks) {\n  if (!performance || !performance.getEntriesByType || !utils.isArray(desiredMarks)) {\n    /* istanbul ignore next  */\n    return {};\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}\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  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}\nfunction sendMetricsOnEvent(eventName, eMarkMap, callback) {\n  document.addEventListener(eventName, function listenOnInitialised(event) {\n    sendMetrics(eMarkMap, event.detail, callback);\n    if (!eMarkMap.multiple) {\n      document.removeEventListener(eventName, listenOnInitialised);\n    }\n  });\n}\nfunction sendMetrics(eMarkMap, eventDetails, callback) {\n  const suffix = utils.buildPerfmarkSuffix(eventDetails);\n  const marks = getMarksForEvents(eMarkMap.marks, suffix);\n  if (eMarkMap.navigation) {\n    const navMarks = getNavigationPerfMarks(eMarkMap.navigation);\n    Object.assign(marks, navMarks);\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  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    if (typeof eventDetails.isEmpty === \"boolean\") {\n      eventPayload.creative.isEmpty = eventDetails.isEmpty;\n    }\n  }\n  callback(eventPayload);\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 */\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    }\n\n    // try returning the parsed object\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;\nfunction getNearestBreakpoint() {\n  let winner;\n  const dims = oViewport.getSize(true);\n  function findCurrentBreakpoint(breakpoint) {\n    const breakpointDims = breakpoints$1[breakpoint];\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  Object.keys(breakpoints$1).forEach(findCurrentBreakpoint);\n  return winner;\n}\nfunction fire() {\n  const winner = getNearestBreakpoint();\n  if (current !== winner) {\n    setCurrent(winner);\n    callback(winner);\n  }\n}\nfunction setCurrent(name) {\n  current = name;\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  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/**\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 */\nfunction log() {\n  let type;\n  let argsIndex;\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  const args = [].slice.call(arguments, argsIndex);\n  if (log.isOn(type)) {\n    window.console[type].apply(window.console, args);\n  }\n}\n\n/**\n * Determine if debug logging is on and if the type if supported\n * @param {string} type\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/**\n * Log a warning message\n */\nconst warn = function () {\n  const args = [\"warn\"].concat([].slice.call(arguments, 0));\n  log.apply(null, args);\n};\n\n/**\n * Log an error message\n */\nconst error = function () {\n  const args = [\"error\"].concat([].slice.call(arguments, 0));\n  log.apply(null, args);\n};\n\n/**\n * Log an info message\n */\nconst info = function () {\n  const args = [\"info\"].concat([].slice.call(arguments, 0));\n  log.apply(null, args);\n};\n\n/**\n * Start a collapsed group\n * @param {string} group the name of the group, defaults to o-ads\n */\nconst start = function (group) {\n  if (!log.isOn(\"groupCollapsed\")) {\n    return;\n  }\n  window.console.groupCollapsed(group || \"o-ads\");\n};\n\n/**\n * End a collapsed group\n */\nconst end = function () {\n  if (!log.isOn(\"groupEnd\")) {\n    return;\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        if (isArray(object[item]) || isObject(object[item])) {\n          val = JSON.stringify(object[item]);\n        } else {\n          val = object[item];\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 */\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/**\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 */\nfunction is(object) {\n  const type = Object.prototype.toString.call(object).match(/^\\[object\\s(.*)\\]$/)[1];\n  if (object === null) {\n    return \"Null\";\n  } else if (object === undefined) {\n    return \"Undefined\";\n  } else {\n    return type;\n  }\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 */\nconst isArray = function (obj) {\n  return is(obj) === \"Array\";\n};\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 */\nconst isString = function (obj) {\n  return is(obj) === \"String\";\n};\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 */\nconst isFunction = function (obj) {\n  return is(obj) === \"Function\";\n};\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 */\nconst isStorage = function (obj) {\n  return is(obj) === \"Storage\";\n};\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 */\nconst isObject = function (obj) {\n  return is(obj) === \"Object\";\n};\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 */\nconst isWindow = function (obj) {\n  return obj && obj !== null && obj === window;\n};\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 */\nconst isPlainObject = function (obj) {\n  const hop = Object.prototype.hasOwnProperty;\n\n  // 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  if (!obj || !isObject(obj) || obj.nodeType || isWindow(obj)) {\n    return false;\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  }\n\n  // Own properties are enumerated firstly, so to speed up,\n  // if last one is own, then all properties are own.\n  let key;\n  for (key in obj) {\n    // empty\n  }\n  return key === undefined || hop.call(obj, key);\n};\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 */\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  /* 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;\n\n  // Handle a deep copy situation\n  if (typeof target === \"boolean\") {\n    deep = target;\n    target = arguments[1] || {};\n\n    // skip the boolean and the target\n    i = 2;\n  }\n\n  // Handle case when target is a string or something (possible in deep copy)\n  /* istanbul ignore else  */\n  if (typeof target !== \"object\" && !isFunction(target)) {\n    target = {};\n  }\n\n  // do nothing if only one argument is passed (or 2 for a deep copy)\n  /* istanbul ignore else  */\n  if (length === i) {\n    return target;\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];\n\n          // Prevent never-ending loop\n          if (target === copy) {\n            continue;\n          }\n\n          // Recurse if we're merging arrays\n          if (deep && copy && (isPlainObject(copy) || isArray(copy))) {\n            copyIsArray = isArray(copy);\n            if (copyIsArray) {\n              copyIsArray = false;\n              clone = src && isArray(src) ? src : [];\n            } else {\n              clone = src && isObject(src) ? src : {};\n            }\n\n            // Never move original objects, clone them\n            target[name] = extend(deep, clone, copy);\n\n            // Don't bring in undefined values\n          } else if (copy !== undefined) {\n            target[name] = copy;\n          }\n        }\n      }\n    }\n  }\n\n  // Return the modified object\n  return target;\n}\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 */\nconst hash = function (str, delimiter, pairing) {\n  let pair;\n  let value;\n  const hashObj = {};\n  if (str && str.split) {\n    str = str.split(delimiter);\n    for (let idx = 0, l = str.length; idx < l; idx += 1) {\n      value = str[idx];\n      pair = value.split(pairing);\n      if (pair.length > 1) {\n        hashObj[pair[0].trim()] = pair.slice(1).join(pairing);\n      }\n    }\n  }\n  return hashObj;\n};\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 */\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  function processCallback(callback) {\n    /* istanbul ignore else  */\n    if (!hasRun) {\n      callback.call();\n      hasRun = true;\n      /* istanbul ignore else  */\n      if (autoRemove) {\n        tag.parentElement.removeChild(tag);\n      }\n    }\n  }\n  tag.setAttribute(\"src\", scriptUrl);\n  tag.setAttribute(\"o-ads\", \"\");\n  /* istanbul ignore else */\n  if (async) {\n    tag.async = \"true\";\n  }\n  /* istanbul ignore else  */\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\n  /* istanbul ignore else  */\n  if (isFunction(errorcb)) {\n    tag.onerror = function () {\n      processCallback(errorcb);\n    };\n  }\n  // Use insert before, append child has issues with script tags in some browsers.\n  node.parentNode.insertBefore(tag, node);\n  return tag;\n};\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/* istanbul ignore next - cannot reliably test value of referer */\nconst getReferrer = function () {\n  return document.referrer || \"\";\n};\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 */\nconst dehyphenise = function (string) {\n  return string.replace(/(-)([a-z])/g, function (match, hyphen, letter) {\n    return letter.toUpperCase();\n  });\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 */\nconst parseAttributeName = function (attribute) {\n  const name = isString(attribute) ? attribute : attribute.name;\n  return dehyphenise(name.replace(/(data-)?o-ads-/, \"\"));\n};\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/* istanbul ignore next - cannot reliably test value of location */\nconst getLocation = function () {\n  return document.location.href || \"\";\n};\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 */\nconst getQueryString = function () {\n  return document.location.search.substring(1) || \"\";\n};\n\n/**\n * Get a query string parameter by name from a url\n * @param name\n * @param url\n * @returns {string | null}\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  if (!results) {\n    return null;\n  }\n  if (!results[2]) {\n    return \"\";\n  }\n  return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n};\n\n/**\n * returns a timestamp of the current date/time in the format YYYYMMDDHHMMSS\n * @returns {string}\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/**\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 */\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;\n\n  // Figure out which iframe DOM node we have the window for\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  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      if (slotName) {\n        return slotName;\n      }\n      node = node.parentNode;\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/**\n * Default configuration set in the constructor.\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};\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/**\n * @private\n * @function\n * fetchCanonicalURL Grabs the canonical URL from the page meta if it exists.\n */\nfunction fetchCanonicalURL() {\n  let canonical;\n  const canonicalTag = document.querySelector('link[rel=\"canonical\"]');\n  if (canonicalTag) {\n    canonical = canonicalTag.href;\n  }\n  return {\n    canonical: canonical\n  };\n}\n\n/**\n * Defines a store for configuration information and returns a getter/setter method for access.\n * @class\n * @constructor\n */\nfunction Config() {\n  this.store = {};\n}\nConfig.prototype.access = function (k, v) {\n  let result;\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  return result;\n};\nConfig.prototype.clear = function (key) {\n  if (key) {\n    delete this.store[key];\n  } else {\n    this.store = {};\n  }\n};\nConfig.prototype.init = function () {\n  this.store = utils.extend(true, {}, defaults, fetchCanonicalURL(), fetchDeclaritiveConfig());\n  return this.store;\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    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          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    return sizes;\n  },\n  responsiveSizes: function (name, value, sizes) {\n    const screenName = name.replace(/^sizes/, \"\").toLowerCase();\n    /* istanbul ignore else\t*/\n    if (!utils.isPlainObject(sizes)) {\n      sizes = {};\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    if (!utils.isPlainObject(sizes)) {\n      sizes = {};\n    }\n    sizes[screenName] = attributeParsers.formats(value, []);\n    return sizes;\n  },\n  lazyLoadThreshold: function (value) {\n    return value.split(\",\").map(Number);\n  },\n  /**\n   * Turn the value of data-o-ads-target into an object\n   * ```js\n   * // url-encoded input:\n   * \"pos=PartnerContent&format=horizontal\"\n   * // Legacy semicolon-delimited input:\n   * \"pos=PartnerContent;format=horizontal\"\n   *\n   * //output\n   * {pos:\"PartnerContent\",format:\"horizontal\"}\n   * ```\n   * @param {string} value\n   * @param {Record<string, string>} [targeting]\n   * @returns {Record<string, string>}\n   */\n  targeting: function (value, targeting = {}) {\n    if (!value || value.length === 0) return targeting;\n    try {\n      if (value.includes(\";\")) {\n        targeting = {\n          ...targeting,\n          ...utils.hash(value, \";\", \"=\")\n        };\n        throw new Error(`legacy targeting format detected: consider url-encoding '${value}' instead`);\n      }\n      const params = new URLSearchParams(value);\n      targeting = {\n        ...targeting,\n        ...Object.fromEntries(params)\n      };\n    } catch ({\n      message\n    }) {\n      console.warn(message);\n    }\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    return value;\n  },\n  collapseEmpty: function (value) {\n    const isUnknownAttribute = VALID_COLLAPSE_MODES.indexOf(value) === -1;\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    return value;\n  }\n};\nconst convertLazyLoadBooleanToObject = obj => {\n  if (obj.lazyLoad === true) {\n    obj.lazyLoad = {};\n  }\n};\nconst onChangeBreakpoint = event => {\n  const slot = event.detail.slot;\n  slot.screensize = event.detail.screensize;\n  if (slot.hasValidSize()) {\n    slot.uncollapse();\n  } else {\n    slot.collapse();\n    slot.clear();\n  }\n};\n\n/**\n * The Slot class.\n * @class\n * @constructor\n */\nfunction Slot(container, screensize, initLazyLoading) {\n  const renderEvent = \"slotRenderStart\";\n  const cfg = config$1();\n  let slotConfig = config$1(\"slots\") || {};\n\n  // store the container\n  this.container = container;\n  // the current responsive screensize\n\n  /* istanbul ignore else\t*/\n  if (screensize) {\n    this.screensize = screensize;\n  }\n\n  // init slot dom structure\n  this.outer = this.container.querySelector(\".o-ads__outer\");\n  if (!this.outer) {\n    this.outer = this.addContainer(container, {\n      class: \"o-ads__outer\"\n    });\n  }\n  this.inner = this.outer.firstChild;\n  if (!this.inner) {\n    this.inner = this.addContainer(this.outer, {\n      class: \"o-ads__inner\"\n    });\n  }\n\n  // make sure the slot has a name\n  this.setName();\n  slotConfig = slotConfig[this.name] || {};\n\n  // default configuration properties\n  this.server = \"gpt\";\n  this.defer = false;\n\n  // global slots configuration\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  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  if (typeof slotConfig.lazyLoad !== \"undefined\") {\n    this.lazyLoad = slotConfig.lazyLoad;\n  } else {\n    this.lazyLoad = config$1(\"lazyLoad\") || false;\n  }\n  const outerEl = container.querySelector(\".o-ads__outer\");\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  }\n\n  // extend with imperative configuration options\n  this.parseAttributeConfig();\n  /* istanbul ignore else\t*/\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  }\n\n  // Either retrieve the existing IntersectionObserver, or tell slots.js to create a new one.\n  this.lazyLoadObserver = initLazyLoading(this.lazyLoad);\n  this.initLazyLoad();\n  this.centerContainer();\n  this.labelContainer();\n  this.initResponsive();\n}\n\n/**\n * parse slot attribute config\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    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    }\n    // eslint-disable-next-line no-prototype-builtins\n    else if (this.hasOwnProperty(name)) {\n      this[name] = attributeParsers.base(value);\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/**\n *\tLoad a slot when it appears in the viewport\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);\n\n    //Master/Companion ads don't work with lazy loading, so if a master ad loads trigger\n    /* istanbul ignore else */\n    if (this.companion) {\n      utils.once(\"masterLoaded\", () => {\n        if (this.hasValidSize()) {\n          this.render();\n        }\n      }, this.container);\n    }\n  }\n  return this;\n};\nSlot.prototype.render = function () {\n  this.fire(\"slotCanRender\");\n  /* istanbul ignore else  */\n  if (this.lazyLoadObserver) {\n    this.lazyLoadObserver.unobserve(this.container);\n  }\n};\n\n/**\n *\tListen to responsive breakpoints and collapse slots\n * where the configured size is set to false\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    utils.on(\"breakpoint\", onChangeBreakpoint, this.container);\n  }\n  return this;\n};\n\n/**\n * Maximise the slot when size is 100x100\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/**\n *\tIf the slot doesn't have a name give it one\n */\nSlot.prototype.setName = function () {\n  this.name = this.container.getAttribute(\"data-o-ads-name\") || this.container.getAttribute(\"o-ads-name\");\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  return this;\n};\n\n/**\n * add the empty class to the slot\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/**\n * add the additional class to the slot\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/**\n * sets a classname of the format\n */\nSlot.prototype.setFormatLoaded = function (format) {\n  this.container.setAttribute(\"data-o-ads-loaded\", format);\n  return this;\n};\n\n/**\n * remove the empty class from the slot\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/**\n * call the ad server clear method on the slot if one exists\n */\nSlot.prototype.clear = function () {\n  /* istanbul ignore else  */\n  if (utils.isFunction(this[\"clearSlot\"])) {\n    this.clearSlot();\n  }\n  return this;\n};\n\n/**\n * call the ad server destroySlot method on the slot if one exists\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    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/**\n * call the ad server impression URL for an out of page slot if it has been configured correctly for delayed impressions\n */\nSlot.prototype.submitImpression = function () {\n  /* istanbul ignore else  */\n  if (utils.isFunction(this[\"submitGptImpression\"])) {\n    this.submitGptImpression();\n  }\n  return this;\n};\n\n/**\n *\tfire an event on the slot\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  if (typeof gpt.isEmpty === \"boolean\") {\n    details.isEmpty = gpt.isEmpty;\n  }\n  if (utils.isPlainObject(data)) {\n    utils.extend(details, data);\n  }\n  utils.broadcast(name, details, this.container);\n  return this;\n};\n\n/**\n *\tadd a div tag into the current slot container\n **/\nSlot.prototype.addContainer = function (node, attrs) {\n  let container = \"<div \";\n  /* istanbul ignore else  */\n  if (attrs) {\n    Object.keys(attrs).forEach(function (attr) {\n      const value = attrs[attr];\n      container += `${attr}=${value} `;\n    });\n  }\n  container += \"></div>\";\n  node.insertAdjacentHTML(\"beforeend\", container);\n  return node.lastChild;\n};\nSlot.prototype.hasValidSize = function (screensize) {\n  screensize = screensize || this.screensize;\n  if (screensize && utils.isPlainObject(this.sizes)) {\n    return this.sizes[screensize] !== false;\n  }\n  return true;\n};\n\n/**\n * Add a center class to the main container\n */\nSlot.prototype.centerContainer = function () {\n  if (this.center) {\n    this.container.classList.add(\"o-ads--center\");\n  }\n  return this;\n};\n\n/**\n * Add a label class to the main container\n */\nSlot.prototype.labelContainer = function () {\n  let className;\n  if (this.label === true || this.label === \"left\") {\n    className = \"label-left\";\n  } else if (this.label === \"right\") {\n    className = \"label-right\";\n  }\n  if (className && !config$1(\"displayLabelWithBorders\")) {\n    this.container.classList.add(`o-ads--${className}`);\n  }\n  return this;\n};\n\n/** @typedef {import(\"@financial-times/ads-slot\").Slot} Slot */\n\n/**\n * @param {Slot} slot\n * @returns {string}\n */\nfunction getSlotSizes(slot) {\n  if (!Array.isArray(slot.sizes)) return \"responsive slot\";\n  const sizes = [];\n  for (const size of slot.sizes) {\n    sizes.push(Array.isArray(size) ? size.join(\"×\") : size);\n  }\n  return sizes.join(\", \");\n}\n\n/**\n * @param {Slot} slot\n * @returns {string}\n */\nfunction getSlotTargeting({\n  targeting\n}) {\n  const params = [];\n  for (const [key, val] of Object.entries(targeting || {})) {\n    params.push(`${key}=${val}`);\n  }\n  return params.join(\", \");\n}\n\n/**\n * @param {Slot} slot\n * @returns {string}\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/**\n * Use a type predicate to distinguish between the `Slots` instance's properties\n * @type {(o: Slot | IntersectionObserver) => o is Slot }\n */\nconst isSlot = o => \"name\" in o;\n\n/**\n * @param {(Slot | IntersectionObserver)[]} slots\n */\nfunction debug$1(slots) {\n  const data = [];\n  for (const slot of slots) {\n    if (isSlot(slot)) {\n      var _slot$gpt, _slot$gpt2, _slot$gpt3;\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  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/**\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 */\nfunction Slots() {\n  //eslint-disable-line no-empty\n}\nfunction invokeMethodOnSlots(names, method, callback) {\n  let slots = [];\n  names = names || Object.keys(this);\n\n  /* istanbul ignore else\t*/\n  if (utils.isNonEmptyString(names)) {\n    slots.push(names);\n  } else if (utils.isArray(names)) {\n    slots = names;\n  }\n  slots.forEach(run.bind(null, this, method));\n  if (utils.isFunction(callback)) {\n    callback.call(this, slots);\n  }\n  return this;\n}\n\n/*\n * Either run a method or fire an event on the named slot.\n * @private\n * @param slots the slots object\n */\nfunction run(slots, action, name) {\n  const slot = slots[name];\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}\nfunction findFormatBySize(size) {\n  if (!size) {\n    return false;\n  }\n  const formats = config$1(\"formats\");\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      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 */\nSlots.prototype.collapse = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"collapse\");\n};\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 */\nSlots.prototype.uncollapse = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"uncollapse\");\n};\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 */\nSlots.prototype.refresh = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"refresh\");\n};\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 */\nSlots.prototype.clear = function (names) {\n  return invokeMethodOnSlots.call(this, names, \"clear\");\n};\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 */\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/**\n * Given a slot name will submit a delayed impression for the slot\n */\nSlots.prototype.submitImpression = function (name) {\n  return invokeMethodOnSlots.call(this, name, \"submitImpression\");\n};\n\n/**\n * Confirms a container in the page exists and creates a Slot object\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    if (container && container.id) {\n      container.setAttribute(\"data-o-ads-name\", container.id);\n      container.removeAttribute(\"id\");\n    }\n  }\n\n  // if not an element or we can't find it in the DOM exit\n  if (!utils.isElement(container)) {\n    utils.log.error(\"slot container must be an element!\", container);\n    return false;\n  }\n\n  // pass the method to retrieve or create the single IntersectionObserver instance\n  const slot = new Slot(container, screensize, this.initLazyLoading.bind(this));\n  /* istanbul ignore else\t*/\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  return slot;\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    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      setInterval(refresh, (parseFloat(data.time) || 1) * 1000);\n    }\n  }\n  return this;\n};\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 */\nSlots.prototype.initRendered = function () {\n  utils.on(\"slotRenderStart\", function (slots, event) {\n    const slot = slots[event.detail.name];\n    /* istanbul ignore else\t*/\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/*\n * if responsive configuration exists listen for breakpoint changes\n */\nSlots.prototype.initResponsive = function () {\n  const breakpoints = config$1(\"responsive\");\n  /* istanbul ignore else\t*/\n  if (utils.isObject(breakpoints)) {\n    screensize = utils.responsive(breakpoints, onBreakpointChange.bind(null, this));\n  }\n  return this;\n};\n\n/*\n * called when a responsive breakpoint is crossed though window resizing or orientation change.\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      /* 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      if (isCurrentlyResponsive && stillWantsResponsive) {\n        return false;\n      }\n      slot.screensize = screensize;\n      slot.fire(\"breakpoint\", {\n        screensize: screensize\n      });\n    }\n  });\n}\n\n/*\n * Initialise the postMessage API\n */\nSlots.prototype.initPostMessage = function () {\n  // Listen for messages coming from ads\n  window.addEventListener(\"message\", pmHandler.bind(null, this), false);\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    if (data.type && (/^oAds\\./.test(data.type) || /^touch/.test(data.type))) {\n      const type = data.type.replace(\"oAds.\", \"\");\n      // Make sure the message is coming from an identified ad slot\n      const slotName = utils.iframeToSlotName(event.source.window);\n      const slot = slots[slotName] || false;\n      if (!slot) {\n        utils.log.error(\"Message received from unidentified slot\");\n        return;\n      }\n      switch (type) {\n        // TODO: Remove adIframeLoaded once we can tag onto GPTs `slotRenderEnded` event\n        case \"adIframeLoaded\":\n          slot.fire(\"slotRenderEnded\");\n          break;\n        case \"slotClass\":\n          if (data.slotClass) {\n            slot.addClass(data.slotClass);\n          }\n          break;\n        // Received message to Collapse ad slot.\n        case \"collapse\":\n          slot.fire(\"slotCollapsed\");\n          slot.collapse();\n          break;\n        // Received message from heavy ads reporting\n        case \"heavyAdReporting\":\n          slot.fire(\"slotHeavyAdReporting\");\n          break;\n        default:\n          // Received touch events from ad slot iframe\n          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  }\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\nSlots.prototype.flushLazyLoading = function () {\n  this.lazyLoadingObservers = this.lazyLoadingObservers.filter(observer => {\n    return Boolean(!observer.root || document.contains(observer.root));\n  });\n};\nSlots.prototype.initLazyLoading = function (slotConfig) {\n  const lazyLoadingConfig = config$1(\"lazyLoad\") || slotConfig | {};\n  this.lazyLoadingObservers = this.lazyLoadingObservers || [];\n  this.flushLazyLoading();\n  // find any pre-existing observers\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    /* 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      if (slotName) {\n        invokeMethodOnSlots.call(this, slotName, \"render\");\n      }\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  /* istanbul ignore else\t*/\n  if (\"IntersectionObserver\" in window && !lazyLoadingObserver && Boolean(lazyLoadingConfig)) {\n    const options = {};\n\n    /* istanbul ignore else\t*/\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      if (lazyLoadingConfig.threshold) {\n        options.threshold = lazyLoadingConfig.threshold;\n      }\n      options.root = lazyLoadingConfig.root || null;\n    }\n    lazyLoadingObserver = new IntersectionObserver(onChange.bind(this), options);\n    this.lazyLoadingObservers.push(lazyLoadingObserver);\n  }\n  return lazyLoadingObserver;\n};\nSlots.prototype.forEach = function (fn) {\n  Object.keys(this).forEach(name => {\n    const slot = this[name];\n    /* istanbul ignore else\t*/\n    if (slot instanceof Slot) {\n      fn.call(this, slot);\n    }\n  });\n  return this;\n};\n\n/*\n * Initialise slots\n */\nSlots.prototype.init = function () {\n  this.initRefresh();\n  this.initRendered();\n  this.initResponsive();\n  this.initPostMessage();\n  this.initLazyLoading();\n};\nSlots.prototype.debug = function () {\n  debug$1(Object.values(this));\n};\nvar slots = new Slots();\n\nlet parameters = {};\nfunction Targeting() {} //eslint-disable-line no-empty-function\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  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  return parameters;\n};\nTargeting.prototype.add = function (obj) {\n  /* istanbul ignore else  */\n  if (utils.isPlainObject(obj)) {\n    utils.extend(parameters, obj);\n  }\n};\nTargeting.prototype.remove = function (key) {\n  /* istanbul ignore else */\n  if (parameters[key]) {\n    delete parameters[key];\n  }\n};\nTargeting.prototype.clear = function () {\n  parameters = {};\n};\nTargeting.prototype.getVersion = function () {\n  if (config$1(\"passOAdsVersion\")) {\n    return {\n      OADS_VERSION: utils.getVersion()\n    };\n  }\n};\n\n/**\n * If there is a query parameter called socialflow=xxx, we need to add it\n * as a tag\n */\nTargeting.prototype.socialFlow = function () {\n  const sf = utils.getQueryParamByName(\"socialflow\");\n  if (sf) {\n    return {\n      socialflow: sf\n    };\n  }\n};\nTargeting.prototype.getSocialReferrer = function () {\n  let codedValue;\n  const referrer = utils.getReferrer();\n  // TODO: add on.ft.com\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    if (refererRegex.test(referrer)) {\n      codedValue = lookup[url];\n    }\n  });\n  return codedValue && {\n    socref: codedValue\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\n  /* istanbul ignore else\t*/\n  if (keywords && keywords !== \"\") {\n    keywords = unescape(keywords).toLowerCase().replace(/[';^+]/g, \" \").replace(/\\s+/g, \" \").trim();\n  }\n  return {\n    kw: keywords\n  };\n};\nTargeting.prototype.timestamp = function () {\n  return {\n    ts: utils.getTimestamp()\n  };\n};\nTargeting.prototype.responsive = function () {\n  return config$1(\"responsive\") ? {\n    res: utils.responsive.getCurrent()\n  } : {};\n};\nTargeting.prototype.debug = function () {\n  const log = utils.log;\n  const parameters = this.get();\n  /* istanbul ignore else  */\n  if (Object.keys(parameters).length !== 0) {\n    log.start(\"Targeting\");\n    log.attributeTable(this.get());\n    log.end();\n  }\n};\nvar targeting = new Targeting();\n\nconst SEARCH_PARAMS = [\"q\", \"kw\"];\n\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 */\nfunction filterNestedParams(nestedParams, keysToStrip) {\n  if (!keysToStrip || keysToStrip.length < 1) {\n    return nestedParams;\n  }\n  const childParams = new URLSearchParams(nestedParams);\n  for (const key of keysToStrip) {\n    childParams.delete(key);\n  }\n  return childParams.toString();\n}\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 */\nfunction stripUrlParams({\n  href,\n  filters\n}) {\n  // @ts-ignore: URL absolutely accepts Location!\n  const url = new URL(href);\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      if (nestedParams) {\n        url.searchParams.set(param, filterNestedParams(nestedParams, filter));\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 */\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/*\n * initalise the googletag global namespace and add the google publish tags library to the page\n */\nfunction loadGPT() {\n  if (!window.googletag) {\n    // set up a place holder for the gpt code downloaded from google\n    window.googletag = {};\n\n    // 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    window.googletag.cmd = [];\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//#################################\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 */\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();\n\n  // eslint-disable-next-line no-prototype-builtins\n  if (gptConfig.hasOwnProperty(\"enableLazyLoad\")) {\n    enableLazyLoad(gptConfig.enableLazyLoad);\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/**\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 */\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/*\n * set the gpt rendering mode to either sync or async\n * default is async\n */\n\nfunction setRenderingMode(gptConfig) {\n  const rendering = gptConfig.rendering;\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/**\n * Adds page targeting to GPT ad calls\n * @name setPageTargeting\n * @memberof GPT\n * @lends GPT\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  return targetingData;\n}\n\n/**\n * Removes page targeting for a specified key from GPT ad calls\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  if (!key) {\n    utils.log.warn(\"Refusing to unset all keys - a key must be specified\");\n    return;\n  }\n  googletag.cmd.push(() => {\n    googletag.pubads().clearTargeting(key);\n  });\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 */\nfunction setPageCollapseEmpty() {\n  const mode = config$1(\"collapseEmpty\");\n  if (mode === \"before\") {\n    googletag.pubads().collapseEmptyDivs(true);\n  }\n  if (mode === \"after\") {\n    googletag.pubads().collapseEmptyDivs(false);\n  }\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 */\nfunction enableCompanions(gptConfig) {\n  if (gptConfig.companions) {\n    googletag.pubads().disableInitialLoad();\n    googletag.companionAds().setRefreshUnfilledSlots(true);\n  }\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 */\nfunction onReady(slotMethods, event) {\n  const slot = event.detail.slot;\n  /* istanbul ignore else  */\n  if (slot.server === \"gpt\") {\n    slot.gpt = {};\n\n    // extend the slot with gpt methods\n    utils.extend(slot, slotMethods);\n\n    // setup the gpt configuration the ad\n    googletag.cmd.push(() => {\n      slot.defineSlot().addServices().setCollapseEmpty().setTargeting().setURL();\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 */\nfunction onRender(event) {\n  const slot = event.detail.slot;\n  /* istanbul ignore else  */\n  if (utils.isFunction(slot.display)) {\n    slot.display();\n  }\n}\n\n/*\n * refresh is called when a slot requests the ad be flipped\n */\nfunction onRefresh(event) {\n  window.googletag.cmd.push(() => {\n    const targeting = event.detail.targeting;\n    if (utils.isPlainObject(targeting)) {\n      Object.keys(targeting).forEach(name => {\n        event.detail.slot.gpt.slot.setTargeting(name, targeting[name]);\n      });\n    }\n    googletag.pubads().refresh([event.detail.slot.gpt.slot]);\n  });\n  return this;\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/*\n * function passed to the gpt library that is run when an ad completes rendering\n */\nfunction onRenderEnded(event) {\n  var _slotTargeting$pos;\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  data.pos = Array.isArray(slotTargeting === null || slotTargeting === void 0 ? void 0 : slotTargeting.pos) && (_slotTargeting$pos = slotTargeting.pos) !== null && _slotTargeting$pos !== void 0 && _slotTargeting$pos.length ? slotTargeting.pos.join() : \"\";\n  const isPromotedContent = data.pos.includes(\"native\");\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  if (iFrameEl) {\n    if (!isPromotedContent) {\n      // allow screenreader to access if it is promoted content\n      iFrameEl.setAttribute(\"tabindex\", \"-1\");\n      iFrameEl.setAttribute(\"aria-hidden\", \"true\");\n      iFrameEl.setAttribute(\"role\", \"presentation\");\n    }\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  utils.broadcast(\"slotRenderStart\", data);\n}\n\n/*\n//################\n// Slot methods ##\n//################\n* Set of methods extended on to the slot constructor for GPT served slots\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      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        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   * 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   *\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   * 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      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      this.gpt.unitName = unitName;\n    });\n    return this;\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      if (gpt.companions && this.companion !== false) {\n        gptSlot.addService(googletag.companionAds());\n      }\n    });\n    return this;\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      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      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    if (this.outOfPage && this.gpt.iframe) {\n      const impressionURL = getImpressionURL(this.gpt.iframe);\n      /* istanbul ignore next  */\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   * 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   * 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      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//####################\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 */\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}\nfunction getCorrelator() {\n  if (window.googletag && window.googletag.pubads) {\n    return googletag.pubads().getCorrelator();\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}\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}\n//https://developers.google.com/doubleclick-gpt/common_implementation_mistakes#scenario-2:-checking-the-googletag-object-to-know-whether-gpt-is-ready\nfunction hasGPTLoaded() {\n  if (window.googletag && window.googletag.apiReady) {\n    return true;\n  } else {\n    return false;\n  }\n}\nfunction debug() {\n  const log = utils.log;\n  const conf = config$1(\"gpt\");\n  if (!conf) {\n    return;\n  }\n  log.start(\"gpt\");\n  log.attributeTable(conf);\n  log.end();\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 */\nfunction Ads() {\n  addDOMEventListener();\n  if (window && !window.oAds) {\n    window.oAds = this;\n  }\n}\nconfig$1.init = init$1;\nconfig$1.clear = clear;\n\n// bung all our modules on the protoype\nAds.prototype.config = config$1;\nAds.prototype.slots = slots;\nAds.prototype.gpt = gpt;\nAds.prototype.targeting = targeting;\nAds.prototype.utils = utils;\n\n/**\n * Initialises the ads library and all sub modules\n * @param options {object} a JSON object containing configuration for the current page\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  if (options.disableConsentCookie) {\n    this.consents = {\n      behavioral: true\n    };\n  } else {\n    this.consents = getConsents();\n  }\n  if (this.consents.behavioral) {\n    this.utils.broadcast(\"consentBehavioral\");\n  }\n  if (this.consents.programmatic) {\n    this.utils.broadcast(\"consentProgrammatic\");\n  }\n  this.utils.broadcast(\"initialising\");\n  this.targeting.add(this.config().targeting);\n  return Promise.resolve(this.initLibrary());\n};\n\n/**\n * Update page level targeting data in o-ads and GPT\n */\nAds.prototype.updateTargeting = function (data) {\n  this.targeting.add(data);\n  this.gpt.updatePageTargeting(this.targeting.get());\n};\nAds.prototype.initLibrary = function () {\n  this.slots.init();\n  if (this.consents.programmatic) {\n    this.config({\n      nonPersonalized: false\n    });\n    this.targeting.add({\n      cc: \"y\"\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};\nAds.prototype.debug = function () {\n  let remove = true;\n  if (localStorage.getItem(\"oAds\")) {\n    remove = false;\n  } else {\n    localStorage.setItem(\"oAds\", true);\n  }\n  this.gpt.debug();\n  this.slots.debug();\n  this.targeting.debug();\n  if (remove) {\n    localStorage.removeItem(\"oAds\");\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};\nAds.prototype.getVersion = function () {\n  return this.utils.getVersion();\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};\nAds.prototype.initAll = initAll;\nfunction getConsents() {\n  // derive consent options from ft consent cookie\n  const re = /FTConsent=([^;]+)/;\n  const match = document.cookie.match(re);\n  if (!match) {\n    // cookie stasis or no consent cookie found\n    return {\n      behavioral: false,\n      programmatic: false\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}\nfunction addDOMEventListener() {\n  document.addEventListener(\"o.DOMContentLoaded\", initAll);\n}\nfunction removeDOMEventListener() {\n  document.removeEventListener(\"o.DOMContentLoaded\", initAll);\n}\nconst ads = new Ads();\n\nexport { Ads, ads as default };\n"],"sourceRoot":""}