@thg-agentic/hyper-personalisation-web 3.24.0 → 3.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- (()=>{async function Re(n,o,a){let l=m=>Array.from(new Uint8Array(m),v=>v.toString(16).padStart(2,"0")).join(""),u=new TextEncoder,x=n.maxnumber??1e6;for(let m=0;m<=x;m+=256){let v=[];for(let T=m;T<m+256&&T<=x;T++)v.push(crypto.subtle.digest("SHA-256",u.encode(n.salt+T)));let h=(await Promise.all(v)).findIndex(T=>l(T)===n.challenge);if(h>=0)return m+h;if(o&&await o(),a?.aborted)return null}return null}var kt=()=>globalThis.scheduler?.postTask?.(()=>{},{priority:"user-visible"})??new Promise(n=>setTimeout(n,0)),De=(n,o)=>Re(n,kt,o);function At(n,o){let a=`onmessage=async(e)=>postMessage(await(${Re})(e.data))`,l=URL.createObjectURL(new Blob([a],{type:"text/javascript"}));return new Promise((u,x)=>{let m;try{m=new Worker(l)}catch(h){URL.revokeObjectURL(l),x(h);return}let v=(h,T)=>{m.terminate(),URL.revokeObjectURL(l),h(T)};o.addEventListener("abort",()=>v(u,null),{once:!0}),m.onmessage=h=>v(u,h.data),m.onerror=h=>{h.preventDefault?.(),v(x,h)},m.postMessage({challenge:n.challenge,salt:n.salt,maxnumber:n.maxnumber})})}var St=n=>n&&n.algorithm==="SHA-256"&&typeof n.challenge=="string"&&typeof n.salt=="string"&&typeof n.signature=="string";async function Ue(n){if(!St(n)||typeof crypto?.subtle?.digest!="function")return null;let o=Date.now(),a=new AbortController,l,u=new Promise(v=>{l=setTimeout(()=>v(null),2e4)}),x=typeof Worker=="function"&&typeof Blob=="function"?At(n,a.signal).catch(()=>De(n,a.signal)):De(n,a.signal),m=await Promise.race([x,u]);return clearTimeout(l),a.abort(),typeof m!="number"?null:btoa(JSON.stringify({algorithm:n.algorithm,challenge:n.challenge,number:m,salt:n.salt,signature:n.signature,took:Date.now()-o}))}function B(n){if(typeof n!="string")return null;try{let o=new URL(n);return o.protocol==="https:"?o.href:null}catch{return null}}function G(n){if(typeof n!="string")return null;try{let o=new URL(n);return o.protocol==="https:"||o.protocol==="http:"&&o.hostname==="localhost"?o.href:null}catch{return null}}function pe(n,o,a,l){if(typeof o=="string"){n.append(a.createTextNode(o));return}if(l>6||o===null)return;if(Array.isArray(o)){for(let v of o)pe(n,v,a,l+1);return}if(typeof o!="object")return;let u="b"in o?"b":"i"in o?"i":"a"in o?"a":null;if(!u)return;let x=u==="a"?B(o.href):null,m=u==="a"&&!x?n:a.createElement(u);x&&(m.setAttribute("href",x),m.setAttribute("rel","noopener")),pe(m,o[u],a,l+1),m!==n&&n.append(m)}function We(n,o=document){let a=o.createDocumentFragment();return pe(a,n,o,0),a}var Et=n=>n!==null&&typeof n=="object"&&!Array.isArray(n);function V(n,o,a){if(typeof a=="string"&&a)return a;let l=Et(n?.next?.answers)?n.next.answers:{};for(let[u,x]of Object.entries(l)){let m=u.indexOf("="),v=o[u.slice(0,m)];if(m>0&&v?.includes(u.slice(m+1)))return x}return typeof n?.next?.default=="string"?n.next.default:null}var ue={AT:"43",AU:"61",BE:"32",CA:"1",CH:"41",DE:"49",DK:"45",ES:"34",FI:"358",FR:"33",GB:"44",IE:"353",IT:"39",NL:"31",NO:"47",NZ:"64",PL:"48",PT:"351",SE:"46",US:"1"};function Fe(n,o){let a=String(n??"").replace(/[\s.()-]/g,"");a.startsWith("00")&&(a=`+${a.slice(2)}`);let l=ue[String(o??"").toUpperCase()];return!a.startsWith("+")&&l&&(a=`+${l}${a.replace(/^0/,"")}`),/^\+[1-9]\d{7,14}$/.test(a)?a:null}var Ye=n=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(n);function fe(n,o,a,l,u){let x=n("select","i");x.setAttribute("aria-label",o);for(let[m,v]of[["",a],...l]){let h=n("option","",v);h.value=m,h.selected=m===u,x.append(h)}return x}var he={system:"system-ui,sans-serif","neo-grotesque":'Inter,Roboto,"Helvetica Neue",Arial,sans-serif',humanist:'Seravek,"Gill Sans Nova",Ubuntu,Calibri,sans-serif',"geometric-humanist":"Avenir,Montserrat,Corbel,sans-serif","rounded-sans":'ui-rounded,Quicksand,Comfortaa,"Arial Rounded MT Bold",sans-serif',industrial:'Bahnschrift,"DIN Alternate","Franklin Gothic Medium",sans-serif',transitional:'Charter,"Sitka Text",Cambria,serif',"old-style":'"Iowan Old Style","Palatino Linotype",P052,serif',didone:'Didot,"Bodoni MT","Noto Serif Display",serif',"slab-serif":'Rockwell,"Roboto Slab","DejaVu Serif",serif'},me="cubic-bezier(.16,1,.3,1)",be=`
1
+ (()=>{async function Re(i,o,a){let l=m=>Array.from(new Uint8Array(m),v=>v.toString(16).padStart(2,"0")).join(""),f=new TextEncoder,x=i.maxnumber??1e6;for(let m=0;m<=x;m+=256){let v=[];for(let T=m;T<m+256&&T<=x;T++)v.push(crypto.subtle.digest("SHA-256",f.encode(i.salt+T)));let h=(await Promise.all(v)).findIndex(T=>l(T)===i.challenge);if(h>=0)return m+h;if(o&&await o(),a?.aborted)return null}return null}var kt=()=>globalThis.scheduler?.postTask?.(()=>{},{priority:"user-visible"})??new Promise(i=>setTimeout(i,0)),De=(i,o)=>Re(i,kt,o);function At(i,o){let a=`onmessage=async(e)=>postMessage(await(${Re})(e.data))`,l=URL.createObjectURL(new Blob([a],{type:"text/javascript"}));return new Promise((f,x)=>{let m;try{m=new Worker(l)}catch(h){URL.revokeObjectURL(l),x(h);return}let v=(h,T)=>{m.terminate(),URL.revokeObjectURL(l),h(T)};o.addEventListener("abort",()=>v(f,null),{once:!0}),m.onmessage=h=>v(f,h.data),m.onerror=h=>{h.preventDefault?.(),v(x,h)},m.postMessage({challenge:i.challenge,salt:i.salt,maxnumber:i.maxnumber})})}var St=i=>i&&i.algorithm==="SHA-256"&&typeof i.challenge=="string"&&typeof i.salt=="string"&&typeof i.signature=="string";async function Ue(i){if(!St(i)||typeof crypto?.subtle?.digest!="function")return null;let o=Date.now(),a=new AbortController,l,f=new Promise(v=>{l=setTimeout(()=>v(null),2e4)}),x=typeof Worker=="function"&&typeof Blob=="function"?At(i,a.signal).catch(()=>De(i,a.signal)):De(i,a.signal),m=await Promise.race([x,f]);return clearTimeout(l),a.abort(),typeof m!="number"?null:btoa(JSON.stringify({algorithm:i.algorithm,challenge:i.challenge,number:m,salt:i.salt,signature:i.signature,took:Date.now()-o}))}function B(i){if(typeof i!="string")return null;try{let o=new URL(i);return o.protocol==="https:"?o.href:null}catch{return null}}function G(i){if(typeof i!="string")return null;try{let o=new URL(i);return o.protocol==="https:"||o.protocol==="http:"&&o.hostname==="localhost"?o.href:null}catch{return null}}function pe(i,o,a,l){if(typeof o=="string"){i.append(a.createTextNode(o));return}if(l>6||o===null)return;if(Array.isArray(o)){for(let v of o)pe(i,v,a,l+1);return}if(typeof o!="object")return;let f="b"in o?"b":"i"in o?"i":"a"in o?"a":null;if(!f)return;let x=f==="a"?B(o.href):null,m=f==="a"&&!x?i:a.createElement(f);x&&(m.setAttribute("href",x),m.setAttribute("rel","noopener")),pe(m,o[f],a,l+1),m!==i&&i.append(m)}function We(i,o=document){let a=o.createDocumentFragment();return pe(a,i,o,0),a}var Et=i=>i!==null&&typeof i=="object"&&!Array.isArray(i);function V(i,o,a){if(typeof a=="string"&&a)return a;let l=Et(i?.next?.answers)?i.next.answers:{};for(let[f,x]of Object.entries(l)){let m=f.indexOf("="),v=o[f.slice(0,m)];if(m>0&&v?.includes(f.slice(m+1)))return x}return typeof i?.next?.default=="string"?i.next.default:null}var ue={AT:"43",AU:"61",BE:"32",CA:"1",CH:"41",DE:"49",DK:"45",ES:"34",FI:"358",FR:"33",GB:"44",IE:"353",IT:"39",NL:"31",NO:"47",NZ:"64",PL:"48",PT:"351",SE:"46",US:"1"};function Fe(i,o){let a=String(i??"").replace(/[\s.()-]/g,"");a.startsWith("00")&&(a=`+${a.slice(2)}`);let l=ue[String(o??"").toUpperCase()];return!a.startsWith("+")&&l&&(a=`+${l}${a.replace(/^0/,"")}`),/^\+[1-9]\d{7,14}$/.test(a)?a:null}var Ye=i=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(i);function fe(i,o,a,l,f){let x=i("select","i");x.setAttribute("aria-label",o);for(let[m,v]of[["",a],...l]){let h=i("option","",v);h.value=m,h.selected=m===f,x.append(h)}return x}var he={system:"system-ui,sans-serif","neo-grotesque":'Inter,Roboto,"Helvetica Neue",Arial,sans-serif',humanist:'Seravek,"Gill Sans Nova",Ubuntu,Calibri,sans-serif',"geometric-humanist":"Avenir,Montserrat,Corbel,sans-serif","rounded-sans":'ui-rounded,Quicksand,Comfortaa,"Arial Rounded MT Bold",sans-serif',industrial:'Bahnschrift,"DIN Alternate","Franklin Gothic Medium",sans-serif',transitional:'Charter,"Sitka Text",Cambria,serif',"old-style":'"Iowan Old Style","Palatino Linotype",P052,serif',didone:'Didot,"Bodoni MT","Noto Serif Display",serif',"slab-serif":'Rockwell,"Roboto Slab","DejaVu Serif",serif'},me="cubic-bezier(.16,1,.3,1)",be=`
2
2
  :host{all:initial}
3
3
  :host([preview]){display:block;position:relative;width:100%;height:100%;overflow:hidden;contain:layout paint}
4
4
  .s{--a:var(--hp-accent,#111);--b:var(--hp-bg,#fff);--t:var(--hp-text,#111);--r:var(--hp-radius,16px);--oa:var(--hp-on-accent,#fff);--ot:var(--hp-on-accent-text,var(--oa));--fl:var(--hp-field,color-mix(in srgb,var(--t) 5%,var(--b)));--ft:var(--hp-field-text,var(--t));--mu:color-mix(in srgb,var(--t) 74%,var(--b));--ln:color-mix(in srgb,var(--t) 18%,var(--b));--br:min(12px,var(--r));--ir:min(var(--r),8px);font:16px/1.5 var(--hp-font,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif);color:var(--t);-webkit-font-smoothing:antialiased;box-sizing:border-box;margin:0;padding:0;border:0;background:none;max-width:none;max-height:none;overflow:visible}
@@ -115,7 +115,7 @@ hr{width:100%;margin:4px 0;border:0;border-top:1px solid var(--ln)}
115
115
  .hd{display:none}
116
116
  .uc h2{text-transform:uppercase;font-weight:800;letter-spacing:-.01em;line-height:1.02}
117
117
  .uc .btn:not(.no),.uc .tb{text-transform:uppercase;letter-spacing:.06em}
118
- .sheet,.bar,.teaser{position:fixed;inset:auto;z-index:2147483646;display:flex;flex-direction:column}
118
+ .sheet,.bar,.teaser{position:fixed;inset:auto;height:auto;z-index:2147483646;display:flex;flex-direction:column}
119
119
  .sheet{right:24px;bottom:24px;width:min(400px,calc(100% - 32px));max-height:calc(100% - 48px)}
120
120
  .sheet.p-bottom-left{right:auto;left:24px}
121
121
  .sheet.p-bottom{right:auto;left:50%;translate:-50% 0}
@@ -179,4 +179,4 @@ hr{width:100%;margin:4px 0;border:0;border-top:1px solid var(--ln)}
179
179
  @keyframes hp-down{from{transform:translateY(-100%)}}
180
180
  @keyframes hp-out{to{opacity:0;transform:translateY(12px) scale(.98)}}
181
181
  @media (prefers-reduced-motion:reduce){.s .w,.s .ov,.f>*{animation:hp-fade .15s ease both!important}.btn{transition:none}}
182
- `;var $t=/^#(?:[0-9a-f]{3}){1,2}$/i,He=["popup","fullscreen"],_t=["ok","verify","already"],zt=["stack","split","overlay","image-only"],Be={bar:["bottom","top"],sheet:["bottom-right","bottom-left","bottom"],teaser:["bottom-left","bottom-right","left","right"]},Tt=["xs","sm","md","lg","xl","display"],Ge={xs:4,sm:8,md:16,lg:28,xl:44},Ve={sm:380,md:480,lg:880},Ct=["left","center","right"],Xe={secondary:" b2",link:" no"},Lt=220,Mt=["verify","already","held","fallback","success"],Ot=[500,1500],It=600,Pt=1800,$={email:"Enter a valid email address.",phone:"Enter a valid mobile number.",intl:"Enter a valid mobile number, starting with + and its country code.",consent:"Tick the box to sign up.",failed:"Something went wrong. Please try again.",busy:"Too many tries. Please wait a moment and try again.",spin:"Sign up first to spin.",yours:"Your code",held:"You\u2019re already on the list",resent:"We\u2019ve sent your code to your inbox again.",inbox:"Your code is in the email we sent when you first signed up.",shop:"Continue shopping",closeOffer:"Close offer",code:"We\u2019ll email your code to you.",claimed:"This email address has already claimed its code.",copied:"Copied",thanks:"Thanks, you\u2019re signed up",unavailable:"Not available right now.",won:"You won"},P=n=>n!==null&&typeof n=="object"&&!Array.isArray(n),F=(n,o,a)=>n.includes(o)?o:a,I=(n,o,a)=>Number.isFinite(n)?Math.min(Math.max(n,o),a):null,ge=n=>n.type==="date"||n.type==="number",xe=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0;function Ze(n){let o=P(n.layout)?n.layout:{},a=P(o.media)?o.media:null,l=F(zt,o.template,"stack"),u=a?.side==="right"?"right":"left";return!a&&P(o.image)&&o.image.side!=="none"&&(a=o.image,o.image.side!=="top"&&(l="split",u=o.image.side==="right"?"right":"left")),(!a||!G(a.asset))&&(a=null,l="stack"),{template:l,media:a,side:u,scrim:I(o.scrim,0,.9)??.45,padding:F(["none","sm","md","lg"],o.padding,"md")}}var Je=(n,o)=>F(["sm","md","lg","full"],n.size,null)??(o.template==="split"||o.template==="overlay"?"lg":"md"),Qe=(n,o,a=1)=>{if(n==="fullscreen"||o==="full")return"100vw";let l=n==="teaser"?220:n==="sheet"?400:Ve[o]??Ve.md;return`(max-width: 639px) 100vw, ${Math.round(l*a)}px`},et=(n,o,a)=>{if(!a||!Array.isArray(n.widths)||!o.endsWith(".webp"))return null;let l=n.widths.filter(u=>Number.isInteger(u)&&u>0&&u<a).sort((u,x)=>u-x);return l.length===0?null:[...l.map(u=>`${o.slice(0,-5)}-${u}w.webp ${u}w`),`${o} ${a}w`].join(",")},tt=(n,o)=>n.format==="inline"?"inline":o.format&&o.format!=="inline"?o.format:n.format,ve=n=>n.kind==="video"||n.t==="video",we={webm:"video/webm",mp4:"video/mp4",m4v:"video/mp4",mov:"video/quicktime",ogv:"video/ogg"},ke=n=>we[n.split(/[?#]/)[0].split(".").pop().toLowerCase()],Nt=(n,o)=>[...new Set([o,...Array.isArray(n.sources)?n.sources.map(G):[]])].filter(Boolean).sort((a,l)=>(ke(l)===we.webm)-(ke(a)===we.webm));function Ae(n,o,a,l=new Set){let u=o.steps.find(k=>k.id===a);if(!u)return Promise.resolve();let x=tt(n,o),m=Ze(u),v=x==="teaser"&&u===o.steps[0],h=x==="teaser"&&!v?"popup":x,T=Je(o.theme,m),S=v?[]:u.blocks.filter(k=>P(k)&&(k.t==="image"||k.t==="video")).map(k=>[k,1]);return m.media&&!(v&&m.template!=="image-only")&&S.push([m.media,m.template==="split"?.46:1]),Promise.all(S.map(([k,Z])=>{let C=G(ve(k)?k.poster:k.asset);if(!C)return null;let L=document.createElement("img"),U=!ve(k)&&et(k,C,I(k.width,1,8192));U&&(L.sizes=Qe(h,T,Z),L.srcset=U);let y=`${L.sizes} ${U||C}`;return l.has(y)?null:(l.add(y),L.src=C,L.decode?.().catch(()=>{}))}))}var jt=0,ye=n=>`hp-${n}-${++jt}`;function f(n,o,a){let l=document.createElement(n);return o&&(l.className=o),a!==void 0&&l.append(We(a)),l}var nt=n=>{let o=n.length===4?[...n.slice(1)].map(a=>a+a).join(""):n.slice(1);return[0,2,4].map(a=>Number.parseInt(o.slice(a,a+2),16))},K=n=>{let[o,a,l]=nt(n).map(u=>{let x=u/255;return x<=.04045?x/12.92:((x+.055)/1.055)**2.4});return .2126*o+.7152*a+.0722*l},Ke=(n,o=4.5)=>{let a=K(n)+.05,l=1.05/a;return l>=o?"#fff":a/(K("#111")+.05)>l?"#111":"#fff"};function qt(n,o){let a=(S,k)=>k&&n.style.setProperty(S,k),l=S=>$t.test(S??"")?S:null;a("--hp-accent",l(o.accent)),a("--hp-bg",l(o.background)),a("--hp-text",l(o.text));let u=I(o.radius,0,48);u!==null&&a("--hp-radius",`${u}px`),a("--hp-font",o.font==="site"?n.ownerDocument.defaultView.getComputedStyle(n.parentElement??n.ownerDocument.body).fontFamily:Object.hasOwn(he,o.font)?he[o.font]:null),l(o.accent)&&(a("--hp-on-accent",Ke(o.accent,3)),a("--hp-on-accent-text",Ke(o.accent))),l(o.background)&&K(o.background)<.18&&(a("--hp-field","#fff"),a("--hp-field-text","#111"));let x=P(o.overlay)?o.overlay:{},m=[l(o.text),l(o.background)].filter(Boolean).sort((S,k)=>K(S)-K(k))[0],[v,h,T]=nt(l(x.colour)??m??"#0b0b0f");a("--hp-ov",`rgb(${v} ${h} ${T} / ${I(x.opacity,0,1)??.6})`)}function Dt(n){try{let o=new CSSStyleSheet;o.replaceSync(be),n.adoptedStyleSheets=[o]}catch{let o=document.createElement("style");o.textContent=be,n.append(o)}}function it(n){let{form:o,creative:a,decision:l,access:u,client:x,api:m,counters:v}=n,h=n.preview??null,T=e=>{let t=e.blocks.find(r=>r?.t==="email"||r?.t==="phone");return t?.t==="phone"||!t&&!o.consent_text?o.sms_consent_text:o.consent_text},S=tt(o,a),k=a.theme,Z=F(Be[S]??[],k.position,Be[S]?.[0]),C=document.createElement("hp-onsite");h&&C.setAttribute("preview",""),qt(C,k);let L=C.attachShadow({mode:"open"});Dt(L);let U=S!=="inline"&&!h,y=f(U?"dialog":S==="inline"?"section":"div"),Se=f("div","ov"),E=f("div","w"),W=f("div","m");h&&(W.dataset.hpMedia="");let Ee=()=>{let e=f("form","f");return e.noValidate=!0,e.addEventListener("submit",gt),e.addEventListener("input",()=>{M.textContent&&A.getAttribute("aria-busy")!=="true"&&N(null)}),e},A=Ee(),M=f("p","e");M.id=ye("err"),M.setAttribute("aria-live","assertive");let ie=f("div","hd");ie.setAttribute("aria-hidden","true"),E.append(ie,W,A),y.append(Se,E);let Y=S!=="inline"&&f("button","x");Y&&(Y.type="button",Y.addEventListener("click",()=>j("close")),E.append(Y),Se.addEventListener("click",()=>j("close"))),L.append(y);let i={step:null,mode:S,size:"md",modal:!1,mobile:h?.device==="mobile",answers:{},sent:new Set,receipt:null,claim:n.coupon?{code:n.coupon}:h?{code:"WELCOME15"}:null,claiming:null,touched:!1,toWarm:new Set,warmed:n.warmed??new Set,warming:!1,owed:!1,submitted:!1,pow:null,wheel:null,timers:[],codes:[],videos:[],closed:!1},J=o.locale||document.documentElement.lang,ot=o.questions.some(ge)&&n.loadAnswers().catch(()=>null),$e=new WeakMap,_e=()=>{let e=P(k.button)?k.button:{};y.className=`s ${i.mode}${Z?` p-${Z}`:""} b-${F(["pill","rounded","square"],e.shape,"rounded")}${i.mobile?" mob":""}${h?" pv":""}${e.style==="outline"?" bo":""}${k.caps===!0?" uc":""}`},X=h?null:globalThis.matchMedia?.("(max-width: 639px)"),ze=()=>{i.mobile=X?.matches===!0,ae(),_e()};X&&(i.mobile=X.matches===!0,X.addEventListener?.("change",ze));let Q=(e,t)=>{h||!l.decision_id||!u.analytics()||x.slotEngaged({decision_id:l.decision_id,slot:l.slot,arm:l.arm??null,engagement:e,step:t??i.step?.id??null})},N=(e,t)=>{M.className="e",M.textContent=e??"";for(let s of A.querySelectorAll("[aria-invalid]"))s.removeAttribute("aria-invalid");let r=t?.closest("label,fieldset");r&&A.contains(r)?r.after(M):A.append(M),t&&(t.setAttribute("aria-invalid","true"),t.setAttribute("aria-describedby",M.id),t.focus(),t.scrollIntoView?.({block:"nearest"}))},H=e=>{A.setAttribute("aria-busy",String(e));for(let t of A.querySelectorAll("button"))t.disabled=e},Te=()=>h?Promise.resolve(null):(i.pow??(i.pow=m.challenge().then(e=>e.status===200?Ue(e.body):null).catch(()=>null)),i.pow),oe=()=>{for(let e of i.videos)try{document.hidden||xe()?e.pause():e.play()?.catch?.(()=>{})}catch{}};document.addEventListener("visibilitychange",oe);function Ce(e,t,r,s){let c=G(e.asset);if(!c)return null;let p=typeof e.alt=="string"?e.alt:"",d;if(ve(e)){d=f("video",t),d.muted=d.defaultMuted=d.loop=d.playsInline=!0;let w=G(e.poster);w&&(d.poster=w),p?d.setAttribute("aria-label",p):d.setAttribute("aria-hidden","true"),d.autoplay=!xe()&&!h,d.preload=d.autoplay?"auto":w?"none":"metadata";let _=Nt(e,c);if(_.length>1)for(let z of _){let O=f("source");O.src=z;let q=ke(z);q&&(O.type=q),d.append(O)}else d.src=c;i.videos.push(d)}else{d=f("img",t),d.alt=p,d.decoding="async",d.loading=r?"eager":"lazy",r&&(d.fetchPriority="high");let w=et(e,c,I(e.width,1,8192));w&&(d.sizes=Qe(i.mode,i.size,s),d.srcset=w),d.src=c}let b=I(e.width,1,8192),g=I(e.height,1,8192);return b&&g&&(d.width=b,d.height=g),P(e.focal)&&(d.style.objectPosition=`${I(e.focal.x,0,100)??50}% ${I(e.focal.y,0,100)??50}%`),d}function Le(e,t){let r=f("label","l");r.append(f("span","lt",e.label??(t==="email"?"Email":"Mobile number")));let s=f("input","i");if(s.type=t,s.name=t==="email"?"email":"phone",s.autocomplete=s.inputMode=t,s.required=!0,typeof e.placeholder=="string"&&(s.placeholder=e.placeholder),s.setAttribute("aria-describedby",M.id),s.addEventListener("focus",Te,{once:!0}),t!=="tel")return r.append(s),r;s.id=`${M.id}-p`,r.htmlFor=s.id;let c=fe(f,"Country code","+",Object.entries(ue).map(([d,b])=>[d,`${d} +${b}`]),(e.country||/-(\w\w)$/.exec(J)?.[1]||"").toUpperCase());c.classList.add("cc"),c.name="hp_cc";let p=f("span","ph");return p.append(c,s),r.append(p),r}function rt(e){let t=o.questions.find(b=>b.key===e.question);if(!t||!ge(t)&&!Array.isArray(t.options))return null;let r=f("fieldset");r.dataset.question=t.key,r.append(f("legend","",t.label??""));let s=i.answers[t.key]??[];if(ge(t))return ot.then(b=>{if(!b)return r.append(f("p","sm",$.unavailable));b.answerFields(r,t,f,s[0],J),$e.set(r,()=>b.answerOf(r,t,void 0,J))}),r;let c=t.type==="many",p=F(["list","dropdown"],e.display,"buttons"),d=t.options.filter(b=>P(b)&&typeof b.value=="string");if(p==="dropdown"&&!c)return r.append(fe(f,t.label??t.key,"\u2014",d.map(b=>[b.value,b.label??b.value]),s[0])),r;p!=="buttons"&&(r.className="ls");for(let b of d){let g=f("input");g.value=b.value,g.checked=s.includes(b.value),g.type=c?"checkbox":"radio",g.name=`q_${t.key}`;let w=f("label",p==="buttons"?"ch":"c");w.append(g,f("span","",b.label??b.value)),r.append(w)}return r}function re(){for(let e of i.codes){if(e.replaceChildren(),!i.claim)continue;if(!i.claim.code){e.append(f("p","",i.claim.held?$.claimed:$.code));continue}i.claim.prize?.label&&e.append(f("p","",i.claim.prize.label));let t=f("output");t.textContent=i.claim.code;let r=f("button","btn cp");r.type="button",r.textContent="Copy code",r.addEventListener("click",()=>{navigator.clipboard?.writeText(i.claim.code).then(()=>{r.textContent=$.copied}).catch(()=>{})}),e.append(t,r)}}function st(e){if(i.claim&&!i.claim.code)return null;let t=f("p","tm");t.setAttribute("role","timer");let r=Date.now()+Math.max(0,Number(e.minutes)||0)*6e4,s=()=>{let p=Math.max(0,Math.round((r-Date.now())/1e3));t.textContent=`${String(Math.floor(p/60)).padStart(2,"0")}:${String(p%60).padStart(2,"0")}`,p===0&&clearInterval(c)},c=setInterval(s,1e3);return i.timers.push(c),s(),t}function se(e,t){return e.href=t,e.rel="noopener",e.addEventListener("click",r=>{h?r.preventDefault():Q("click")}),e}function at(e){let t=e.label??"Continue";if(e.action==="link"){let s=B(e.href);return s?se(f("a",`btn${Xe[e.variant]??""}`,t),s):null}let r=f("button",`btn${Xe[e.variant]??""}`,t);return r.type=e.action==="submit"?"submit":"button",r.type==="button"?r.addEventListener("click",()=>te(e)):r.dataset.submit="",r}let Me=(e,t,r)=>(e.classList.add(`x-${F(Tt,t.size,r)}`),Ct.includes(t.align)&&e.classList.add(`a-${t.align}`),e);function Oe(e){let t=Ce(e,"bi",i.step===a.steps[0]);if(!t)return null;t.style.objectFit=e.fit==="contain"?"contain":"cover";let r=I(e.radius,0,48);r!==null&&(t.style.borderRadius=`${r}px`);let s=I(e.max_height,40,800);if(s!==null&&(t.style.maxHeight=`${s}px`),!t.width&&e.fit!=="contain"&&(t.style.aspectRatio="16 / 9"),e.t==="video"||!B(e.href))return t;let c=se(f("a","bl"),B(e.href));return c.append(t),c}function lt(e){let t=I(e.threshold,.01,1e7);if(!t)return null;let r=f("div","pg"),s=f("p"),c=f("div","tr"),p=f("i");c.append(p),c.setAttribute("role","progressbar"),c.setAttribute("aria-valuemin","0"),c.setAttribute("aria-valuemax",String(t)),r.append(s,c);let d=g=>g.toFixed(2);try{let g=new Intl.NumberFormat(J||void 0,{style:"currency",currency:e.currency});d=w=>g.format(w)}catch{}let b=()=>{let g=Math.max(0,Number(n.basket?.())||0),w=t-g;s.textContent=w>0?String(e.text??"").replace("{amount}",d(w)):e.done??"",p.style.transform=`scaleX(${Math.min(1,g/t)})`,c.setAttribute("aria-valuenow",String(Math.min(g,t))),s.id||(s.id=ye("pg")),c.setAttribute("aria-labelledby",s.id)};return b(),i.timers.push(setInterval(b,2e3)),r}let Ie={heading(e){let t=Me(f("h2","",e.text),e,"xl");return t.id=ye("h"),t.tabIndex=-1,y.hasAttribute("aria-labelledby")||(y.setAttribute("aria-labelledby",t.id),i.step===a.steps[0]&&He.includes(i.mode)&&!h&&(t.autofocus=!0)),t},text:e=>Me(f("p","",e.text),e,"md"),email:e=>Le(e,"email"),phone:e=>Le(e,"tel"),consent(e){let t=T(i.step)?.text;if(typeof t!="string")return null;if(e.required!==!0)return f("p","sm",t);let r=f("label","c"),s=f("input");return s.type="checkbox",s.name="hp_consent",s.required=!0,s.setAttribute("aria-describedby",M.id),r.append(s,f("span","",t)),r},question:rt,wheel(){let e=f("div","wh");return n.loadWheel().then(t=>{i.closed||(i.wheel=t.mountWheel(e,o.prizes))}).catch(()=>{}),e},code(){let e=f("div","k");return e.setAttribute("aria-live","polite"),i.codes.push(e),e},button:at,decline(e){let t=f("button","btn no",e.label??"No thanks");return t.type="button",t.addEventListener("click",()=>j("decline")),t},countdown:st,progress:lt,image:Oe,video:Oe,spacer(e){let t=f("div","sp");return t.style.height=`${Ge[e.size]??Ge.md}px`,t.setAttribute("aria-hidden","true"),t},divider:()=>f("hr")};function ct(e,t){W.replaceChildren();let r=e.media,s=!r||t&&e.template!=="image-only";if(i.size=Je(k,e),E.className=`w t-${e.template} z-${i.size}${e.side==="right"?" right":""}${k.text_align==="center"?" ta-center":""}${s?" nm":""}`,E.style.setProperty("--sc",String(e.scrim)),A.className=`f pd-${e.padding}`,W.hidden=s,W.hidden)return;let c=Ce(r,"",i.step===a.steps[0],e.template==="split"?.46:1);if(!c)return;if(c.width?E.style.setProperty("--ar",`${c.width} / ${c.height}`):E.style.removeProperty("--ar"),e.template!=="image-only"){c.tagName==="IMG"&&e.template==="overlay"&&(c.alt=""),W.append(c);return}let p=B(r.href),d=p?se(f("a","io"),p):f("button","io");p||(d.type="button",d.addEventListener("click",()=>te({action:"next"}))),d.append(c),W.append(d)}function dt(e){let t=e.blocks.find(c=>c?.t==="heading"),r=e.blocks.find(c=>c?.t==="button"&&c.action==="next"),s=f("button","tb");return s.textContent=t?f("b","",t.text).textContent:r?.label??"Open",s.type="button",s.addEventListener("click",()=>te(r??{action:"next"})),s}function R(e,t=new Set){let r=a.steps.find(z=>z.id===e);if(!r)return j("done");if(r.kind==="question"&&!h&&!u.analytics()&&!t.has(r.id))return R(V(r,i.answers),t.add(r.id));let s=i.step!==null,c=s&&(L.activeElement||document.activeElement===document.body),p=s&&!h?{mode:i.mode,w:E.offsetWidth,h:E.offsetHeight,top:E.offsetTop}:null;i.step=r,i.touched=!1;for(let z of i.timers.splice(0))clearInterval(z);i.codes=[],i.videos=[],i.wheel=null;let d=S==="teaser"&&r===a.steps[0];if(i.mode=S==="teaser"&&!d?"popup":S,S==="teaser"&&v.tab?.(o.slot,d),Y&&Y.setAttribute("aria-label",d?$.closeOffer:"Close"),_e(),y.removeAttribute("aria-labelledby"),p){let z=Ee();A.replaceWith(z),A=z}let b=Ze(r);ct(b,d);let g=p?.mode==="popup"&&i.mode==="popup";if(ae(),p?.mode===i.mode&&p.h>0&&!g&&(E.style.setProperty("--lw",`${p.w}px`),E.style.setProperty("--lh",`${p.h}px`),E.classList.add("lk")),A.replaceChildren(),d&&b.template!=="image-only")A.append(dt(r));else for(let[z,O]of r.blocks.entries()){let q=P(O)&&Object.hasOwn(Ie,O.t)?Ie[O.t](O):null;q&&(h&&(q.dataset.hpBlock=String(z)),A.append(q))}let w=A.querySelector("[data-submit]"),_=A.querySelector("[name=hp_consent]")?.parentNode;w&&_&&w.before(_),A.hidden=A.childElementCount===0,N(null),re(),y.hasAttribute("aria-labelledby")?y.removeAttribute("aria-label"):y.setAttribute("aria-label",b.media?.alt?.trim?.()||"Sign up"),g&&p.h>0&&pt(p),s&&Pe(),oe(),h||ut(r),c&&A.querySelector("h2")?.focus()}function ae(){E.classList.remove("lk","an"),E.style.removeProperty("--tp")}function pt(e){let t=E.offsetHeight;E.classList.add("an");let r=E.offsetTop,s=Math.max(0,e.top-r);if(s+t>y.clientHeight-2*r)return ae();E.style.setProperty("--tp",`${s}px`)}function ut(e){let t=e.next??{};for(let c of[t.default,...Object.values(P(t.answers)?t.answers:{}),...e.blocks.map(p=>p?.next),...Mt])typeof c=="string"&&i.toWarm.add(c);if(i.warming)return;i.warming=!0;let r=()=>{if(i.warming=!1,!i.closed&&C.isConnected)for(let c of i.toWarm)Ae(o,a,c,i.warmed);i.toWarm.clear()},s=()=>globalThis.requestIdleCallback?requestIdleCallback(r,{timeout:2e3}):setTimeout(r,200);document.readyState==="complete"?s():window.addEventListener("load",s,{once:!0})}function Pe(){if(!U)return;let e=He.includes(i.mode);if(!(y.open&&i.modal===e)){try{y.open&&y.close()}catch{}if(i.modal=e,y.setAttribute("aria-modal",String(e)),e&&typeof y.showModal=="function")y.showModal();else if(typeof y.show=="function"){let t=document.activeElement;y.show(),t&&t!==document.body?t.focus?.({preventScroll:!0}):C.blur()}else y.setAttribute("open","");!e||typeof y.showModal!="function"?y.setAttribute("role","dialog"):y.removeAttribute("role")}}function ft(){for(let e of A.querySelectorAll("fieldset[data-question]")){let t=e.dataset.question,r=$e.get(e)?.()??{};if(r.error)return r;let s=[r.value,...[...e.querySelectorAll("input:checked,select:not([name])")].map(c=>c.value)].filter(Boolean);s.length?i.answers[t]=s:delete i.answers[t]}}function mt(){let e=[];for(let[r,s]of Object.entries(i.answers)){let c=`${r}=${s.join(",")}`;i.sent.has(c)||(i.sent.add(c),e.push({question:r,values:s}))}let t=i.step.id;if(i.signedUp&&e.length)return void m.answers({anonymousId:u.anonymousId(),sessionId:u.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t,...i.signedUp,answers:e,context:Ne()});if(u.analytics())for(let r of e)x.preferencesStated({...r,source:"onsite",slot:l.slot,arm:l.arm??null,decision_id:l.decision_id??null,step:t})}let Ne=()=>({page:{url:u.pageUrl()},locale:u.locale()??void 0,consent:u.consent()}),ee=e=>{i.receipt&&!h&&mt(),R(V(i.step,i.answers,e))};async function ht(e){let t=i.step,r=A.querySelector("input[name=email],input[name=phone]");if(!r)return ee(e.next);let s=r.name==="email"?"email":"sms",c=A.querySelector("select[name=hp_cc]")?.value,p=s==="email"?Ye(r.value.trim())?r.value.trim():null:Fe(r.value,c);if(!p)return N(s==="email"?$.email:c?$.phone:$.intl,r);let d=A.querySelector("input[name=hp_consent]");if(d&&!d.checked)return N($.consent,d);N(null),H(!0);let b=await Te();i.pow=null;let g=Object.entries(i.answers).map(([D,de])=>({question:D,values:de})),w=s==="sms"?o.sms_consent_text:o.consent_text,_=await m.capture({anonymousId:u.anonymousId(),sessionId:u.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t.id,channel:s,[s==="email"?"email":"phone"]:p,...s==="sms"&&i.signedUp,consent_text:w?{id:w.id,version:w.version}:void 0,...g.length?{answers:g}:{},...b?{altcha:b}:{},context:Ne()}),z=_.body?.status,O=(_.status===202||_.status===200)&&_t.includes(z);if(i.closed&&!O)return;O||H(!1);let q=_.status===400?_.body?.field:null;if(q==="email"||q==="phone")return N($[q],r);if(!O)return N(_.status===429?$.busy:$.failed,r);r.value="";for(let[D,de]of Object.entries(i.answers))i.sent.add(`${D}=${de.join(",")}`);i.receipt=typeof _.body.receipt=="string"?_.body.receipt:null,s==="email"&&(i.signedUp={email:p,email_receipt:i.receipt}),i.submitted=!0,v.submitted(o.slot),Q("submit",t.id),i.owed=s==="email"&&o.prizes.length>0;let ne=i.owed?ce([]):null;ne||n.emit?.("submitted",{coupon:null});let yt=ne&&await Promise.race([ne,new Promise(D=>setTimeout(D,It))]);if(i.closed)return;if(H(!1),yt?.held)return R(le("held"));let vt=z!=="ok"&&a.steps.some(D=>D.id===z);R(vt?z:V(t,i.answers,e.next));let wt=i.step;ne?.then(D=>{D?.held&&!i.closed&&i.step===wt&&!i.touched&&R(le("held"))})}function le(e){if(a.steps.some(r=>r.id===e))return e;let t=e==="fallback"||i.claim?.code?[{t:"heading",text:e==="fallback"?$.thanks:$.yours},{t:"code"}]:[{t:"heading",text:$.held},{t:"text",text:o.code_relayed===!0?$.resent:$.inbox},{t:"button",label:$.shop,action:"close"}];return a.steps.push({id:e,blocks:t}),e}function je(e){i.owed&&(i.owed=!1,n.emit?.("submitted",{coupon:e?{code:e.code??null,prize:e.prize?.key}:null}))}function ce(e=Ot){let t=i.receipt;return i.claiming??(i.claiming=(async()=>{let r;for(let d of[0,...e])if(d&&await new Promise(b=>setTimeout(b,d)),r=await m.claim({slot:l.slot,decision_id:l.decision_id??void 0,receipt:t}),r.status!==503)break;let s=r.body,c=s?.fallback===!0&&!s.code;if(r.status!==200||!(P(s?.prize)||c))return i.claiming=null,!e.length&&r.status===503?ce():(je(null),null);let p=s.held&&!s.code?v.code?.():null;return p&&(s={...s,code:p}),i.claim=s,typeof s.code=="string"&&v.code?.(s.code),je(s),i.closed||re(),s})()),i.claiming}async function bt(e){if(!i.receipt)return N($.spin);H(!0);let t=await ce();if(i.closed)return;if(!t)return H(!1),N($.failed);let r=t.fallback===!0&&!t.code,s=t.held?-1:o.prizes.findIndex(d=>d.key===t.prize?.key&&d.label===t.prize?.label);if(i.wheel&&s>=0&&!r){if(await i.wheel.spinTo(s),i.closed)return;M.className="e won",M.textContent=`${$.won} ${t.prize.label}`,await new Promise(d=>setTimeout(d,Pt))}if(i.closed)return;H(!1);let c=r?"fallback":s<0?"held":null,p=c?le(c):V(i.step,i.answers,e.next);p?R(p):re()}function te(e){if(e.action==="close")return j("close");let t=ft();return h?ee(e.next):t?N(t.error,t.input):e.action==="apply"?(n.emit?.("apply",{coupon:i.claim?.code?{code:i.claim.code}:null}),Q("click"),V(i.step,i.answers,e.next)?ee(e.next):j("done")):e.action==="submit"?ht(e):e.action==="spin"?bt(e):ee(e.next)}function gt(e){if(e.preventDefault(),A.getAttribute("aria-busy")==="true")return;let t=i.step.blocks.find(r=>r?.t==="button"&&r.action==="submit");te(t??{action:"next"})}function qe(){i.closed=!0;for(let t of i.timers.splice(0))clearInterval(t);document.removeEventListener("visibilitychange",oe),X?.removeEventListener?.("change",ze);let e=()=>{try{y.open&&y.close()}catch{}C.remove()};if(!U||xe())return e();y.classList.add("out"),setTimeout(e,Lt)}function j(e){i.closed||h||(!i.submitted&&e!=="done"&&Q("dismiss"),v.closed(o.slot),v.tab?.(o.slot,!1),qe(),n.onClose?.(e))}for(let e of["pointerdown","keydown","input"])y.addEventListener(e,()=>{i.touched=!0});y.addEventListener("cancel",e=>{e.preventDefault(),j("esc")}),y.addEventListener("keydown",e=>{e.key==="Escape"&&!i.modal&&S!=="inline"&&j("esc"),e.key==="Tab"&&i.modal&&xt(e)});function xt(e){let t=[...L.querySelectorAll("input[type=radio]:checked")],r=new Set,s=[...L.querySelectorAll("a[href],button,input,select,textarea")].filter(g=>{if(g.disabled||!g.getClientRects().length)return!1;if(g.type!=="radio")return!0;let w=t.find(_=>_.name===g.name);return(w?g!==w:r.has(g.name))?!1:(r.add(g.name),!0)});if(!s.length)return;let c=e.shiftKey,p=L.activeElement;p?.type==="radio"&&(p=s.find(g=>g.type==="radio"&&g.name===p.name)??p);let d=s.indexOf(p),b=null;if(d<0){let g=w=>p&&p.compareDocumentPosition(w)&4;b=c?s.findLast(w=>!g(w))??s.at(-1):s.find(g)??s[0]}else(c?d===0:d===s.length-1)&&(b=s.at(c?-1:0));b&&(e.preventDefault(),b.focus())}return ie.addEventListener("pointerdown",e=>{if(!i.mobile||i.mode!=="sheet")return;let t=e.clientY,r=0,s=p=>{r=Math.max(0,p.clientY-t),E.style.transform=`translateY(${r}px)`},c=()=>{document.removeEventListener("pointermove",s),document.removeEventListener("pointerup",c),E.style.transform="",r>80&&j("close")};document.addEventListener("pointermove",s),document.addEventListener("pointerup",c)}),R(h?.step&&a.steps.some(e=>e.id===h.step)?h.step:a.steps[0].id),(n.container??document.body).append(C),Pe(),{close:j,root:L,host:C,show:R,step:()=>i.step?.id??null,modal:()=>!i.closed&&i.modal,destroy:()=>!i.closed&&qe()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.render")]={mountForm:it,warm:Ae};})();
182
+ `;var $t=/^#(?:[0-9a-f]{3}){1,2}$/i,He=["popup","fullscreen"],_t=["ok","verify","already"],zt=["stack","split","overlay","image-only"],Be={bar:["bottom","top"],sheet:["bottom-right","bottom-left","bottom"],teaser:["bottom-left","bottom-right","left","right"]},Tt=["xs","sm","md","lg","xl","display"],Ge={xs:4,sm:8,md:16,lg:28,xl:44},Ve={sm:380,md:480,lg:880},Ct=["left","center","right"],Xe={secondary:" b2",link:" no"},Lt=220,Mt=["verify","already","held","fallback","success"],Ot=[500,1500],It=600,Pt=1800,A={email:"Enter a valid email address.",phone:"Enter a valid mobile number.",intl:"Enter a valid mobile number, starting with + and its country code.",consent:"Tick the box to sign up.",failed:"Something went wrong. Please try again.",busy:"Too many tries. Please wait a moment and try again.",spin:"Sign up first to spin.",yours:"Your code",held:"You\u2019re already on the list",resent:"We\u2019ve sent your code to your inbox again.",inbox:"Your code is in the email we sent when you first signed up.",shop:"Continue shopping",closeOffer:"Close offer",code:"We\u2019ll email your code to you.",claimed:"This email address has already claimed its code.",copied:"Copied",thanks:"Thanks, you\u2019re signed up",retry:"You\u2019re signed up, but we couldn\u2019t load your prize. Please try again.",unclaimed:"We couldn\u2019t load your prize right now.",unavailable:"Not available right now.",won:"You won"},P=i=>i!==null&&typeof i=="object"&&!Array.isArray(i),F=(i,o,a)=>i.includes(o)?o:a,I=(i,o,a)=>Number.isFinite(i)?Math.min(Math.max(i,o),a):null,ge=i=>i.type==="date"||i.type==="number",xe=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0;function Ze(i){let o=P(i.layout)?i.layout:{},a=P(o.media)?o.media:null,l=F(zt,o.template,"stack"),f=a?.side==="right"?"right":"left";return!a&&P(o.image)&&o.image.side!=="none"&&(a=o.image,o.image.side!=="top"&&(l="split",f=o.image.side==="right"?"right":"left")),(!a||!G(a.asset))&&(a=null,l="stack"),{template:l,media:a,side:f,scrim:I(o.scrim,0,.9)??.45,padding:F(["none","sm","md","lg"],o.padding,"md")}}var Je=(i,o)=>F(["sm","md","lg","full"],i.size,null)??(o.template==="split"||o.template==="overlay"?"lg":"md"),Qe=(i,o,a=1)=>{if(i==="fullscreen"||o==="full")return"100vw";let l=i==="teaser"?220:i==="sheet"?400:Ve[o]??Ve.md;return`(max-width: 639px) 100vw, ${Math.round(l*a)}px`},et=(i,o,a)=>{if(!a||!Array.isArray(i.widths)||!o.endsWith(".webp"))return null;let l=i.widths.filter(f=>Number.isInteger(f)&&f>0&&f<a).sort((f,x)=>f-x);return l.length===0?null:[...l.map(f=>`${o.slice(0,-5)}-${f}w.webp ${f}w`),`${o} ${a}w`].join(",")},tt=(i,o)=>i.format==="inline"?"inline":o.format&&o.format!=="inline"?o.format:i.format,ve=i=>i.kind==="video"||i.t==="video",we={webm:"video/webm",mp4:"video/mp4",m4v:"video/mp4",mov:"video/quicktime",ogv:"video/ogg"},ke=i=>we[i.split(/[?#]/)[0].split(".").pop().toLowerCase()],Nt=(i,o)=>[...new Set([o,...Array.isArray(i.sources)?i.sources.map(G):[]])].filter(Boolean).sort((a,l)=>(ke(l)===we.webm)-(ke(a)===we.webm));function Ae(i,o,a,l=new Set){let f=o.steps.find(k=>k.id===a);if(!f)return Promise.resolve();let x=tt(i,o),m=Ze(f),v=x==="teaser"&&f===o.steps[0],h=x==="teaser"&&!v?"popup":x,T=Je(o.theme,m),E=v?[]:f.blocks.filter(k=>P(k)&&(k.t==="image"||k.t==="video")).map(k=>[k,1]);return m.media&&!(v&&m.template!=="image-only")&&E.push([m.media,m.template==="split"?.46:1]),Promise.all(E.map(([k,Z])=>{let C=G(ve(k)?k.poster:k.asset);if(!C)return null;let L=document.createElement("img"),U=!ve(k)&&et(k,C,I(k.width,1,8192));U&&(L.sizes=Qe(h,T,Z),L.srcset=U);let y=`${L.sizes} ${U||C}`;return l.has(y)?null:(l.add(y),L.src=C,L.decode?.().catch(()=>{}))}))}var jt=0,ye=i=>`hp-${i}-${++jt}`;function u(i,o,a){let l=document.createElement(i);return o&&(l.className=o),a!==void 0&&l.append(We(a)),l}var nt=i=>{let o=i.length===4?[...i.slice(1)].map(a=>a+a).join(""):i.slice(1);return[0,2,4].map(a=>Number.parseInt(o.slice(a,a+2),16))},K=i=>{let[o,a,l]=nt(i).map(f=>{let x=f/255;return x<=.04045?x/12.92:((x+.055)/1.055)**2.4});return .2126*o+.7152*a+.0722*l},Ke=(i,o=4.5)=>{let a=K(i)+.05,l=1.05/a;return l>=o?"#fff":a/(K("#111")+.05)>l?"#111":"#fff"};function qt(i,o){let a=(E,k)=>k&&i.style.setProperty(E,k),l=E=>$t.test(E??"")?E:null;a("--hp-accent",l(o.accent)),a("--hp-bg",l(o.background)),a("--hp-text",l(o.text));let f=I(o.radius,0,48);f!==null&&a("--hp-radius",`${f}px`),a("--hp-font",o.font==="site"?i.ownerDocument.defaultView.getComputedStyle(i.parentElement??i.ownerDocument.body).fontFamily:Object.hasOwn(he,o.font)?he[o.font]:null),l(o.accent)&&(a("--hp-on-accent",Ke(o.accent,3)),a("--hp-on-accent-text",Ke(o.accent))),l(o.background)&&K(o.background)<.18&&(a("--hp-field","#fff"),a("--hp-field-text","#111"));let x=P(o.overlay)?o.overlay:{},m=[l(o.text),l(o.background)].filter(Boolean).sort((E,k)=>K(E)-K(k))[0],[v,h,T]=nt(l(x.colour)??m??"#0b0b0f");a("--hp-ov",`rgb(${v} ${h} ${T} / ${I(x.opacity,0,1)??.6})`)}function Dt(i){try{let o=new CSSStyleSheet;o.replaceSync(be),i.adoptedStyleSheets=[o]}catch{let o=document.createElement("style");o.textContent=be,i.append(o)}}function it(i){let{form:o,creative:a,decision:l,access:f,client:x,api:m,counters:v}=i,h=i.preview??null,T=e=>{let t=e.blocks.find(r=>r?.t==="email"||r?.t==="phone");return t?.t==="phone"||!t&&!o.consent_text?o.sms_consent_text:o.consent_text},E=tt(o,a),k=a.theme,Z=F(Be[E]??[],k.position,Be[E]?.[0]),C=document.createElement("hp-onsite");h&&C.setAttribute("preview",""),qt(C,k);let L=C.attachShadow({mode:"open"});Dt(L);let U=E!=="inline"&&!h,y=u(U?"dialog":E==="inline"?"section":"div"),Se=u("div","ov"),$=u("div","w"),W=u("div","m");h&&(W.dataset.hpMedia="");let Ee=()=>{let e=u("form","f");return e.noValidate=!0,e.addEventListener("submit",gt),e.addEventListener("input",()=>{M.textContent&&S.getAttribute("aria-busy")!=="true"&&N(null)}),e},S=Ee(),M=u("p","e");M.id=ye("err"),M.setAttribute("aria-live","assertive");let re=u("div","hd");re.setAttribute("aria-hidden","true"),$.append(re,W,S),y.append(Se,$);let Y=E!=="inline"&&u("button","x");Y&&(Y.type="button",Y.addEventListener("click",()=>j("close")),$.append(Y),Se.addEventListener("click",()=>j("close"))),L.append(y);let n={step:null,mode:E,size:"md",modal:!1,mobile:h?.device==="mobile",answers:{},sent:new Set,receipt:null,claim:i.coupon?{code:i.coupon}:h?{code:"WELCOME15"}:null,claiming:null,touched:!1,toWarm:new Set,warmed:i.warmed??new Set,warming:!1,owed:!1,unclaimed:!1,misses:0,submitted:!1,pow:null,wheel:null,timers:[],codes:[],videos:[],closed:!1},J=o.locale||document.documentElement.lang,ot=o.questions.some(ge)&&i.loadAnswers().catch(()=>null),$e=new WeakMap,_e=()=>{let e=P(k.button)?k.button:{};y.className=`s ${n.mode}${Z?` p-${Z}`:""} b-${F(["pill","rounded","square"],e.shape,"rounded")}${n.mobile?" mob":""}${h?" pv":""}${e.style==="outline"?" bo":""}${k.caps===!0?" uc":""}`},X=h?null:globalThis.matchMedia?.("(max-width: 639px)"),ze=()=>{n.mobile=X?.matches===!0,le(),_e()};X&&(n.mobile=X.matches===!0,X.addEventListener?.("change",ze));let Q=(e,t)=>{h||!l.decision_id||!f.analytics()||x.slotEngaged({decision_id:l.decision_id,slot:l.slot,arm:l.arm??null,engagement:e,step:t??n.step?.id??null})},N=(e,t)=>{M.className="e",M.textContent=e??"";for(let s of S.querySelectorAll("[aria-invalid]"))s.removeAttribute("aria-invalid");let r=t?.closest("label,fieldset");r&&S.contains(r)?r.after(M):S.append(M),t&&(t.setAttribute("aria-invalid","true"),t.setAttribute("aria-describedby",M.id),t.focus(),t.scrollIntoView?.({block:"nearest"}))},H=e=>{S.setAttribute("aria-busy",String(e));for(let t of S.querySelectorAll("button"))t.disabled=e},Te=()=>h?Promise.resolve(null):(n.pow??(n.pow=m.challenge().then(e=>e.status===200?Ue(e.body):null).catch(()=>null)),n.pow),se=()=>{for(let e of n.videos)try{document.hidden||xe()?e.pause():e.play()?.catch?.(()=>{})}catch{}};document.addEventListener("visibilitychange",se);function Ce(e,t,r,s){let c=G(e.asset);if(!c)return null;let p=typeof e.alt=="string"?e.alt:"",d;if(ve(e)){d=u("video",t),d.muted=d.defaultMuted=d.loop=d.playsInline=!0;let w=G(e.poster);w&&(d.poster=w),p?d.setAttribute("aria-label",p):d.setAttribute("aria-hidden","true"),d.autoplay=!xe()&&!h,d.preload=d.autoplay?"auto":w?"none":"metadata";let _=Nt(e,c);if(_.length>1)for(let z of _){let O=u("source");O.src=z;let q=ke(z);q&&(O.type=q),d.append(O)}else d.src=c;n.videos.push(d)}else{d=u("img",t),d.alt=p,d.decoding="async",d.loading=r?"eager":"lazy",r&&(d.fetchPriority="high");let w=et(e,c,I(e.width,1,8192));w&&(d.sizes=Qe(n.mode,n.size,s),d.srcset=w),d.src=c}let b=I(e.width,1,8192),g=I(e.height,1,8192);return b&&g&&(d.width=b,d.height=g),P(e.focal)&&(d.style.objectPosition=`${I(e.focal.x,0,100)??50}% ${I(e.focal.y,0,100)??50}%`),d}function Le(e,t){let r=u("label","l");r.append(u("span","lt",e.label??(t==="email"?"Email":"Mobile number")));let s=u("input","i");if(s.type=t,s.name=t==="email"?"email":"phone",s.autocomplete=s.inputMode=t,s.required=!0,typeof e.placeholder=="string"&&(s.placeholder=e.placeholder),s.setAttribute("aria-describedby",M.id),s.addEventListener("focus",Te,{once:!0}),t!=="tel")return r.append(s),r;s.id=`${M.id}-p`,r.htmlFor=s.id;let c=fe(u,"Country code","+",Object.entries(ue).map(([d,b])=>[d,`${d} +${b}`]),(e.country||/-(\w\w)$/.exec(J)?.[1]||"").toUpperCase());c.classList.add("cc"),c.name="hp_cc";let p=u("span","ph");return p.append(c,s),r.append(p),r}function rt(e){let t=o.questions.find(b=>b.key===e.question);if(!t||!ge(t)&&!Array.isArray(t.options))return null;let r=u("fieldset");r.dataset.question=t.key,r.append(u("legend","",t.label??""));let s=n.answers[t.key]??[];if(ge(t))return ot.then(b=>{if(!b)return r.append(u("p","sm",A.unavailable));b.answerFields(r,t,u,s[0],J),$e.set(r,()=>b.answerOf(r,t,void 0,J))}),r;let c=t.type==="many",p=F(["list","dropdown"],e.display,"buttons"),d=t.options.filter(b=>P(b)&&typeof b.value=="string");if(p==="dropdown"&&!c)return r.append(fe(u,t.label??t.key,"\u2014",d.map(b=>[b.value,b.label??b.value]),s[0])),r;p!=="buttons"&&(r.className="ls");for(let b of d){let g=u("input");g.value=b.value,g.checked=s.includes(b.value),g.type=c?"checkbox":"radio",g.name=`q_${t.key}`;let w=u("label",p==="buttons"?"ch":"c");w.append(g,u("span","",b.label??b.value)),r.append(w)}return r}function ee(){for(let e of n.codes){if(e.replaceChildren(),!n.claim){n.unclaimed&&e.append(u("p","",A.unclaimed));continue}if(!n.claim.code){let s=n.claim.held?A.claimed:n.claim.fallback===!0?A.code:n.claim.prize?.label;s&&e.append(u("p","",s));continue}n.claim.prize?.label&&e.append(u("p","",n.claim.prize.label));let t=u("output");t.textContent=n.claim.code;let r=u("button","btn cp");r.type="button",r.textContent="Copy code",r.addEventListener("click",()=>{navigator.clipboard?.writeText(n.claim.code).then(()=>{r.textContent=A.copied}).catch(()=>{})}),e.append(t,r)}}function st(e){if(n.claim&&!n.claim.code)return null;let t=u("p","tm");t.setAttribute("role","timer");let r=Date.now()+Math.max(0,Number(e.minutes)||0)*6e4,s=()=>{let p=Math.max(0,Math.round((r-Date.now())/1e3));t.textContent=`${String(Math.floor(p/60)).padStart(2,"0")}:${String(p%60).padStart(2,"0")}`,p===0&&clearInterval(c)},c=setInterval(s,1e3);return n.timers.push(c),s(),t}function ae(e,t){return e.href=t,e.rel="noopener",e.addEventListener("click",r=>{h?r.preventDefault():Q("click")}),e}function at(e){let t=e.label??"Continue";if(e.action==="link"){let s=B(e.href);return s?ae(u("a",`btn${Xe[e.variant]??""}`,t),s):null}let r=u("button",`btn${Xe[e.variant]??""}`,t);return r.type=e.action==="submit"?"submit":"button",r.type==="button"?r.addEventListener("click",()=>ie(e)):r.dataset.submit="",r}let Me=(e,t,r)=>(e.classList.add(`x-${F(Tt,t.size,r)}`),Ct.includes(t.align)&&e.classList.add(`a-${t.align}`),e);function Oe(e){let t=Ce(e,"bi",n.step===a.steps[0]);if(!t)return null;t.style.objectFit=e.fit==="contain"?"contain":"cover";let r=I(e.radius,0,48);r!==null&&(t.style.borderRadius=`${r}px`);let s=I(e.max_height,40,800);if(s!==null&&(t.style.maxHeight=`${s}px`),!t.width&&e.fit!=="contain"&&(t.style.aspectRatio="16 / 9"),e.t==="video"||!B(e.href))return t;let c=ae(u("a","bl"),B(e.href));return c.append(t),c}function lt(e){let t=I(e.threshold,.01,1e7);if(!t)return null;let r=u("div","pg"),s=u("p"),c=u("div","tr"),p=u("i");c.append(p),c.setAttribute("role","progressbar"),c.setAttribute("aria-valuemin","0"),c.setAttribute("aria-valuemax",String(t)),r.append(s,c);let d=g=>g.toFixed(2);try{let g=new Intl.NumberFormat(J||void 0,{style:"currency",currency:e.currency});d=w=>g.format(w)}catch{}let b=()=>{let g=Math.max(0,Number(i.basket?.())||0),w=t-g;s.textContent=w>0?String(e.text??"").replace("{amount}",d(w)):e.done??"",p.style.transform=`scaleX(${Math.min(1,g/t)})`,c.setAttribute("aria-valuenow",String(Math.min(g,t))),s.id||(s.id=ye("pg")),c.setAttribute("aria-labelledby",s.id)};return b(),n.timers.push(setInterval(b,2e3)),r}let Ie={heading(e){let t=Me(u("h2","",e.text),e,"xl");return t.id=ye("h"),t.tabIndex=-1,y.hasAttribute("aria-labelledby")||(y.setAttribute("aria-labelledby",t.id),n.step===a.steps[0]&&He.includes(n.mode)&&!h&&(t.autofocus=!0)),t},text:e=>Me(u("p","",e.text),e,"md"),email:e=>Le(e,"email"),phone:e=>Le(e,"tel"),consent(e){let t=T(n.step)?.text;if(typeof t!="string")return null;if(e.required!==!0)return u("p","sm",t);let r=u("label","c"),s=u("input");return s.type="checkbox",s.name="hp_consent",s.required=!0,s.setAttribute("aria-describedby",M.id),r.append(s,u("span","",t)),r},question:rt,wheel(){let e=u("div","wh");return i.loadWheel().then(t=>{n.closed||(n.wheel=t.mountWheel(e,o.prizes))}).catch(()=>{}),e},code(){let e=u("div","k");return e.setAttribute("aria-live","polite"),n.codes.push(e),e},button:at,decline(e){let t=u("button","btn no",e.label??"No thanks");return t.type="button",t.addEventListener("click",()=>j("decline")),t},countdown:st,progress:lt,image:Oe,video:Oe,spacer(e){let t=u("div","sp");return t.style.height=`${Ge[e.size]??Ge.md}px`,t.setAttribute("aria-hidden","true"),t},divider:()=>u("hr")};function ct(e,t){W.replaceChildren();let r=e.media,s=!r||t&&e.template!=="image-only";if(n.size=Je(k,e),$.className=`w t-${e.template} z-${n.size}${e.side==="right"?" right":""}${k.text_align==="center"?" ta-center":""}${s?" nm":""}`,$.style.setProperty("--sc",String(e.scrim)),S.className=`f pd-${e.padding}`,W.hidden=s,W.hidden)return;let c=Ce(r,"",n.step===a.steps[0],e.template==="split"?.46:1);if(!c)return;if(c.width?$.style.setProperty("--ar",`${c.width} / ${c.height}`):$.style.removeProperty("--ar"),e.template!=="image-only"){c.tagName==="IMG"&&e.template==="overlay"&&(c.alt=""),W.append(c);return}let p=B(r.href),d=p?ae(u("a","io"),p):u("button","io");p||(d.type="button",d.addEventListener("click",()=>ie({action:"next"}))),d.append(c),W.append(d)}function dt(e){let t=e.blocks.find(c=>c?.t==="heading"),r=e.blocks.find(c=>c?.t==="button"&&c.action==="next"),s=u("button","tb");return s.textContent=t?u("b","",t.text).textContent:r?.label??"Open",s.type="button",s.addEventListener("click",()=>ie(r??{action:"next"})),s}function D(e,t=new Set){let r=a.steps.find(z=>z.id===e);if(!r)return j("done");if(r.kind==="question"&&!h&&!f.analytics()&&!t.has(r.id))return D(V(r,n.answers),t.add(r.id));let s=n.step!==null,c=s&&(L.activeElement||document.activeElement===document.body),p=s&&!h?{mode:n.mode,w:$.offsetWidth,h:$.offsetHeight,top:$.offsetTop}:null;n.step=r,n.touched=!1;for(let z of n.timers.splice(0))clearInterval(z);n.codes=[],n.videos=[],n.wheel=null;let d=E==="teaser"&&r===a.steps[0];if(n.mode=E==="teaser"&&!d?"popup":E,E==="teaser"&&v.tab?.(o.slot,d),Y&&Y.setAttribute("aria-label",d?A.closeOffer:"Close"),_e(),y.removeAttribute("aria-labelledby"),p){let z=Ee();S.replaceWith(z),S=z}let b=Ze(r);ct(b,d);let g=p?.mode==="popup"&&n.mode==="popup";if(le(),p?.mode===n.mode&&p.h>0&&!g&&($.style.setProperty("--lw",`${p.w}px`),$.style.setProperty("--lh",`${p.h}px`),$.classList.add("lk")),S.replaceChildren(),d&&b.template!=="image-only")S.append(dt(r));else for(let[z,O]of r.blocks.entries()){let q=P(O)&&Object.hasOwn(Ie,O.t)?Ie[O.t](O):null;q&&(h&&(q.dataset.hpBlock=String(z)),S.append(q))}let w=S.querySelector("[data-submit]"),_=S.querySelector("[name=hp_consent]")?.parentNode;w&&_&&w.before(_),S.hidden=S.childElementCount===0,N(null),ee(),y.hasAttribute("aria-labelledby")?y.removeAttribute("aria-label"):y.setAttribute("aria-label",b.media?.alt?.trim?.()||"Sign up"),g&&p.h>0&&pt(p),s&&Pe(),se(),h||ut(r),c&&S.querySelector("h2")?.focus()}function le(){$.classList.remove("lk","an"),$.style.removeProperty("--tp")}function pt(e){let t=$.offsetHeight;$.classList.add("an");let r=$.offsetTop,s=Math.max(0,e.top-r);if(s+t>y.clientHeight-2*r)return le();$.style.setProperty("--tp",`${s}px`)}function ut(e){let t=e.next??{};for(let c of[t.default,...Object.values(P(t.answers)?t.answers:{}),...e.blocks.map(p=>p?.next),...Mt])typeof c=="string"&&n.toWarm.add(c);if(n.warming)return;n.warming=!0;let r=()=>{if(n.warming=!1,!n.closed&&C.isConnected)for(let c of n.toWarm)Ae(o,a,c,n.warmed);n.toWarm.clear()},s=()=>globalThis.requestIdleCallback?requestIdleCallback(r,{timeout:2e3}):setTimeout(r,200);document.readyState==="complete"?s():window.addEventListener("load",s,{once:!0})}function Pe(){if(!U)return;let e=He.includes(n.mode);if(!(y.open&&n.modal===e)){try{y.open&&y.close()}catch{}if(n.modal=e,y.setAttribute("aria-modal",String(e)),e&&typeof y.showModal=="function")y.showModal();else if(typeof y.show=="function"){let t=document.activeElement;y.show(),t&&t!==document.body?t.focus?.({preventScroll:!0}):C.blur()}else y.setAttribute("open","");!e||typeof y.showModal!="function"?y.setAttribute("role","dialog"):y.removeAttribute("role")}}function ft(){for(let e of S.querySelectorAll("fieldset[data-question]")){let t=e.dataset.question,r=$e.get(e)?.()??{};if(r.error)return r;let s=[r.value,...[...e.querySelectorAll("input:checked,select:not([name])")].map(c=>c.value)].filter(Boolean);s.length?n.answers[t]=s:delete n.answers[t]}}function mt(){let e=[];for(let[r,s]of Object.entries(n.answers)){let c=`${r}=${s.join(",")}`;n.sent.has(c)||(n.sent.add(c),e.push({question:r,values:s}))}let t=n.step.id;if(n.signedUp&&e.length)return void m.answers({anonymousId:f.anonymousId(),sessionId:f.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t,...n.signedUp,answers:e,context:Ne()});if(f.analytics())for(let r of e)x.preferencesStated({...r,source:"onsite",slot:l.slot,arm:l.arm??null,decision_id:l.decision_id??null,step:t})}let Ne=()=>({page:{url:f.pageUrl()},locale:f.locale()??void 0,consent:f.consent()}),te=e=>{n.receipt&&!h&&mt(),D(V(n.step,n.answers,e))};async function ht(e){let t=n.step,r=S.querySelector("input[name=email],input[name=phone]");if(!r)return te(e.next);let s=r.name==="email"?"email":"sms",c=S.querySelector("select[name=hp_cc]")?.value,p=s==="email"?Ye(r.value.trim())?r.value.trim():null:Fe(r.value,c);if(!p)return N(s==="email"?A.email:c?A.phone:A.intl,r);let d=S.querySelector("input[name=hp_consent]");if(d&&!d.checked)return N(A.consent,d);N(null),H(!0);let b=await Te();n.pow=null;let g=Object.entries(n.answers).map(([R,de])=>({question:R,values:de})),w=s==="sms"?o.sms_consent_text:o.consent_text,_=await m.capture({anonymousId:f.anonymousId(),sessionId:f.sessionId()??void 0,slot:l.slot,arm:l.arm??void 0,decision_id:l.decision_id??void 0,step:t.id,channel:s,[s==="email"?"email":"phone"]:p,...s==="sms"&&n.signedUp,consent_text:w?{id:w.id,version:w.version}:void 0,...g.length?{answers:g}:{},...b?{altcha:b}:{},context:Ne()}),z=_.body?.status,O=(_.status===202||_.status===200)&&_t.includes(z);if(n.closed&&!O)return;O||H(!1);let q=_.status===400?_.body?.field:null;if(q==="email"||q==="phone")return N(A[q],r);if(!O)return N(_.status===429?A.busy:A.failed,r);r.value="";for(let[R,de]of Object.entries(n.answers))n.sent.add(`${R}=${de.join(",")}`);n.receipt=typeof _.body.receipt=="string"?_.body.receipt:null,s==="email"&&(n.signedUp={email:p,email_receipt:n.receipt}),n.submitted=!0,v.submitted(o.slot),Q("submit",t.id),n.owed=s==="email"&&o.prizes.length>0;let oe=n.owed?ce([]):null;oe||i.emit?.("submitted",{coupon:null});let yt=oe&&await Promise.race([oe,new Promise(R=>setTimeout(R,It))]);if(n.closed)return;if(H(!1),yt?.held)return D(ne("held"));let vt=z!=="ok"&&a.steps.some(R=>R.id===z);D(vt?z:V(t,n.answers,e.next));let wt=n.step;oe?.then(R=>{R?.held&&!n.closed&&n.step===wt&&!n.touched&&D(ne("held"))})}function ne(e){if(a.steps.some(s=>s.id===e))return e;let t={t:"button",label:A.shop,action:"close"},r=e==="unclaimed"?[{t:"heading",text:A.thanks},{t:"text",text:A.unclaimed},t]:e==="fallback"||n.claim?.code?[{t:"heading",text:e==="fallback"?A.thanks:A.yours},{t:"code"}]:[{t:"heading",text:A.held},{t:"text",text:o.code_relayed===!0?A.resent:A.inbox},t];return a.steps.push({id:e,blocks:r}),e}function je(e){n.owed&&(n.owed=!1,i.emit?.("submitted",{coupon:e?{code:e.code??null,prize:e.prize?.key}:null}))}function ce(e=Ot){let t=n.receipt;return n.claiming??(n.claiming=(async()=>{n.unclaimed=!1;let r;for(let d of[0,...e])if(d&&await new Promise(b=>setTimeout(b,d)),r=await m.claim({slot:l.slot,decision_id:l.decision_id??void 0,receipt:t}),r.status!==503)break;let s=r.body,c=s?.fallback===!0&&!s.code;if(r.status!==200||!(P(s?.prize)||c))return n.claiming=null,!e.length&&r.status===503?ce():(je(null),n.unclaimed=!0,n.closed||ee(),null);let p=s.held&&!s.code?v.code?.():null;return p&&(s={...s,code:p}),n.claim=s,typeof s.code=="string"&&v.code?.(s.code),je(s),n.closed||ee(),s})()),n.claiming}async function bt(e){if(!n.receipt)return N(A.spin);H(!0);let t=await ce();if(n.closed)return;if(!t)return H(!1),n.misses+=1,n.misses<2?N(A.retry):D(ne("unclaimed"));let r=t.fallback===!0&&!t.code,s=t.held?-1:o.prizes.findIndex(d=>d.key===t.prize?.key&&d.label===t.prize?.label);if(n.wheel&&s>=0&&!r){if(await n.wheel.spinTo(s),n.closed)return;M.className="e won",M.textContent=`${A.won} ${t.prize.label}`,await new Promise(d=>setTimeout(d,Pt))}if(n.closed)return;H(!1);let c=r?"fallback":s<0?"held":null,p=c?ne(c):V(n.step,n.answers,e.next);p?D(p):ee()}function ie(e){if(e.action==="close")return j("close");let t=ft();return h?te(e.next):t?N(t.error,t.input):e.action==="apply"?(i.emit?.("apply",{coupon:n.claim?.code?{code:n.claim.code}:null}),Q("click"),V(n.step,n.answers,e.next)?te(e.next):j("done")):e.action==="submit"?ht(e):e.action==="spin"?bt(e):te(e.next)}function gt(e){if(e.preventDefault(),S.getAttribute("aria-busy")==="true")return;let t=n.step.blocks.find(r=>r?.t==="button"&&r.action==="submit");ie(t??{action:"next"})}function qe(){n.closed=!0;for(let t of n.timers.splice(0))clearInterval(t);document.removeEventListener("visibilitychange",se),X?.removeEventListener?.("change",ze);let e=()=>{try{y.open&&y.close()}catch{}C.remove()};if(!U||xe())return e();y.classList.add("out"),setTimeout(e,Lt)}function j(e){n.closed||h||(!n.submitted&&e!=="done"&&Q("dismiss"),v.closed(o.slot),v.tab?.(o.slot,!1),qe(),i.onClose?.(e))}for(let e of["pointerdown","keydown","input"])y.addEventListener(e,()=>{n.touched=!0});y.addEventListener("cancel",e=>{e.preventDefault(),j("esc")}),y.addEventListener("keydown",e=>{e.key==="Escape"&&!n.modal&&E!=="inline"&&j("esc"),e.key==="Tab"&&n.modal&&xt(e)});function xt(e){let t=[...L.querySelectorAll("input[type=radio]:checked")],r=new Set,s=[...L.querySelectorAll("a[href],button,input,select,textarea")].filter(g=>{if(g.disabled||!g.getClientRects().length)return!1;if(g.type!=="radio")return!0;let w=t.find(_=>_.name===g.name);return(w?g!==w:r.has(g.name))?!1:(r.add(g.name),!0)});if(!s.length)return;let c=e.shiftKey,p=L.activeElement;p?.type==="radio"&&(p=s.find(g=>g.type==="radio"&&g.name===p.name)??p);let d=s.indexOf(p),b=null;if(d<0){let g=w=>p&&p.compareDocumentPosition(w)&4;b=c?s.findLast(w=>!g(w))??s.at(-1):s.find(g)??s[0]}else(c?d===0:d===s.length-1)&&(b=s.at(c?-1:0));b&&(e.preventDefault(),b.focus())}return re.addEventListener("pointerdown",e=>{if(!n.mobile||n.mode!=="sheet")return;let t=e.clientY,r=0,s=p=>{r=Math.max(0,p.clientY-t),$.style.transform=`translateY(${r}px)`},c=()=>{document.removeEventListener("pointermove",s),document.removeEventListener("pointerup",c),$.style.transform="",r>80&&j("close")};document.addEventListener("pointermove",s),document.addEventListener("pointerup",c)}),D(h?.step&&a.steps.some(e=>e.id===h.step)?h.step:a.steps[0].id),(i.container??document.body).append(C),Pe(),{close:j,root:L,host:C,show:D,step:()=>n.step?.id??null,modal:()=>!n.closed&&n.modal,destroy:()=>!n.closed&&qe()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.render")]={mountForm:it,warm:Ae};})();
@@ -1 +1 @@
1
- (()=>{function S(e,o,t=5){let n=360/o;return t*360+(360-(e+.5)*n)}var w="http://www.w3.org/2000/svg",T=4500,I=.22,L=.95,C=.105,m=.082,O=.62,F=1.15,E="var(--hp-accent,#111)",z="var(--hp-on-accent,#fff)",g="var(--hp-bg,#fff)",M="var(--hp-text,#111)";function l(e,o={}){let t=document.createElementNS(w,e);for(let[n,c]of Object.entries(o))t.setAttribute(n,String(c));return t}function a(e,o,t,n=1){return e.style.fill=o,n<1&&(e.style.fillOpacity=String(n)),t&&(e.style.stroke=t),e}var k=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0,$=(e,o=1)=>{let t=(e-90)*Math.PI/180;return`${(o*Math.cos(t)).toFixed(4)} ${(o*Math.sin(t)).toFixed(4)}`};function R(e,o){let t=L-I,n=2*.35*Math.sin(Math.min(Math.PI/o,Math.PI/2)),c=s=>Math.max(m,Math.min(C,n/(s*F))),d=s=>t/(Math.max(1,s.length)*O),r=d(e);if(r>=m)return{lines:[e],size:Math.min(c(1),r)};let y=[...e.matchAll(/ /g)].map(s=>s.index);if(y.length){let s=e.length/2,i=y.reduce((h,p)=>Math.abs(p-s)<Math.abs(h-s)?p:h),u=[e.slice(0,i),e.slice(i+1)],f=Math.min(c(2),...u.map(d));if(f>=m)return{lines:u,size:f}}let x=Math.floor(t/(m*O));return{lines:[`${e.slice(0,x-1).trimEnd()}\u2026`],size:m}}function P(e,o){let t=(Array.isArray(o)?o:[]).map(s=>String(s?.label??s?.key??"")),n=t.length;if(n<2)return null;let c=360/n,d=l("svg",{viewBox:"-1.2 -1.2 2.4 2.4",role:"img","aria-label":`Prize wheel: ${t.join(", ")}`}),r=l("g");r.style.transformBox="fill-box",r.style.transformOrigin="50% 50%";let y=[[1,z],[.14,M],[.72,z]];r.append(a(l("circle",{r:1}),g));let x=[];return t.forEach((s,i)=>{let[u,f]=y[n%2===1&&i===n-1?2:i%2];r.append(a(l("path",{d:`M0 0L${$(i*c)}A1 1 0 ${c>180?1:0} 1 ${$((i+1)*c)}Z`,"stroke-width":.012}),E,g,u));let h=(i+.5)*c-90,p=R(s,n),N=a(l("text",{transform:`rotate(${h}) translate(${(I+L)/2} 0)${h>90&&h<270?" rotate(180)":""}`,"text-anchor":"middle","dominant-baseline":"central","font-size":p.size.toFixed(4),"font-weight":700,"aria-hidden":"true"}),f);p.lines.forEach((b,_)=>{let A=l("tspan",{x:0,y:((_-(p.lines.length-1)/2)*p.size*F).toFixed(4)});A.textContent=b,N.append(A)}),r.append(N);for(let b of[i*c,(i+.5)*c]){let[_,A]=$(b,1.075).split(" ");x.push(a(l("circle",{cx:_,cy:A,r:.024}),g))}}),d.append(a(l("circle",{r:1.13}),M),...x,r,a(l("circle",{r:.17,"stroke-width":.035}),g,M),a(l("circle",{r:.065}),E),a(l("path",{d:"M-0.12 -1.2L0.12 -1.2L0 -0.86Z","stroke-width":.03,"stroke-linejoin":"round"}),E,g)),e.append(d),{spinTo(s){let i=k();return r.style.transition=i?"none":`transform ${T}ms cubic-bezier(.15,.7,.1,1)`,r.style.transform=`rotate(${S(s,t.length,i?0:5)}deg)`,i?Promise.resolve():new Promise(u=>{let f=setTimeout(u,T+200);r.addEventListener("transitionend",()=>{clearTimeout(f),u()},{once:!0})})},remove:()=>d.remove()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.wheel")]={mountWheel:P};})();
1
+ (()=>{function L(e,i,s=5){let n=360/i;return s*360+(360-(e+.5)*n)}var k="http://www.w3.org/2000/svg",z=4500,S=.22,O=.95,v=.105,w=.082,A=.062,I=.62,F=1.15,N="var(--hp-accent,#111)",C="var(--hp-on-accent,#fff)",g="var(--hp-bg,#fff)",T="var(--hp-text,#111)";function c(e,i={}){let s=document.createElementNS(k,e);for(let[n,o]of Object.entries(i))s.setAttribute(n,String(o));return s}function f(e,i,s,n=1){return e.style.fill=i,n<1&&(e.style.fillOpacity=String(n)),s&&(e.style.stroke=s),e}var j=()=>globalThis.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches===!0,$=(e,i=1)=>{let s=(e-90)*Math.PI/180;return`${(i*Math.cos(s)).toFixed(4)} ${(i*Math.sin(s)).toFixed(4)}`};function B(e,i){let s=O-S,n=2*.35*Math.sin(Math.min(Math.PI/i,Math.PI/2)),o=t=>Math.max(w,Math.min(v,n/(t*F))),a=t=>s/(Math.max(1,t.length)*I),r=[...e.matchAll(/ /g)].map(t=>t.index),u=e.length/2,p=r.length?r.reduce((t,l)=>Math.abs(l-u)<Math.abs(t-u)?l:t):-1,h=p<0?null:[e.slice(0,p),e.slice(p+1)];for(let t of[w,A]){let l=a(e);if(l>=t)return{lines:[e],size:Math.min(o(1),l)};if(h){let m=Math.min(o(2),...h.map(a));if(m>=t)return{lines:h,size:m}}}let d=Math.floor(s/(A*I));return{lines:[`${e.slice(0,d-1).trimEnd()}\u2026`],size:A}}function P(e){let i=O-S,s=n=>n.getComputedTextLength?.()??0;for(let n of e){let o=[...n.querySelectorAll("tspan")],a=Math.max(0,...o.map(s));if(!(a>i))continue;let r=Math.max(A,Number(n.getAttribute("font-size"))*i/a);n.setAttribute("font-size",r.toFixed(4)),o.forEach((u,p)=>{u.setAttribute("y",((p-(o.length-1)/2)*r*F).toFixed(4)),s(u)>i&&(u.setAttribute("textLength",i.toFixed(4)),u.setAttribute("lengthAdjust","spacingAndGlyphs"))})}}function R(e,i){let s=(Array.isArray(i)?i:[]).map(d=>String(d?.label??d?.key??"")),n=s.length;if(n<2)return null;let o=360/n,a=c("svg",{viewBox:"-1.2 -1.2 2.4 2.4",role:"img","aria-label":`Prize wheel: ${s.join(", ")}`}),r=c("g");r.style.transformBox="fill-box",r.style.transformOrigin="50% 50%";let u=[[1,C],[.14,T],[.72,C]];r.append(f(c("circle",{r:1}),g));let p=[],h=[];return s.forEach((d,t)=>{let[l,m]=u[n%2===1&&t===n-1?2:t%2];r.append(f(c("path",{d:`M0 0L${$(t*o)}A1 1 0 ${o>180?1:0} 1 ${$((t+1)*o)}Z`,"stroke-width":.012}),N,g,l));let b=(t+.5)*o-90,x=B(d,n),_=f(c("text",{transform:`rotate(${b}) translate(${(S+O)/2} 0)${b>90&&b<270?" rotate(180)":""}`,"text-anchor":"middle","dominant-baseline":"central","font-size":x.size.toFixed(4),"font-weight":700,"aria-hidden":"true"}),m);x.lines.forEach((M,E)=>{let y=c("tspan",{x:0,y:((E-(x.lines.length-1)/2)*x.size*F).toFixed(4)});y.textContent=M,_.append(y)}),r.append(_),h.push(_);for(let M of[t*o,(t+.5)*o]){let[E,y]=$(M,1.075).split(" ");p.push(f(c("circle",{cx:E,cy:y,r:.024}),g))}}),a.append(f(c("circle",{r:1.13}),T),...p,r,f(c("circle",{r:.17,"stroke-width":.035}),g,T),f(c("circle",{r:.065}),N),f(c("path",{d:"M-0.12 -1.2L0.12 -1.2L0 -0.86Z","stroke-width":.03,"stroke-linejoin":"round"}),N,g)),e.append(a),P(h),globalThis.requestAnimationFrame?.(()=>P(h)),{spinTo(d){let t=j();return r.style.transition=t?"none":`transform ${z}ms cubic-bezier(.15,.7,.1,1)`,r.style.transform=`rotate(${L(d,s.length,t?0:5)}deg)`,t?Promise.resolve():new Promise(l=>{let m=setTimeout(l,z+200);r.addEventListener("transitionend",()=>{clearTimeout(m),l()},{once:!0})})},remove:()=>a.remove()}}window[Symbol.for("@thg-agentic/hyper-personalisation-web.onsite.wheel")]={mountWheel:R};})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thg-agentic/hyper-personalisation-web",
3
- "version": "3.24.0",
3
+ "version": "3.25.0",
4
4
  "description": "Browser SDK for the THG Hyper-Personalisation event specification: event tracking from a write key and remote settings, strict CMP-agnostic consent, a GA4 dataLayer bridge and in-session audience evaluation. Dependency-free ESM on the Segment wire protocol, a CDN script (dist/hp.min.js), and an optional @segment/analytics-next plugin path.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/bootstrap.js CHANGED
@@ -16,9 +16,10 @@
16
16
  * cookie, the device cookie's), the per-request currency / ship-to / locale getters, the preset,
17
17
  * the page type, debug, and which property this page is for a key scoped to several.
18
18
  *
19
- * Resolves to the client, or null when the key is disabled or unknown, the settings cannot be
20
- * fetched on a first visit, or the options are invalid. Never throws into the page, and is
21
- * idempotent per page. createAnalytics() and connectDataLayer() remain the lower-level API.
19
+ * Resolves to the client, or null when the key is disabled or unknown, or the options are invalid.
20
+ * Settings that cannot be fetched on a first visit start it on built-in, collect-only defaults.
21
+ * Never throws into the page, and is idempotent per page. createAnalytics() and connectDataLayer()
22
+ * remain the lower-level API.
22
23
  */
23
24
 
24
25
  import { assignmentDecisionId, assignmentSession } from './assignment.js';
@@ -47,9 +48,9 @@ import { createAnalytics, normaliseSha256, PAGE_TYPES } from './index.js';
47
48
  import { dropPendingOpens, onsite } from './onsite-facade.js';
48
49
  import { loadOnsite } from './onsite-loader.js';
49
50
  import {
51
+ BUILT_IN,
50
52
  cachedSettings,
51
53
  cacheSettings,
52
- DISABLED,
53
54
  eventsHost,
54
55
  fetchSettings,
55
56
  forgetSettings,
@@ -68,6 +69,9 @@ const INSTANCE = Symbol.for('@thg-agentic/hyper-personalisation-web.bootstrap');
68
69
  const DRAIN = Symbol.for('@thg-agentic/hyper-personalisation-web.drain');
69
70
  const CARRY = Symbol.for('@thg-agentic/hyper-personalisation-web.carry');
70
71
  const REPLAY = Symbol.for('@thg-agentic/hyper-personalisation-web.replay');
72
+ const UNREACHABLE = Symbol.for(
73
+ '@thg-agentic/hyper-personalisation-web.unreachable',
74
+ );
71
75
  /** Where bootstrap leaves `hp.assignmentDecisionId` its reader of the page's identity cookies. */
72
76
  const ASSIGNMENT = Symbol.for(
73
77
  '@thg-agentic/hyper-personalisation-web.assignment',
@@ -218,21 +222,18 @@ function pendingIdentify(propertyId, identity) {
218
222
  *
219
223
  * Inline settings (development, tests) are used as given and never fetched or cached. Otherwise a
220
224
  * cached answer starts the page at once while the API is asked again for the next page; with no
221
- * cache the page waits for the API, and `unreachable` says when it could not be asked.
225
+ * cache the page waits for the API, and starts on BUILT_IN when it cannot be asked: an outage of
226
+ * the API never turns collection off, and the events it cannot take wait in the retry buffer.
222
227
  */
223
228
  async function resolveSettings({ writeKey, apiHost }, options) {
224
229
  if (options.settings !== undefined)
225
230
  return { settings: readSettings(options.settings), revalidated: null };
226
231
  const fetched = fetchSettings(apiHost, writeKey);
227
232
  const cached = cachedSettings(writeKey);
228
- if (cached) return { settings: cached, revalidated: fetched };
233
+ if (cached) return { settings: cached, revalidated: fetched, fetched };
229
234
  const answer = await fetched;
230
- const settings = answer ?? DISABLED;
231
- return {
232
- settings,
233
- revalidated: Promise.resolve(settings),
234
- unreachable: answer === null,
235
- };
235
+ if (!answer) return { settings: BUILT_IN, revalidated: null, fetched };
236
+ return { settings: answer, revalidated: fetched, fetched };
236
237
  }
237
238
 
238
239
  /**
@@ -320,14 +321,44 @@ function startAutocapture(client, autocapture) {
320
321
  };
321
322
  }
322
323
 
324
+ /**
325
+ * How long a page that started from cached settings lets its forms wait for the fresh answer: the
326
+ * settings request already in flight, which the edge answers in well under this. Only the forms
327
+ * wait, never the page or its events; a slower answer leaves this page's forms on the cache.
328
+ */
329
+ const ONSITE_FRESH_MS = 1000;
330
+
323
331
  /**
324
332
  * Onsite forms, only when the page opted in and the settings have a live one: the runtime is a
325
- * separate chunk, fetched here and never part of the core.
333
+ * separate chunk, fetched here and never part of the core. A page that started from cached settings
334
+ * judges its forms by the answer it revalidates with, when that comes within ONSITE_FRESH_MS, so a
335
+ * form set live, changed or stopped in the console shows on the next page, not the one after.
326
336
  */
327
- function startOnsiteForms(client, opted, settings) {
328
- if (!opted || !settings.onsite) return dropPendingOpens();
329
- loadOnsite()
330
- .then((module) => module.startOnsite(client, opted === true ? {} : opted))
337
+ function startOnsiteForms(client, opted, settings, revalidated) {
338
+ if (!opted) return dropPendingOpens();
339
+ // The chunk is fetched alongside the fresh answer when the cache has a form, so neither waits.
340
+ const early = settings.onsite ? loadOnsite() : null;
341
+ early?.catch(() => {});
342
+ const fresh = revalidated
343
+ ? Promise.race([
344
+ revalidated.then((next) => next ?? settings),
345
+ new Promise((resolve) =>
346
+ setTimeout(() => resolve(settings), ONSITE_FRESH_MS),
347
+ ),
348
+ ])
349
+ : Promise.resolve(settings);
350
+ fresh
351
+ .then((current) => {
352
+ const forms = current.enabled ? current.onsite : null;
353
+ if (!forms) return dropPendingOpens();
354
+ const options = opted === true ? {} : opted;
355
+ return (early ?? loadOnsite()).then((module) =>
356
+ module.startOnsite(client, {
357
+ ...options,
358
+ settings: options.settings ?? forms,
359
+ }),
360
+ );
361
+ })
331
362
  .catch((err) => {
332
363
  dropPendingOpens();
333
364
  console.warn('[hp] onsite not started:', err?.message ?? err);
@@ -356,11 +387,10 @@ async function start(config, options, carry) {
356
387
  const { writeKey } = config;
357
388
  // The visitor's identity may still be looking itself up; it is waited for alongside the
358
389
  // settings, never before them. A lookup that fails leaves the visitor anonymous.
359
- const [{ settings, revalidated, unreachable }, identity] =
360
- await Promise.all([
361
- resolveSettings(config, options),
362
- Promise.resolve(options.identity).catch(() => null),
363
- ]);
390
+ const [{ settings, revalidated, fetched }, identity] = await Promise.all([
391
+ resolveSettings(config, options),
392
+ Promise.resolve(options.identity).catch(() => null),
393
+ ]);
364
394
 
365
395
  // What to cache is the newest answer; when is the first grant. Either may come first.
366
396
  let latest = revalidated ? settings : null;
@@ -373,11 +403,6 @@ async function start(config, options, carry) {
373
403
  else forgetSettings(writeKey);
374
404
  });
375
405
 
376
- // Unreachable, or left before the answer: what `hp` queued goes to the next page.
377
- if (unreachable) {
378
- dropPendingOpens();
379
- return null;
380
- }
381
406
  if (!settings.enabled) {
382
407
  if (options.debug)
383
408
  console.info(
@@ -386,8 +411,9 @@ async function start(config, options, carry) {
386
411
  return off(carry);
387
412
  }
388
413
  // The page's own property, else the source's default; a source with several and no default needs the page's.
389
- const propertyId = options.propertyId ?? settings.propertyId;
390
- if (!propertyId) {
414
+ // On BUILT_IN the ingest stamps the key's, and quarantines the events of a key with several.
415
+ const propertyId = options.propertyId ?? settings.propertyId ?? null;
416
+ if (!propertyId && settings !== BUILT_IN) {
391
417
  console.warn(
392
418
  '[hp] not started: this write key covers several properties, so propertyId is required',
393
419
  );
@@ -482,6 +508,9 @@ async function start(config, options, carry) {
482
508
 
483
509
  if (typeof window !== 'undefined')
484
510
  window[RECOMMENDATION_CONTEXT] = () => client.recommendationContext();
511
+ // The settings and the ingest share a host: one failing says the other likely is too, so what
512
+ // leaves at unload is also kept for the next page.
513
+ fetched?.then((answer) => answer === null && client[UNREACHABLE]());
485
514
 
486
515
  // Before this page's own events: they were made first. Consent here decides, as for any call.
487
516
  for (const [method, args, made] of carry.take()) {
@@ -535,7 +564,7 @@ async function start(config, options, carry) {
535
564
 
536
565
  if (identified) client.identify(identified, undefined, IDENTITY_OPTION);
537
566
  client.onsite = onsite;
538
- startOnsiteForms(client, options.onsite, settings);
567
+ startOnsiteForms(client, options.onsite, settings, revalidated);
539
568
  return client;
540
569
  } catch (err) {
541
570
  console.warn('[hp] not started:', err?.message ?? err);
@@ -98,7 +98,8 @@ function previousFromCookie(name) {
98
98
  * @param {boolean} [options.debug]
99
99
  * @param {{ read: () => any[], write: (items: any[]) => void }} [options.store]
100
100
  * Carry held items across pages (`holdAcrossPages`). Read on start, so a grant on the next page
101
- * releases what the previous one held; cleared on a grant or a refusal, never at unload.
101
+ * releases what the previous one held; written when the page is hidden, cleared on a grant or a
102
+ * refusal.
102
103
  */
103
104
  export function createConsentGate(options) {
104
105
  const {
@@ -240,9 +241,12 @@ export function createConsentGate(options) {
240
241
  */
241
242
  function onHidden(event) {
242
243
  if (!awaitingAnswer()) return;
243
- // With a store, the stored copy is what the next page answers for: the end of this one
244
- // discards nothing.
245
- if (store) return;
244
+ // With a store, the stored copy is what the next page answers for: written here, once, rather
245
+ // than on every held event, and the end of this page discards nothing.
246
+ if (store) {
247
+ store.write(held);
248
+ return;
249
+ }
246
250
  if (event?.type !== 'visibilitychange' && !event?.persisted) discardHeld();
247
251
  }
248
252
 
@@ -297,7 +301,6 @@ export function createConsentGate(options) {
297
301
  return false;
298
302
  }
299
303
  held.push(item);
300
- store?.write(held);
301
304
  return true;
302
305
  },
303
306
  /** Items unload would lose; the caller's own unload path flushes after this. */
package/src/context.js CHANGED
@@ -344,7 +344,8 @@ export const CONTEXT_KEYS = [
344
344
 
345
345
  export function sourceContext(cfg) {
346
346
  return {
347
- property_id: String(cfg.propertyId),
347
+ // None known (BUILT_IN settings): the ingest stamps the key's.
348
+ ...(cfg.propertyId == null ? {} : { property_id: String(cfg.propertyId) }),
348
349
  channel: cfg.channel ?? null,
349
350
  market: cfg.market ?? null,
350
351
  environment: cfg.environment ?? null,
@@ -2,9 +2,9 @@
2
2
  * Two device writes beyond the SDK's own buffers.
3
3
  *
4
4
  * held store events the consent gate holds for an unanswered CMP, in sessionStorage per
5
- * property, so a navigation before the answer (a sign-in redirect) does not lose
6
- * them (`holdAcrossPages`, 3.5). They leave only on a grant, on whichever page it
7
- * comes; a refusal deletes them.
5
+ * write key, so a navigation before the answer (a sign-in redirect) does not lose
6
+ * them (`holdAcrossPages`, 3.5). They leave only on a
7
+ * grant, on whichever page it comes; a refusal deletes them.
8
8
  * device cookie Hyper-Personalisation's device id, for a source whose settings say `hp_cookie`
9
9
  * (3.6). Under strict consent it is written only once analytics is granted.
10
10
  */
@@ -33,7 +33,7 @@ const local = () => {
33
33
  };
34
34
 
35
35
  /**
36
- * @param {string} key A property-scoped key (storageKey(storageName('held'), propertyId)).
36
+ * @param {string} key A write-key-scoped key (storageKey(storageName('held'), writeKey)).
37
37
  * @param {() => number} [now]
38
38
  */
39
39
  export function createHeldStore(key, now = () => Date.now()) {
package/src/index.js CHANGED
@@ -115,6 +115,10 @@ export { emailSha256, getCookie };
115
115
 
116
116
  /** How a call made before the SDK started is replayed with the messageId and time it was made at. */
117
117
  const REPLAY = Symbol.for('@thg-agentic/hyper-personalisation-web.replay');
118
+ /** How bootstrap tells the client its API could not be reached. Not public API. */
119
+ const UNREACHABLE = Symbol.for(
120
+ '@thg-agentic/hyper-personalisation-web.unreachable',
121
+ );
118
122
  /** How ./onsite reads what it needs from a client it was handed. Not public API. */
119
123
  const ONSITE_ACCESS = Symbol.for(
120
124
  '@thg-agentic/hyper-personalisation-web.onsite-access',
@@ -309,14 +313,65 @@ function contextOverrides(options) {
309
313
  return options;
310
314
  }
311
315
 
316
+ /**
317
+ * Before 3.25 the retry buffer and the held store were per property. What a 3.24 page kept there
318
+ * moves to this write key's, oldest first, and the old key goes: the batches keep their messageIds
319
+ * and are replayed as any other, under the same consent rules.
320
+ */
321
+ function adoptPropertyScopedBuffers(propertyId, writeKey) {
322
+ if (propertyId == null || String(propertyId) === writeKey) return;
323
+ const moves = [
324
+ [
325
+ 'localStorage',
326
+ 'retry',
327
+ (old, current) => [
328
+ ...(Array.isArray(old) ? old : []),
329
+ ...(Array.isArray(current) ? current : []),
330
+ ],
331
+ ],
332
+ [
333
+ 'sessionStorage',
334
+ 'held',
335
+ (old, current) =>
336
+ current
337
+ ? {
338
+ ...current,
339
+ items: [...(old.items ?? []), ...(current.items ?? [])],
340
+ }
341
+ : old,
342
+ ],
343
+ ];
344
+ for (const [store, name, merge] of moves) {
345
+ try {
346
+ const storage = globalThis[store];
347
+ const from = storageKey(storageName(name), propertyId);
348
+ const raw = storage?.getItem(from);
349
+ if (!raw) continue;
350
+ const to = storageKey(storageName(name), writeKey);
351
+ const current = storage.getItem(to);
352
+ storage.setItem(
353
+ to,
354
+ JSON.stringify(
355
+ merge(JSON.parse(raw), current ? JSON.parse(current) : null),
356
+ ),
357
+ );
358
+ storage.removeItem(from);
359
+ } catch {
360
+ /* unreadable or full: left where it was */
361
+ }
362
+ }
363
+ }
364
+
312
365
  export function createAnalytics(options) {
313
366
  const apiHost = resolveApiHost(options?.apiHost);
314
367
  if (!apiHost)
315
368
  throw new Error(
316
369
  'createAnalytics: apiHost, when given, must be a host or an http(s) origin',
317
370
  );
318
- if (!options?.propertyId)
319
- throw new Error('createAnalytics: propertyId is required');
371
+ if (options?.propertyId !== null && !options?.propertyId)
372
+ throw new Error(
373
+ 'createAnalytics: propertyId is required (null: the ingest stamps the key’s)',
374
+ );
320
375
 
321
376
  const cfg = {
322
377
  libraryName: LIB,
@@ -341,10 +396,12 @@ export function createAnalytics(options) {
341
396
  cfg.getConsent = () => (gate ? gate.stamp() : hostConsent());
342
397
  const granted = () => !strict || gate?.status === 'granted';
343
398
 
344
- // Opt-in (3.5): events held for an unanswered CMP survive a navigation, in sessionStorage.
399
+ adoptPropertyScopedBuffers(cfg.propertyId, cfg.writeKey);
400
+ // Opt-in (3.5): events held for an unanswered CMP survive a navigation, in sessionStorage. Per
401
+ // write key, as the retry buffer: what they are sent with.
345
402
  const heldStore =
346
403
  strict && cfg.holdAcrossPages
347
- ? createHeldStore(storageKey(storageName('held'), cfg.propertyId))
404
+ ? createHeldStore(storageKey(storageName('held'), cfg.writeKey))
348
405
  : null;
349
406
  const carried = heldStore?.read() ?? { items: [], anonymousId: null };
350
407
 
@@ -379,9 +436,9 @@ export function createAnalytics(options) {
379
436
  new Transport({
380
437
  apiHost: cfg.apiHost,
381
438
  writeKey: cfg.writeKey,
382
- // Per tenant: a persisted batch is replayed through whichever instance starts next, with its
383
- // writeKey, and one origin can serve several tenants.
384
- storageKey: storageKey(storageName('retry'), cfg.propertyId),
439
+ // Per write key, which a replay is sent with: one origin can serve several tenants, and a page
440
+ // started without its property (BUILT_IN settings) is replayed by the next one, which has it.
441
+ storageKey: storageKey(storageName('retry'), cfg.writeKey),
385
442
  // Under strict consent, persisting is a device write and replaying is a send: both wait for a
386
443
  // grant (see onStatus below, which replays on a grant and clears on a refusal).
387
444
  mayPersist: strict ? () => gate?.status === 'granted' : undefined,
@@ -1098,6 +1155,10 @@ export function createAnalytics(options) {
1098
1155
  },
1099
1156
  };
1100
1157
  },
1158
+ /** bootstrap: the settings could not be fetched, so the ingest on the same host is taken as down. */
1159
+ [UNREACHABLE]() {
1160
+ transport.markFailing?.();
1161
+ },
1101
1162
  /** `hp` and bootstrap replay a call made before the start through this. Not public API. */
1102
1163
  [REPLAY](method, args, made) {
1103
1164
  if (typeof this[method] !== 'function') return;