@freshjuice/zest 2.1.0 → 2.2.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.
- package/dist/zest.d.ts +33 -0
- package/dist/zest.de.js +107 -3
- package/dist/zest.de.js.map +1 -1
- package/dist/zest.de.min.js +1 -1
- package/dist/zest.en.js +107 -3
- package/dist/zest.en.js.map +1 -1
- package/dist/zest.en.min.js +1 -1
- package/dist/zest.es.js +107 -3
- package/dist/zest.es.js.map +1 -1
- package/dist/zest.es.min.js +1 -1
- package/dist/zest.esm.js +107 -3
- package/dist/zest.esm.js.map +1 -1
- package/dist/zest.esm.min.js +1 -1
- package/dist/zest.fr.js +107 -3
- package/dist/zest.fr.js.map +1 -1
- package/dist/zest.fr.min.js +1 -1
- package/dist/zest.headless.d.ts +33 -0
- package/dist/zest.headless.esm.js +107 -3
- package/dist/zest.headless.esm.js.map +1 -1
- package/dist/zest.headless.esm.min.js +1 -1
- package/dist/zest.it.js +107 -3
- package/dist/zest.it.js.map +1 -1
- package/dist/zest.it.min.js +1 -1
- package/dist/zest.ja.js +107 -3
- package/dist/zest.ja.js.map +1 -1
- package/dist/zest.ja.min.js +1 -1
- package/dist/zest.js +107 -3
- package/dist/zest.js.map +1 -1
- package/dist/zest.min.js +1 -1
- package/dist/zest.nl.js +107 -3
- package/dist/zest.nl.js.map +1 -1
- package/dist/zest.nl.min.js +1 -1
- package/dist/zest.pl.js +107 -3
- package/dist/zest.pl.js.map +1 -1
- package/dist/zest.pl.min.js +1 -1
- package/dist/zest.pt.js +107 -3
- package/dist/zest.pt.js.map +1 -1
- package/dist/zest.pt.min.js +1 -1
- package/dist/zest.ru.js +107 -3
- package/dist/zest.ru.js.map +1 -1
- package/dist/zest.ru.min.js +1 -1
- package/dist/zest.uk.js +107 -3
- package/dist/zest.uk.js.map +1 -1
- package/dist/zest.uk.min.js +1 -1
- package/dist/zest.zh.js +107 -3
- package/dist/zest.zh.js.map +1 -1
- package/dist/zest.zh.min.js +1 -1
- package/package.json +1 -1
- package/src/config/defaults.js +48 -0
- package/src/core/pattern-matcher.js +37 -0
- package/src/core-lifecycle.js +23 -4
- package/src/types/zest.d.ts +33 -0
- package/src/types/zest.headless.d.ts +33 -0
package/dist/zest.pt.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Zest=function(){"use strict";const t={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};function n(n){if(null==n)return"";return("string"==typeof n?n:n+"").replace(/[&<>"'`]/g,n=>t[n])}const e=new Set(["transparent","black","white","red","green","blue","yellow","orange","purple","pink","gray","grey","brown","cyan","magenta","silver","gold","navy","teal","maroon","olive","lime","aqua","fuchsia","indigo","violet","crimson","coral","salmon","tomato"]);const o=[/(\([^)]*[+*][^)]*\)|\[[^\]]*\]|\\w|\\d|\\s)\s*[+*]/,/\(\?[=!][^)]*[+*][^)]*\)[+*]/];function a(t,n){if(t instanceof RegExp)return t;if("string"!=typeof t)return null;if(t.length>500)return null;for(const n of o)if(n.test(t))return null;try{return RegExp(t,n)}catch(t){return null}}const s=new Set(["__proto__","constructor","prototype"]);function r(t,n){if(!t||"object"!=typeof t||Array.isArray(t))return null;const e={version:"string"==typeof t.version?t.version:null,timestamp:"number"==typeof t.timestamp&&Number.isFinite(t.timestamp)?t.timestamp:null,categories:{}},o=t.categories;if(!o||"object"!=typeof o||Array.isArray(o))return null;for(const t of n)s.has(t)||Object.prototype.hasOwnProperty.call(o,t)&&(e.categories[t]=!0===o[t]);return n.includes("essential")&&(e.categories.essential=!0),e}function i(t,...n){if("function"==typeof t)try{return t(...n)}catch(t){try{console.error("[Zest] User callback threw:",t)}catch(t){}return}}const c={essential:[/^zest_/,/^csrf/i,/^xsrf/i,/^session/i,/^__host-/i,/^__secure-/i],functional:[/^lang/i,/^locale/i,/^theme/i,/^preferences/i,/^ui_/i],analytics:[/^_ga/,/^_gid/,/^_gat/,/^_utm/,/^__utm/,/^plausible/i,/^_pk_/,/^matomo/i,/^_hj/,/^ajs_/],marketing:[/^_fbp/,/^_fbc/,/^_gcl/,/^_ttp/,/^ads/i,/^doubleclick/i,/^__gads/,/^__gpi/,/^_pin_/,/^li_/]};let l={...c};function d(t){for(const[n,e]of Object.entries(l))if(e.some(n=>n.test(t)))return n;return"marketing"}let u=null;const p=[];let f=()=>!1;function g(){return u}let m=null,b=null;const h=[],y=[];let z=()=>!1;function w(t,n,e){return new Proxy(t,{get(t,e){if("setItem"===e)return(e,o)=>{const a=d(e);z(a)?t.setItem(e,o):200>n.length&&n.push({key:e,value:o,category:a,timestamp:Date.now()})};const o=t[e];return"function"==typeof o?o.bind(t):o}})}const x={analytics:["google-analytics.com","www.google-analytics.com","analytics.google.com","googletagmanager.com","www.googletagmanager.com","plausible.io","cloudflareinsights.com","static.cloudflareinsights.com"],marketing:["connect.facebook.net","www.facebook.com/tr","ads.google.com","www.googleadservices.com","googleads.g.doubleclick.net","pagead2.googlesyndication.com"]},v={analytics:[...x.analytics,"analytics.tiktok.com","matomo.","hotjar.com","static.hotjar.com","script.hotjar.com","clarity.ms","www.clarity.ms","heapanalytics.com","cdn.heapanalytics.com","mixpanel.com","cdn.mxpnl.com","segment.com","cdn.segment.com","api.segment.io","fullstory.com","rs.fullstory.com","amplitude.com","cdn.amplitude.com","mouseflow.com","cdn.mouseflow.com","luckyorange.com","cdn.luckyorange.net","crazyegg.com","script.crazyegg.com"],marketing:[...x.marketing,"snap.licdn.com","px.ads.linkedin.com","ads.linkedin.com","analytics.twitter.com","static.ads-twitter.com","t.co","analytics.tiktok.com","ads.tiktok.com","sc-static.net","tr.snapchat.com","ct.pinterest.com","pintrk.com","s.pinimg.com","widgets.pinterest.com","bat.bing.com","ads.yahoo.com","sp.analytics.yahoo.com","amazon-adsystem.com","z-na.amazon-adsystem.com","criteo.com","static.criteo.net","dis.criteo.com","taboola.com","cdn.taboola.com","trc.taboola.com","outbrain.com","widgets.outbrain.com","adroll.com","s.adroll.com"],functional:["cdn.onesignal.com","onesignal.com","pusher.com","js.pusher.com","intercom.io","widget.intercom.io","js.intercomcdn.com","crisp.chat","client.crisp.chat","cdn.livechatinc.com","livechatinc.com","tawk.to","embed.tawk.to","zendesk.com","static.zdassets.com"]};function k(t,n){let e;try{e=new URL(t)}catch(t){return!1}const o=e.hostname.toLowerCase(),a=e.pathname.toLowerCase();for(const t of n){if("string"!=typeof t)continue;const n=t.toLowerCase();if(n.endsWith(".")){const t=n.slice(0,-1);if(o.split(".").some(n=>n===t)||o.startsWith(n))return!0;continue}const e=n.indexOf("/");if(-1!==e){const t=n.slice(0,e),s=n.slice(e);if((o===t||o.endsWith("."+t))&&a.startsWith(s))return!0;continue}if(o===n||o.endsWith("."+n))return!0}return!1}function _(t,n="safe"){const e="strict"===n?v:x;for(const[n,o]of Object.entries(e))if(k(t,o))return n;return null}const A=new Set(["functional","analytics","marketing"]),C=[];let S=null,j="safe",E=[],$=()=>!1;function N(t){if(t.hasAttribute("data-zest-allow"))return null;const n=t.getAttribute("data-consent-category"),e=n&&A.has(n)?n:null,o=t.src;if(!o)return e;const a=function(t){if(!t||0===E.length)return null;try{const n=new URL(t).hostname.toLowerCase();for(const t of E){const e="string"==typeof t?t:t.domain,o="string"==typeof t?"marketing":t.category||"marketing";if(n===e||n.endsWith("."+e))return o}}catch(t){}return null}(o);let s=null;switch(j){case"manual":break;case"safe":case"strict":s=_(o,j);break;case"doomsday":(function(t){try{const n=new URL(t).hostname,e=window.location.hostname,o=t=>t.replace(/^www\./,"");return o(n)!==o(e)}catch(t){return!1}})(o)&&(s=_(o,"strict")||"marketing")}return s||a||e}function R(t){if(t.hasAttribute("data-zest-processed"))return!1;const n=N(t);if(!n)return t.setAttribute("data-zest-processed","allowed"),!1;if($(n))return t.setAttribute("data-zest-processed","allowed"),!1;const e={category:n,src:t.src||"",inline:t.textContent,type:t.type,async:t.async,defer:t.defer,element:t,timestamp:Date.now()};return t.setAttribute("data-zest-processed","blocked"),t.setAttribute("data-consent-category",n),t.type="text/plain",t.src&&t.removeAttribute("src"),500>C.length&&C.push(e),!0}function L(t){for(const n of t)for(const t of n.addedNodes)if("SCRIPT"!==t.nodeName||t.hasAttribute("data-zest-processed")||R(t),t.querySelectorAll){t.querySelectorAll("script:not([data-zest-processed])").forEach(R)}}function M(t="safe",n=[]){return j=t,E=n,document.querySelectorAll("script:not([data-zest-processed])").forEach(R),S=new MutationObserver(L),S.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const D={essential:{id:"essential",label:"Essential",description:"Required for the website to function properly. Cannot be disabled.",required:!0,default:!0},functional:{id:"functional",label:"Functional",description:"Enable personalized features like language preferences and themes.",required:!1,default:!1},analytics:{id:"analytics",label:"Analytics",description:"Help us understand how visitors interact with our website.",required:!1,default:!1},marketing:{id:"marketing",label:"Marketing",description:"Used to deliver relevant advertisements and track campaign performance.",required:!1,default:!1}};function O(){return Object.keys(D)}function q(){if("undefined"==typeof navigator)return!1;const t=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===t||"yes"===t||!0===t||!0===navigator.globalPrivacyControl}function T(t,n,e){const o=e?"default":"update";n.consentModeGoogle&&function(t,n){if(window.dataLayer=window.dataLayer||[],"function"==typeof window.gtag)window.gtag("consent",t,n);else{function e(){window.dataLayer.push(arguments)}e("consent",t,n)}}(o,function(t){const n=t=>t?"granted":"denied";return{ad_storage:n(t.marketing),ad_user_data:n(t.marketing),ad_personalization:n(t.marketing),analytics_storage:n(t.analytics),functionality_storage:"granted",personalization_storage:n(t.functional)}}(t)),n.consentModeMicrosoft&&function(t,n){window.uetq=window.uetq||[],window.uetq.push("consent",t,n)}(o,function(t){return{ad_storage:t.marketing?"granted":"denied"}}(t))}const W={labels:{banner:{title:"Valorizamos sua privacidade",description:'Usamos cookies para melhorar sua experiência de navegação, fornecer conteúdo personalizado e analisar nosso tráfego. Ao clicar em "Aceitar tudo", você consente com o uso de cookies.',acceptAll:"Aceitar tudo",rejectAll:"Rejeitar tudo",settings:"Configurações"},modal:{title:"Configurações de privacidade",description:"Gerencie suas preferências de cookies. Você pode ativar ou desativar diferentes tipos de cookies abaixo.",save:"Salvar preferências",acceptAll:"Aceitar tudo",rejectAll:"Rejeitar tudo"},widget:{label:"Configurações de cookies"}},categories:{essential:{label:"Essenciais",description:"Necessários para o funcionamento do site. Não podem ser desativados."},functional:{label:"Funcionais",description:"Permitem recursos personalizados como preferências de idioma e tema."},analytics:{label:"Analíticos",description:"Nos ajudam a entender como os visitantes interagem com nosso site."},marketing:{label:"Marketing",description:"Usados para exibir anúncios relevantes e medir o desempenho de campanhas."}}};const I={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:D,labels:{banner:{title:"We value your privacy",description:'We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies.',acceptAll:"Accept All",rejectAll:"Reject All",settings:"Settings"},modal:{title:"Privacy Settings",description:"Manage your cookie preferences. You can enable or disable different types of cookies below.",save:"Save Preferences",acceptAll:"Accept All",rejectAll:"Reject All"},widget:{label:"Cookie Settings"}},autoInit:!0,showWidget:!0,expiration:365,respectDNT:!0,dntBehavior:"reject",customStyles:"",consentModeGoogle:!1,consentModeMicrosoft:!1,mode:"safe",blockedDomains:[],policyUrl:null,imprintUrl:null,callbacks:{onAccept:null,onReject:null,onChange:null,onReady:null}};function U(t){const n={...I};t||(t={});const e=["lang","position","theme","accentColor","autoInit","showWidget","expiration","policyUrl","imprintUrl","customStyles","mode","blockedDomains","respectDNT","dntBehavior","consentModeGoogle","consentModeMicrosoft"];for(const o of e)void 0!==t[o]&&(n[o]=t[o]);n.lang="pt";const o=W,a=o.labels||{},s=t.labels||{};n.labels={banner:{...I.labels.banner,...a.banner,...s.banner},modal:{...I.labels.modal,...a.modal,...s.modal},widget:{...I.labels.widget,...a.widget,...s.widget}};const r=o.categories||{},i=t.categories||{};n.categories={...I.categories};for(const t of Object.keys(I.categories))n.categories[t]={...I.categories[t],...r[t],...i[t]};return t.callbacks&&(n.callbacks={...I.callbacks,...t.callbacks}),t.patterns&&(n.patterns=t.patterns),n}function Z(){const t="undefined"!=typeof window&&window.ZestConfig?window.ZestConfig:{},n=function(){const t=document.currentScript||document.querySelector("script[data-zest]")||document.querySelector('script[src*="zest"]');if(!t)return{};const n={},e=t.getAttribute("data-position");e&&(n.position=e);const o=t.getAttribute("data-theme");o&&(n.theme=o);const a=t.getAttribute("data-accent")||t.getAttribute("data-accent-color");a&&(n.accentColor=a);const s=t.getAttribute("data-policy-url")||t.getAttribute("data-privacy-url");s&&(n.policyUrl=s);const r=t.getAttribute("data-imprint-url");r&&(n.imprintUrl=r);const i=t.getAttribute("data-show-widget");null!==i&&(n.showWidget="false"!==i);const c=t.getAttribute("data-auto-init");null!==c&&(n.autoInit="false"!==c);const l=t.getAttribute("data-expiration");l&&(n.expiration=parseInt(l,10));const d=t.getAttribute("data-consent-mode-google");null!==d&&(n.consentModeGoogle="false"!==d);const u=t.getAttribute("data-consent-mode-microsoft");return null!==u&&(n.consentModeMicrosoft="false"!==u),n}();return U({...t,...n})}let P=null;function Y(){return P||(P=Z()),P}const H="zest_consent";function F(){try{return"undefined"!=typeof location&&"https:"===location.protocol?"; Secure":""}catch(t){return""}}let B=null;function G(t){const n=g();n?.set?n.set.call(document,t):document.cookie=t}function J(){const t=g();return t?.get?t.get.call(document):document.cookie}function X(){try{const t=J().match(RegExp(H+"=([^;]+)"));if(t){const n=r(JSON.parse(decodeURIComponent(t[1])),O());if(n&&n.categories)return B={essential:!0,functional:!1,analytics:!1,marketing:!1,...n.categories},{...B}}}catch(t){}return B={essential:!0,functional:!1,analytics:!1,marketing:!1},{...B}}function V(){return B||(B=X()),{...B}}function K(t,n=365){const e=B?{...B}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return B={essential:!0,functional:!!t.functional,analytics:!!t.analytics,marketing:!!t.marketing},function(t=365){B||(B={essential:!0,functional:!1,analytics:!1,marketing:!1});const n={version:"1.0",timestamp:Date.now(),categories:B},e=new Date(Date.now()+24*t*60*60*1e3).toUTCString();G(`${H}=${encodeURIComponent(JSON.stringify(n))}; expires=${e}; path=/; SameSite=Lax${F()}`)}(n),{current:{...B},previous:e}}function Q(t){return B||(B=X()),!0===B[t]}function tt(t=365){return K({functional:!1,analytics:!1,marketing:!1},t)}function nt(){try{return J().includes(H)}catch(t){return!1}}const et={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function ot(t,n={}){const e=new CustomEvent(t,{detail:n,bubbles:!0,cancelable:!0});return document.dispatchEvent(e),e}function at(t,n){return ot(et.CONSENT,{consent:t,previous:n})}function st(t){return ot(et.REJECT,{consent:t})}function rt(t,n){return ot(et.CHANGE,{consent:t,previous:n})}function it(t="banner"){return ot(et.SHOW,{type:t})}function ct(t="banner"){return ot(et.HIDE,{type:t})}let lt=!1,dt=null;function ut(t){return Q(t)}function pt(t){!function(t){const n=[];for(const e of p)t.includes(e.category)?u?.set&&u.set.call(document,e.value):n.push(e);p.length=0,p.push(...n)}(t),function(t){const n=[];for(const e of h)t.includes(e.category)?m?.setItem(e.key,e.value):n.push(e);h.length=0,h.push(...n);const e=[];for(const n of y)t.includes(n.category)?b?.setItem(n.key,n.value):e.push(n);y.length=0,y.push(...e)}(t),function(t){const n=[];for(const e of C){if(!t.includes(e.category)){n.push(e);continue}const o=document.createElement("script");e.src?o.src=e.src:e.inline&&(o.textContent=e.inline),e.async&&(o.async=!0),e.defer&&(o.defer=!0),e.type&&"text/plain"!==e.type&&(o.type=e.type),o.setAttribute("data-zest-processed","executed"),o.setAttribute("data-consent-executed","true");const a=e.element;a&&a.isConnected&&a.parentNode?a.parentNode.replaceChild(o,a):document.head.appendChild(o)}C.length=0,C.push(...n)}(t)}function ft(t={}){if(lt)return{alreadyInitialized:!0,config:dt,consent:X(),hasDecision:nt(),dntApplied:!1};P=U(t),dt=P,T({functional:!1,analytics:!1,marketing:!1},dt,!0),dt.patterns&&function(t){if(l={...c},t&&"object"==typeof t)for(const[n,e]of Object.entries(t)){if(!Array.isArray(e))continue;const t=[];for(const n of e){const e=a(n);if(e)t.push(e);else try{console.warn("[Zest] Rejected unsafe pattern:",n)}catch(t){}}l[n]=t}}(dt.patterns),f=ut,function(t){z=t}(ut),function(t){$=t}(ut),u=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),u?Object.defineProperty(document,"cookie",{get:()=>u.get.call(document),set(t){const n=function(t){const n=t.match(/^([^=]+)/);return n?n[1].trim():null}(t);if(!n)return;const e=d(n);f(e)?u.set.call(document,t):100>p.length&&p.push({value:t,name:n,category:e,timestamp:Date.now()})},configurable:!1}):console.warn("[Zest] Could not get cookie descriptor"),function(){try{return m=window.localStorage,b=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:w(m,h),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:w(b,y),configurable:!0,writable:!1}),!0}catch(t){return console.warn("[Zest] Could not intercept storage APIs:",t),!1}}(),M(dt.mode,dt.blockedDomains);const n=X();lt=!0,nt()&&T(n,dt,!1);let e=!1;if(q()&&dt.respectDNT&&"ignore"!==dt.dntBehavior&&"reject"===dt.dntBehavior&&!nt()){const t=tt(dt.expiration);e=!0,T(t.current,dt,!1),st(t.current),rt(t.current,t.previous),i(dt.callbacks?.onReject),i(dt.callbacks?.onChange,t.current)}return function(t){ot(et.READY,{consent:t})}(n),i(dt.callbacks?.onReady,n),{alreadyInitialized:!1,config:dt,consent:n,hasDecision:nt(),dntApplied:e}}function gt(){if(!lt)return null;const t=function(t=365){return K({functional:!0,analytics:!0,marketing:!0},t)}(dt.expiration);return T(t.current,dt,!1),pt(O()),at(t.current,t.previous),rt(t.current,t.previous),i(dt.callbacks?.onAccept,t.current),i(dt.callbacks?.onChange,t.current),t}function mt(){G(`${H}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax${F()}`),B=null}function bt(){return lt}function ht(){return dt}const yt="#4F46E5";function zt(t){const n=function(t){if("string"!=typeof t)return null;const n=t.trim();return/^#[0-9a-fA-F]{3,8}$/.test(n)||e.has(n.toLowerCase())||/^(rgb|rgba|hsl|hsla)\(\s*[\d.,%\s/]+\s*\)$/i.test(n)?n:null}(t.accentColor)||yt,o=function(t){if("string"!=typeof t||0===t.length)return"";if(t.length>2e4)return"";let n=t.replace(/\/\*[\s\S]*?\*\//g,"");return n=n.replace(/@import\s+[^;]+;?/gi,""),n=n.replace(/@charset\s+[^;]+;?/gi,""),n=n.replace(/url\(\s*(['"]?)([^)'"]+)\1\s*\)/gi,(t,n,e)=>{const o=e.trim().toLowerCase();return o.startsWith("https:")||o.startsWith("data:image/")||o.startsWith("/")||o.startsWith("#")?t:"url(#)"}),n=n.replace(/\.zest-btn--secondary\s*\{[^}]*\}/gi,""),n=n.replace(/\[data-action\s*=\s*["']reject-all["']\]\s*\{[^}]*\}/gi,""),n=n.replace(/\[data-action\s*=\s*["']accept-all["']\]\s*\{[^}]*\}/gi,""),n=n.replace(/expression\s*\([^)]*\)/gi,""),n=n.replace(/-moz-binding\s*:[^;}]*/gi,""),n}(t.customStyles);return`\n:host {\n --zest-accent: ${n};\n --zest-accent-hover: ${function(t,n){"string"==typeof t&&/^#[0-9a-fA-F]{3,8}$/.test(t.trim())||(t=yt);let e=t.trim().replace("#","");3===e.length&&(e=e.split("").map(t=>t+t).join(""));8===e.length&&(e=e.slice(0,6));6!==e.length&&(e="4F46E5");const o=parseInt(e,16),a=Math.round(2.55*n);return"#"+(16777216+65536*Math.min(255,Math.max(0,(o>>16)+a))+256*Math.min(255,Math.max(0,(o>>8&255)+a))+Math.min(255,Math.max(0,(255&o)+a))).toString(16).slice(1)}(n,-15)};\n --zest-bg: #ffffff;\n --zest-bg-secondary: #f3f4f6;\n --zest-text: #1f2937;\n --zest-text-secondary: #6b7280;\n --zest-border: #e5e7eb;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n --zest-radius: 12px;\n --zest-radius-sm: 8px;\n --zest-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n\n font-family: var(--zest-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--zest-text);\n box-sizing: border-box;\n}\n\n:host([data-theme="dark"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n}\n\n@media (prefers-color-scheme: dark) {\n :host([data-theme="auto"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n }\n}\n\n*, *::before, *::after {\n box-sizing: border-box;\n}\n\n/* Banner */\n.zest-banner {\n position: fixed;\n z-index: 999999;\n max-width: 480px;\n padding: 20px;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-slide-in 0.3s ease-out;\n}\n\n.zest-banner--bottom {\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.zest-banner--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.zest-banner--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.zest-banner--top {\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n@keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n.zest-banner--bottom-left {\n animation-name: zest-slide-in-left;\n}\n\n@keyframes zest-slide-in-left {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.zest-banner--bottom-right {\n animation-name: zest-slide-in-right;\n}\n\n@keyframes zest-slide-in-right {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .zest-banner,\n .zest-modal {\n animation: none;\n }\n}\n\n.zest-banner__title {\n margin: 0 0 8px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-banner__description {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-banner__buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* Buttons */\n.zest-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--zest-radius-sm);\n cursor: pointer;\n transition: background-color 0.15s ease, transform 0.1s ease;\n}\n\n.zest-btn:hover {\n transform: translateY(-1px);\n}\n\n.zest-btn:active {\n transform: translateY(0);\n}\n\n.zest-btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-btn--primary {\n background: var(--zest-accent);\n color: #ffffff;\n}\n\n.zest-btn--primary:hover {\n background: var(--zest-accent-hover);\n}\n\n.zest-btn--secondary {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n.zest-btn--secondary:hover {\n background: var(--zest-border);\n}\n\n.zest-btn--ghost {\n background: transparent;\n color: var(--zest-text-secondary);\n}\n\n.zest-btn--ghost:hover {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n/* Modal */\n.zest-modal-overlay {\n position: fixed;\n inset: 0;\n z-index: 999998;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n background: rgba(0, 0, 0, 0.5);\n animation: zest-fade-in 0.2s ease-out;\n}\n\n@keyframes zest-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.zest-modal {\n width: 100%;\n max-width: 500px;\n max-height: 90vh;\n overflow-y: auto;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-modal-in 0.3s ease-out;\n}\n\n@keyframes zest-modal-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n.zest-modal__header {\n padding: 20px 20px 0;\n}\n\n.zest-modal__title {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-modal__description {\n margin: 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-modal__body {\n padding: 20px;\n}\n\n.zest-modal__footer {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 0 20px 20px;\n}\n\n/* Categories */\n.zest-category {\n padding: 16px;\n margin-bottom: 12px;\n background: var(--zest-bg-secondary);\n border-radius: var(--zest-radius-sm);\n}\n\n.zest-category:last-child {\n margin-bottom: 0;\n}\n\n.zest-category__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.zest-category__info {\n flex: 1;\n}\n\n.zest-category__label {\n display: block;\n font-size: 14px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-category__description {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--zest-text-secondary);\n}\n\n/* Toggle Switch */\n.zest-toggle {\n position: relative;\n width: 44px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.zest-toggle__input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n}\n\n.zest-toggle__input:disabled {\n cursor: not-allowed;\n}\n\n.zest-toggle__slider {\n position: absolute;\n inset: 0;\n background: var(--zest-border);\n border-radius: 12px;\n transition: background-color 0.2s ease;\n pointer-events: none;\n}\n\n.zest-toggle__slider::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 20px;\n height: 20px;\n background: #ffffff;\n border-radius: 50%;\n transition: transform 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider {\n background: var(--zest-accent);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider::before {\n transform: translateX(20px);\n}\n\n.zest-toggle__input:focus-visible + .zest-toggle__slider {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-toggle__input:disabled + .zest-toggle__slider {\n opacity: 0.6;\n}\n\n/* Widget */\n.zest-widget {\n position: fixed;\n z-index: 999997;\n bottom: 20px;\n left: 20px;\n}\n\n.zest-widget__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n padding: 0;\n background: var(--zest-bg);\n border: 1px solid var(--zest-border);\n border-radius: 50%;\n box-shadow: var(--zest-shadow);\n cursor: pointer;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.zest-widget__btn:hover {\n transform: scale(1.05);\n box-shadow: 0 12px 28px -5px rgba(0, 0, 0, 0.15);\n}\n\n.zest-widget__btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-widget__icon {\n width: 24px;\n height: 24px;\n fill: var(--zest-text);\n}\n\n/* Link */\n.zest-link {\n color: var(--zest-accent);\n text-decoration: none;\n}\n\n.zest-link:hover {\n text-decoration: underline;\n}\n\n/* Mobile */\n@media (max-width: 480px) {\n .zest-banner {\n left: 10px;\n right: 10px;\n max-width: none;\n transform: none;\n }\n\n .zest-banner--bottom,\n .zest-banner--bottom-left,\n .zest-banner--bottom-right {\n bottom: 10px;\n }\n\n .zest-banner--top {\n top: 10px;\n transform: none;\n }\n\n @keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .zest-banner__buttons {\n flex-direction: column;\n }\n\n .zest-btn {\n width: 100%;\n }\n\n .zest-modal-overlay {\n padding: 10px;\n }\n\n .zest-widget {\n bottom: 10px;\n left: 10px;\n }\n}\n\n/* Hidden utility */\n.zest-hidden {\n display: none !important;\n}\n${o}\n`}let wt=null,xt=null;const vt=new Set(["bottom","bottom-left","bottom-right","top"]);function kt(t={}){if(wt)return wt;const e=Y();wt=document.createElement("zest-banner"),wt.setAttribute("data-theme",e.theme||"light"),xt=wt.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=zt(e),xt.appendChild(o);const a=document.createElement("div");a.innerHTML=function(t){const e=t.labels.banner,o=t.position||"bottom";return`\n <div class="zest-banner zest-banner--${vt.has(o)?o:"bottom"}" role="dialog" aria-modal="false" aria-label="${n(e.title)}">\n <h2 class="zest-banner__title">${n(e.title)}</h2>\n <p class="zest-banner__description">${n(e.description)}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${n(e.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${n(e.rejectAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${n(e.settings)}\n </button>\n </div>\n </div>\n `}(e),xt.appendChild(a.firstElementChild);const s=xt.querySelector(".zest-banner");return s.addEventListener("click",n=>{const e=n.target.dataset.action;if(e)switch(e){case"accept-all":t.onAcceptAll?.();break;case"reject-all":t.onRejectAll?.();break;case"settings":t.onSettings?.()}}),s.addEventListener("keydown",n=>{"Escape"===n.key&&t.onSettings?.()}),document.body.appendChild(wt),requestAnimationFrame(()=>{const t=xt.querySelector("button");t?.focus()}),wt}function _t(t={}){wt?wt.classList.remove("zest-hidden"):kt(t)}function At(){wt&&(wt.remove(),wt=null,xt=null)}let Ct=null,St=null,jt={};function Et(t,e){const o=t.labels.modal,a=Object.values(t.categories||D).map(t=>function(t,e,o){const a=o?"disabled":"",s=e?"checked":"",r=n(t.id),i=n(t.label);return`\n <div class="zest-category">\n <div class="zest-category__header">\n <div class="zest-category__info">\n <span class="zest-category__label">${i}</span>\n <p class="zest-category__description">${n(t.description)}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${r}"\n ${s}\n ${a}\n aria-label="${i}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `}(t,e[t.id]??t.default,t.required)).join(""),s=t.policyUrl?function(t){if("string"!=typeof t||0===t.length)return null;const n=t.trim();if(0===n.length)return null;if(/^[/?#]/.test(n))return n;const e=n.match(/^([a-z][a-z0-9+.-]*):/i);if(!e)return n;const o=e[1].toLowerCase();return"http"===o||"https"===o||"mailto"===o||"tel"===o?n:null}(t.policyUrl):null,r=s?`<a href="${n(s)}" class="zest-link" target="_blank" rel="noopener noreferrer">Privacy Policy</a>`:"";return`\n <div class="zest-modal-overlay" role="dialog" aria-modal="true" aria-label="${n(o.title)}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${n(o.title)}</h2>\n <p class="zest-modal__description">${n(o.description)} ${r}</p>\n </div>\n <div class="zest-modal__body">\n ${a}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${n(o.save)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${n(o.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${n(o.rejectAll)}\n </button>\n </div>\n </div>\n </div>\n `}function $t(){if(!St)return jt;const t=St.querySelectorAll(".zest-toggle__input"),n={essential:!0};return t.forEach(t=>{const e=t.dataset.category;e&&"essential"!==e&&(n[e]=t.checked)}),n}function Nt(){Ct&&(Ct.remove(),Ct=null,St=null)}let Rt=null,Lt=null;function Mt(t={}){if(Rt)return Rt;const e=Y();Rt=document.createElement("zest-widget"),Rt.setAttribute("data-theme",e.theme||"light"),Lt=Rt.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=zt(e),Lt.appendChild(o);const a=document.createElement("div");a.innerHTML=function(t){const e=n(t.labels.widget.label);return`\n <div class="zest-widget">\n <button type="button" class="zest-widget__btn" aria-label="${e}" title="${e}">\n <span class="zest-widget__icon"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10c0-.728-.078-1.437-.225-2.12a1 1 0 0 0-1.482-.63 3 3 0 0 1-4.086-3.72 1 1 0 0 0-.793-1.263A10.05 10.05 0 0 0 12 2zm0 2c.178 0 .354.006.528.017a5 5 0 0 0 5.955 5.955c.011.174.017.35.017.528 0 4.418-3.582 8-8 8s-8-3.582-8-8 3.582-8 8-8zm-4 6a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm5 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-2 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"/></svg></span>\n </button>\n </div>\n `}(e),Lt.appendChild(a.firstElementChild);return Lt.querySelector(".zest-widget__btn").addEventListener("click",()=>{t.onClick?.()}),document.body.appendChild(Rt),Rt}function Dt(t={}){Rt?Rt.style.display="":Mt(t)}function Ot(){Rt&&(Rt.style.display="none")}function qt(){gt();const t=ht();At(),Nt(),t?.showWidget&&Dt({onClick:It})}function Tt(){!function(){if(!lt)return null;const t=tt(dt.expiration);T(t.current,dt,!1),st(t.current),rt(t.current,t.previous),i(dt.callbacks?.onReject),i(dt.callbacks?.onChange,t.current)}();const t=ht();At(),Nt(),t?.showWidget&&Dt({onClick:It})}function Wt(t){!function(t){if(!lt)return null;const n=K(t,dt.expiration);T(n.current,dt,!1);const e=Object.keys(n.current).filter(t=>n.current[t]&&!n.previous[t]);e.length>0&&pt(e),Object.entries(t||{}).some(([t,n])=>"essential"!==t&&n)?at(n.current,n.previous):st(n.current),rt(n.current,n.previous),i(dt.callbacks?.onChange,n.current)}(t);const n=ht();Nt(),n?.showWidget&&Dt({onClick:It})}function It(){At(),Ot(),function(t={},n={}){if(Ct)return Ct;const e=Y();jt={...t},Ct=document.createElement("zest-modal"),Ct.setAttribute("data-theme",e.theme||"light"),St=Ct.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=zt(e),St.appendChild(o);const a=document.createElement("div");a.innerHTML=Et(e,t),St.appendChild(a.firstElementChild);const s=St.querySelector(".zest-modal-overlay");s.addEventListener("click",t=>{const e=t.target.dataset.action;if(e)switch(e){case"save":n.onSave?.($t());break;case"accept-all":n.onAcceptAll?.();break;case"reject-all":n.onRejectAll?.()}else t.target===s&&n.onClose?.()}),s.addEventListener("keydown",t=>{"Escape"===t.key&&n.onClose?.()}),St.querySelectorAll(".zest-toggle__input").forEach(t=>{t.addEventListener("change",()=>{jt=$t()})}),document.body.appendChild(Ct),requestAnimationFrame(()=>{const t=St.querySelector("button");t?.focus()})}(V(),{onSave:Wt,onAcceptAll:qt,onRejectAll:Tt,onClose:Ut}),it("modal")}function Ut(){Nt(),ct("modal");const t=ht();nt()&&t?.showWidget?Dt({onClick:It}):_t({onAcceptAll:qt,onRejectAll:Tt,onSettings:It})}function Zt(t={}){const{alreadyInitialized:n,hasDecision:e,dntApplied:o}=ft(t);if(n)return console.warn("[Zest] Already initialized"),Pt;const a=ht();return e||o?a?.showWidget&&Dt({onClick:It}):(_t({onAcceptAll:qt,onRejectAll:Tt,onSettings:It}),it("banner")),Pt}const Pt={init:Zt,show(){bt()?(Nt(),Ot(),_t({onAcceptAll:qt,onRejectAll:Tt,onSettings:It}),it("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){At(),ct("banner")},showSettings(){bt()?It():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){Nt(),ct("modal")},getConsent:V,hasConsent:Q,hasConsentDecision:nt,getConsentProof:function(){try{const t=J().match(RegExp(H+"=([^;]+)"));if(t){return r(JSON.parse(decodeURIComponent(t[1])),O())}}catch(t){}return null},isDoNotTrackEnabled:q,getDNTDetails:function(){if("undefined"==typeof navigator)return{enabled:!1,source:null};const t=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===t||"yes"===t||!0===t?{enabled:!0,source:"dnt"}:!0===navigator.globalPrivacyControl?{enabled:!0,source:"gpc"}:{enabled:!1,source:null}},acceptAll(){bt()?qt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){bt()?Tt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){mt(),Nt(),Rt&&(Rt.remove(),Rt=null,Lt=null),bt()&&(_t({onAcceptAll:qt,onRejectAll:Tt,onSettings:It}),it("banner"))},getConfig:Y,on:function(t,n){return document.addEventListener(t,n),()=>document.removeEventListener(t,n)},once:function(t,n){document.addEventListener(t,n,{once:!0})},EVENTS:et};if("undefined"!=typeof window){try{Object.defineProperty(window,"Zest",{value:Object.freeze(Pt),writable:!1,configurable:!1,enumerable:!0})}catch(t){window.Zest=Pt}const t=()=>{!1!==Z().autoInit&&Zt(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}return Pt}();
|
|
1
|
+
var Zest=function(){"use strict";const t={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};function e(e){if(null==e)return"";return("string"==typeof e?e:e+"").replace(/[&<>"'`]/g,e=>t[e])}const n=new Set(["transparent","black","white","red","green","blue","yellow","orange","purple","pink","gray","grey","brown","cyan","magenta","silver","gold","navy","teal","maroon","olive","lime","aqua","fuchsia","indigo","violet","crimson","coral","salmon","tomato"]);const o=[/(\([^)]*[+*][^)]*\)|\[[^\]]*\]|\\w|\\d|\\s)\s*[+*]/,/\(\?[=!][^)]*[+*][^)]*\)[+*]/];function a(t,e){if(t instanceof RegExp)return t;if("string"!=typeof t)return null;if(t.length>500)return null;for(const e of o)if(e.test(t))return null;try{return RegExp(t,e)}catch(t){return null}}const s=new Set(["__proto__","constructor","prototype"]);function r(t,e){if(!t||"object"!=typeof t||Array.isArray(t))return null;const n={version:"string"==typeof t.version?t.version:null,timestamp:"number"==typeof t.timestamp&&Number.isFinite(t.timestamp)?t.timestamp:null,categories:{}},o=t.categories;if(!o||"object"!=typeof o||Array.isArray(o))return null;for(const t of e)s.has(t)||Object.prototype.hasOwnProperty.call(o,t)&&(n.categories[t]=!0===o[t]);return e.includes("essential")&&(n.categories.essential=!0),n}function i(t,...e){if("function"==typeof t)try{return t(...e)}catch(t){try{console.error("[Zest] User callback threw:",t)}catch(t){}return}}const c={essential:[/^zest_/,/^csrf/i,/^xsrf/i,/^session/i,/^__host-/i,/^__secure-/i],functional:[/^lang/i,/^locale/i,/^theme/i,/^preferences/i,/^ui_/i],analytics:[/^_ga/,/^_gid/,/^_gat/,/^_utm/,/^__utm/,/^plausible/i,/^_pk_/,/^matomo/i,/^_hj/,/^ajs_/],marketing:[/^_fbp/,/^_fbc/,/^_gcl/,/^_ttp/,/^ads/i,/^doubleclick/i,/^__gads/,/^__gpi/,/^_pin_/,/^li_/]};let l={...c};function d(t){return(t+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function u(t){for(const[e,n]of Object.entries(l))if(n.some(e=>e.test(t)))return e;return"marketing"}let p=null;const f=[];let g=()=>!1;function m(){return p}let b=null,y=null;const h=[],z=[];let w=()=>!1;function x(t,e,n){return new Proxy(t,{get(t,n){if("setItem"===n)return(n,o)=>{const a=u(n);w(a)?t.setItem(n,o):200>e.length&&e.push({key:n,value:o,category:a,timestamp:Date.now()})};const o=t[n];return"function"==typeof o?o.bind(t):o}})}const v={analytics:["google-analytics.com","www.google-analytics.com","analytics.google.com","googletagmanager.com","www.googletagmanager.com","plausible.io","cloudflareinsights.com","static.cloudflareinsights.com"],marketing:["connect.facebook.net","www.facebook.com/tr","ads.google.com","www.googleadservices.com","googleads.g.doubleclick.net","pagead2.googlesyndication.com"]},k={analytics:[...v.analytics,"analytics.tiktok.com","matomo.","hotjar.com","static.hotjar.com","script.hotjar.com","clarity.ms","www.clarity.ms","heapanalytics.com","cdn.heapanalytics.com","mixpanel.com","cdn.mxpnl.com","segment.com","cdn.segment.com","api.segment.io","fullstory.com","rs.fullstory.com","amplitude.com","cdn.amplitude.com","mouseflow.com","cdn.mouseflow.com","luckyorange.com","cdn.luckyorange.net","crazyegg.com","script.crazyegg.com"],marketing:[...v.marketing,"snap.licdn.com","px.ads.linkedin.com","ads.linkedin.com","analytics.twitter.com","static.ads-twitter.com","t.co","analytics.tiktok.com","ads.tiktok.com","sc-static.net","tr.snapchat.com","ct.pinterest.com","pintrk.com","s.pinimg.com","widgets.pinterest.com","bat.bing.com","ads.yahoo.com","sp.analytics.yahoo.com","amazon-adsystem.com","z-na.amazon-adsystem.com","criteo.com","static.criteo.net","dis.criteo.com","taboola.com","cdn.taboola.com","trc.taboola.com","outbrain.com","widgets.outbrain.com","adroll.com","s.adroll.com"],functional:["cdn.onesignal.com","onesignal.com","pusher.com","js.pusher.com","intercom.io","widget.intercom.io","js.intercomcdn.com","crisp.chat","client.crisp.chat","cdn.livechatinc.com","livechatinc.com","tawk.to","embed.tawk.to","zendesk.com","static.zdassets.com"]};function _(t,e){let n;try{n=new URL(t)}catch(t){return!1}const o=n.hostname.toLowerCase(),a=n.pathname.toLowerCase();for(const t of e){if("string"!=typeof t)continue;const e=t.toLowerCase();if(e.endsWith(".")){const t=e.slice(0,-1);if(o.split(".").some(e=>e===t)||o.startsWith(e))return!0;continue}const n=e.indexOf("/");if(-1!==n){const t=e.slice(0,n),s=e.slice(n);if((o===t||o.endsWith("."+t))&&a.startsWith(s))return!0;continue}if(o===e||o.endsWith("."+e))return!0}return!1}function A(t,e="safe"){const n="strict"===e?k:v;for(const[e,o]of Object.entries(n))if(_(t,o))return e;return null}const C=new Set(["functional","analytics","marketing"]),S=[];let j=null,E="safe",$=[],N=()=>!1;function R(t){if(t.hasAttribute("data-zest-allow"))return null;const e=t.getAttribute("data-consent-category"),n=e&&C.has(e)?e:null,o=t.src;if(!o)return n;const a=function(t){if(!t||0===$.length)return null;try{const e=new URL(t).hostname.toLowerCase();for(const t of $){const n="string"==typeof t?t:t.domain,o="string"==typeof t?"marketing":t.category||"marketing";if(e===n||e.endsWith("."+n))return o}}catch(t){}return null}(o);let s=null;switch(E){case"manual":break;case"safe":case"strict":s=A(o,E);break;case"doomsday":(function(t){try{const e=new URL(t).hostname,n=window.location.hostname,o=t=>t.replace(/^www\./,"");return o(e)!==o(n)}catch(t){return!1}})(o)&&(s=A(o,"strict")||"marketing")}return s||a||n}function L(t){if(t.hasAttribute("data-zest-processed"))return!1;const e=R(t);if(!e)return t.setAttribute("data-zest-processed","allowed"),!1;if(N(e))return t.setAttribute("data-zest-processed","allowed"),!1;const n={category:e,src:t.src||"",inline:t.textContent,type:t.type,async:t.async,defer:t.defer,element:t,timestamp:Date.now()};return t.setAttribute("data-zest-processed","blocked"),t.setAttribute("data-consent-category",e),t.type="text/plain",t.src&&t.removeAttribute("src"),500>S.length&&S.push(n),!0}function M(t){for(const e of t)for(const t of e.addedNodes)if("SCRIPT"!==t.nodeName||t.hasAttribute("data-zest-processed")||L(t),t.querySelectorAll){t.querySelectorAll("script:not([data-zest-processed])").forEach(L)}}function D(t="safe",e=[]){return E=t,$=e,document.querySelectorAll("script:not([data-zest-processed])").forEach(L),j=new MutationObserver(M),j.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const O={essential:{id:"essential",label:"Essential",description:"Required for the website to function properly. Cannot be disabled.",required:!0,default:!0},functional:{id:"functional",label:"Functional",description:"Enable personalized features like language preferences and themes.",required:!1,default:!1},analytics:{id:"analytics",label:"Analytics",description:"Help us understand how visitors interact with our website.",required:!1,default:!1},marketing:{id:"marketing",label:"Marketing",description:"Used to deliver relevant advertisements and track campaign performance.",required:!1,default:!1}};function q(){return Object.keys(O)}function P(){if("undefined"==typeof navigator)return!1;const t=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===t||"yes"===t||!0===t||!0===navigator.globalPrivacyControl}function T(t,e,n){const o=n?"default":"update";e.consentModeGoogle&&function(t,e){if(window.dataLayer=window.dataLayer||[],"function"==typeof window.gtag)window.gtag("consent",t,e);else{function n(){window.dataLayer.push(arguments)}n("consent",t,e)}}(o,function(t){const e=t=>t?"granted":"denied";return{ad_storage:e(t.marketing),ad_user_data:e(t.marketing),ad_personalization:e(t.marketing),analytics_storage:e(t.analytics),functionality_storage:"granted",personalization_storage:e(t.functional)}}(t)),e.consentModeMicrosoft&&function(t,e){window.uetq=window.uetq||[],window.uetq.push("consent",t,e)}(o,function(t){return{ad_storage:t.marketing?"granted":"denied"}}(t))}const W={labels:{banner:{title:"Valorizamos sua privacidade",description:'Usamos cookies para melhorar sua experiência de navegação, fornecer conteúdo personalizado e analisar nosso tráfego. Ao clicar em "Aceitar tudo", você consente com o uso de cookies.',acceptAll:"Aceitar tudo",rejectAll:"Rejeitar tudo",settings:"Configurações"},modal:{title:"Configurações de privacidade",description:"Gerencie suas preferências de cookies. Você pode ativar ou desativar diferentes tipos de cookies abaixo.",save:"Salvar preferências",acceptAll:"Aceitar tudo",rejectAll:"Rejeitar tudo"},widget:{label:"Configurações de cookies"}},categories:{essential:{label:"Essenciais",description:"Necessários para o funcionamento do site. Não podem ser desativados."},functional:{label:"Funcionais",description:"Permitem recursos personalizados como preferências de idioma e tema."},analytics:{label:"Analíticos",description:"Nos ajudam a entender como os visitantes interagem com nosso site."},marketing:{label:"Marketing",description:"Usados para exibir anúncios relevantes e medir o desempenho de campanhas."}}};const I={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:O,labels:{banner:{title:"We value your privacy",description:'We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies.',acceptAll:"Accept All",rejectAll:"Reject All",settings:"Settings"},modal:{title:"Privacy Settings",description:"Manage your cookie preferences. You can enable or disable different types of cookies below.",save:"Save Preferences",acceptAll:"Accept All",rejectAll:"Reject All"},widget:{label:"Cookie Settings"}},autoInit:!0,showWidget:!0,expiration:365,respectDNT:!0,dntBehavior:"reject",customStyles:"",consentModeGoogle:!1,consentModeMicrosoft:!1,mode:"safe",intercept:{cookies:!0,storage:!0,scripts:!0},essentialKeys:[],essentialPatterns:[],blockedDomains:[],policyUrl:null,imprintUrl:null,callbacks:{onAccept:null,onReject:null,onChange:null,onReady:null}};function U(t){const e={...I};t||(t={});const n=["lang","position","theme","accentColor","autoInit","showWidget","expiration","policyUrl","imprintUrl","customStyles","mode","blockedDomains","respectDNT","dntBehavior","consentModeGoogle","consentModeMicrosoft"];for(const o of n)void 0!==t[o]&&(e[o]=t[o]);e.lang="pt";const o=W,a=o.labels||{},s=t.labels||{};e.labels={banner:{...I.labels.banner,...a.banner,...s.banner},modal:{...I.labels.modal,...a.modal,...s.modal},widget:{...I.labels.widget,...a.widget,...s.widget}};const r=o.categories||{},i=t.categories||{};e.categories={...I.categories};for(const t of Object.keys(I.categories))e.categories[t]={...I.categories[t],...r[t],...i[t]};return t.callbacks&&(e.callbacks={...I.callbacks,...t.callbacks}),t.patterns&&(e.patterns=t.patterns),t.intercept&&"object"==typeof t.intercept&&(e.intercept={...I.intercept,...t.intercept}),Array.isArray(t.essentialKeys)&&(e.essentialKeys=t.essentialKeys.filter(t=>"string"==typeof t&&t.length>0&&200>=t.length)),Array.isArray(t.essentialPatterns)&&(e.essentialPatterns=t.essentialPatterns.filter(t=>"string"==typeof t&&t.length>0&&500>=t.length)),e}function Z(){const t="undefined"!=typeof window&&window.ZestConfig?window.ZestConfig:{},e=function(){const t=document.currentScript||document.querySelector("script[data-zest]")||document.querySelector('script[src*="zest"]');if(!t)return{};const e={},n=t.getAttribute("data-position");n&&(e.position=n);const o=t.getAttribute("data-theme");o&&(e.theme=o);const a=t.getAttribute("data-accent")||t.getAttribute("data-accent-color");a&&(e.accentColor=a);const s=t.getAttribute("data-policy-url")||t.getAttribute("data-privacy-url");s&&(e.policyUrl=s);const r=t.getAttribute("data-imprint-url");r&&(e.imprintUrl=r);const i=t.getAttribute("data-show-widget");null!==i&&(e.showWidget="false"!==i);const c=t.getAttribute("data-auto-init");null!==c&&(e.autoInit="false"!==c);const l=t.getAttribute("data-expiration");l&&(e.expiration=parseInt(l,10));const d=t.getAttribute("data-consent-mode-google");null!==d&&(e.consentModeGoogle="false"!==d);const u=t.getAttribute("data-consent-mode-microsoft");return null!==u&&(e.consentModeMicrosoft="false"!==u),e}();return U({...t,...e})}let Y=null;function H(){return Y||(Y=Z()),Y}const F="zest_consent";function B(){try{return"undefined"!=typeof location&&"https:"===location.protocol?"; Secure":""}catch(t){return""}}let G=null;function K(t){const e=m();e?.set?e.set.call(document,t):document.cookie=t}function J(){const t=m();return t?.get?t.get.call(document):document.cookie}function X(){try{const t=J().match(RegExp(F+"=([^;]+)"));if(t){const e=r(JSON.parse(decodeURIComponent(t[1])),q());if(e&&e.categories)return G={essential:!0,functional:!1,analytics:!1,marketing:!1,...e.categories},{...G}}}catch(t){}return G={essential:!0,functional:!1,analytics:!1,marketing:!1},{...G}}function V(){return G||(G=X()),{...G}}function Q(t,e=365){const n=G?{...G}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return G={essential:!0,functional:!!t.functional,analytics:!!t.analytics,marketing:!!t.marketing},function(t=365){G||(G={essential:!0,functional:!1,analytics:!1,marketing:!1});const e={version:"1.0",timestamp:Date.now(),categories:G},n=new Date(Date.now()+24*t*60*60*1e3).toUTCString();K(`${F}=${encodeURIComponent(JSON.stringify(e))}; expires=${n}; path=/; SameSite=Lax${B()}`)}(e),{current:{...G},previous:n}}function tt(t){return G||(G=X()),!0===G[t]}function et(t=365){return Q({functional:!1,analytics:!1,marketing:!1},t)}function nt(){try{return J().includes(F)}catch(t){return!1}}const ot={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function at(t,e={}){const n=new CustomEvent(t,{detail:e,bubbles:!0,cancelable:!0});return document.dispatchEvent(n),n}function st(t,e){return at(ot.CONSENT,{consent:t,previous:e})}function rt(t){return at(ot.REJECT,{consent:t})}function it(t,e){return at(ot.CHANGE,{consent:t,previous:e})}function ct(t="banner"){return at(ot.SHOW,{type:t})}function lt(t="banner"){return at(ot.HIDE,{type:t})}let dt=!1,ut=null;function pt(t){return tt(t)}function ft(t){!function(t){const e=[];for(const n of f)t.includes(n.category)?p?.set&&p.set.call(document,n.value):e.push(n);f.length=0,f.push(...e)}(t),function(t){const e=[];for(const n of h)t.includes(n.category)?b?.setItem(n.key,n.value):e.push(n);h.length=0,h.push(...e);const n=[];for(const e of z)t.includes(e.category)?y?.setItem(e.key,e.value):n.push(e);z.length=0,z.push(...n)}(t),function(t){const e=[];for(const n of S){if(!t.includes(n.category)){e.push(n);continue}const o=document.createElement("script");n.src?o.src=n.src:n.inline&&(o.textContent=n.inline),n.async&&(o.async=!0),n.defer&&(o.defer=!0),n.type&&"text/plain"!==n.type&&(o.type=n.type),o.setAttribute("data-zest-processed","executed"),o.setAttribute("data-consent-executed","true");const a=n.element;a&&a.isConnected&&a.parentNode?a.parentNode.replaceChild(o,a):document.head.appendChild(o)}S.length=0,S.push(...e)}(t)}function gt(t={}){if(dt)return{alreadyInitialized:!0,config:ut,consent:X(),hasDecision:nt(),dntApplied:!1};Y=U(t),ut=Y,T({functional:!1,analytics:!1,marketing:!1},ut,!0),ut.patterns&&function(t){if(l={...c},t&&"object"==typeof t)for(const[e,n]of Object.entries(t)){if(!Array.isArray(n))continue;const t=[];for(const e of n){const n=a(e);if(n)t.push(n);else try{console.warn("[Zest] Rejected unsafe pattern:",e)}catch(t){}}l[e]=t}}(ut.patterns),(Array.isArray(ut.essentialKeys)&&ut.essentialKeys.length>0||Array.isArray(ut.essentialPatterns)&&ut.essentialPatterns.length>0)&&function(t,{keys:e=[],patternStrings:n=[]}={}){l[t]||(l[t]=[]);for(const n of e){if("string"!=typeof n||!n)continue;const e=a(`^${d(n)}$`);e&&l[t].push(e)}for(const e of n){if("string"!=typeof e||!e)continue;const n=a(e);n&&l[t].push(n)}}("essential",{keys:ut.essentialKeys,patternStrings:ut.essentialPatterns}),g=pt,function(t){w=t}(pt),function(t){N=t}(pt);const e=ut.intercept||{cookies:!0,storage:!0,scripts:!0};!1!==e.cookies&&(p=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),p?Object.defineProperty(document,"cookie",{get:()=>p.get.call(document),set(t){const e=function(t){const e=t.match(/^([^=]+)/);return e?e[1].trim():null}(t);if(!e)return;const n=u(e);g(n)?p.set.call(document,t):100>f.length&&f.push({value:t,name:e,category:n,timestamp:Date.now()})},configurable:!1}):console.warn("[Zest] Could not get cookie descriptor")),!1!==e.storage&&function(){try{return b=window.localStorage,y=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:x(b,h),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:x(y,z),configurable:!0,writable:!1}),!0}catch(t){return console.warn("[Zest] Could not intercept storage APIs:",t),!1}}(),!1!==e.scripts&&D(ut.mode,ut.blockedDomains);const n=X();dt=!0,nt()&&T(n,ut,!1);let o=!1;if(P()&&ut.respectDNT&&"ignore"!==ut.dntBehavior&&"reject"===ut.dntBehavior&&!nt()){const t=et(ut.expiration);o=!0,T(t.current,ut,!1),rt(t.current),it(t.current,t.previous),i(ut.callbacks?.onReject),i(ut.callbacks?.onChange,t.current)}return function(t){at(ot.READY,{consent:t})}(n),i(ut.callbacks?.onReady,n),{alreadyInitialized:!1,config:ut,consent:n,hasDecision:nt(),dntApplied:o}}function mt(){if(!dt)return null;const t=function(t=365){return Q({functional:!0,analytics:!0,marketing:!0},t)}(ut.expiration);return T(t.current,ut,!1),ft(q()),st(t.current,t.previous),it(t.current,t.previous),i(ut.callbacks?.onAccept,t.current),i(ut.callbacks?.onChange,t.current),t}function bt(){K(`${F}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax${B()}`),G=null}function yt(){return dt}function ht(){return ut}const zt="#4F46E5";function wt(t){const e=function(t){if("string"!=typeof t)return null;const e=t.trim();return/^#[0-9a-fA-F]{3,8}$/.test(e)||n.has(e.toLowerCase())||/^(rgb|rgba|hsl|hsla)\(\s*[\d.,%\s/]+\s*\)$/i.test(e)?e:null}(t.accentColor)||zt,o=function(t){if("string"!=typeof t||0===t.length)return"";if(t.length>2e4)return"";let e=t.replace(/\/\*[\s\S]*?\*\//g,"");return e=e.replace(/@import\s+[^;]+;?/gi,""),e=e.replace(/@charset\s+[^;]+;?/gi,""),e=e.replace(/url\(\s*(['"]?)([^)'"]+)\1\s*\)/gi,(t,e,n)=>{const o=n.trim().toLowerCase();return o.startsWith("https:")||o.startsWith("data:image/")||o.startsWith("/")||o.startsWith("#")?t:"url(#)"}),e=e.replace(/\.zest-btn--secondary\s*\{[^}]*\}/gi,""),e=e.replace(/\[data-action\s*=\s*["']reject-all["']\]\s*\{[^}]*\}/gi,""),e=e.replace(/\[data-action\s*=\s*["']accept-all["']\]\s*\{[^}]*\}/gi,""),e=e.replace(/expression\s*\([^)]*\)/gi,""),e=e.replace(/-moz-binding\s*:[^;}]*/gi,""),e}(t.customStyles);return`\n:host {\n --zest-accent: ${e};\n --zest-accent-hover: ${function(t,e){"string"==typeof t&&/^#[0-9a-fA-F]{3,8}$/.test(t.trim())||(t=zt);let n=t.trim().replace("#","");3===n.length&&(n=n.split("").map(t=>t+t).join(""));8===n.length&&(n=n.slice(0,6));6!==n.length&&(n="4F46E5");const o=parseInt(n,16),a=Math.round(2.55*e);return"#"+(16777216+65536*Math.min(255,Math.max(0,(o>>16)+a))+256*Math.min(255,Math.max(0,(o>>8&255)+a))+Math.min(255,Math.max(0,(255&o)+a))).toString(16).slice(1)}(e,-15)};\n --zest-bg: #ffffff;\n --zest-bg-secondary: #f3f4f6;\n --zest-text: #1f2937;\n --zest-text-secondary: #6b7280;\n --zest-border: #e5e7eb;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n --zest-radius: 12px;\n --zest-radius-sm: 8px;\n --zest-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n\n font-family: var(--zest-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--zest-text);\n box-sizing: border-box;\n}\n\n:host([data-theme="dark"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n}\n\n@media (prefers-color-scheme: dark) {\n :host([data-theme="auto"]) {\n --zest-bg: #1f2937;\n --zest-bg-secondary: #374151;\n --zest-text: #f9fafb;\n --zest-text-secondary: #9ca3af;\n --zest-border: #4b5563;\n --zest-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.4), 0 8px 10px -6px rgba(0, 0, 0, 0.3);\n }\n}\n\n*, *::before, *::after {\n box-sizing: border-box;\n}\n\n/* Banner */\n.zest-banner {\n position: fixed;\n z-index: 999999;\n max-width: 480px;\n padding: 20px;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-slide-in 0.3s ease-out;\n}\n\n.zest-banner--bottom {\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.zest-banner--bottom-left {\n bottom: 20px;\n left: 20px;\n}\n\n.zest-banner--bottom-right {\n bottom: 20px;\n right: 20px;\n}\n\n.zest-banner--top {\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n@keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n.zest-banner--bottom-left {\n animation-name: zest-slide-in-left;\n}\n\n@keyframes zest-slide-in-left {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.zest-banner--bottom-right {\n animation-name: zest-slide-in-right;\n}\n\n@keyframes zest-slide-in-right {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .zest-banner,\n .zest-modal {\n animation: none;\n }\n}\n\n.zest-banner__title {\n margin: 0 0 8px 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-banner__description {\n margin: 0 0 16px 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-banner__buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* Buttons */\n.zest-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n font-family: inherit;\n border: none;\n border-radius: var(--zest-radius-sm);\n cursor: pointer;\n transition: background-color 0.15s ease, transform 0.1s ease;\n}\n\n.zest-btn:hover {\n transform: translateY(-1px);\n}\n\n.zest-btn:active {\n transform: translateY(0);\n}\n\n.zest-btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-btn--primary {\n background: var(--zest-accent);\n color: #ffffff;\n}\n\n.zest-btn--primary:hover {\n background: var(--zest-accent-hover);\n}\n\n.zest-btn--secondary {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n.zest-btn--secondary:hover {\n background: var(--zest-border);\n}\n\n.zest-btn--ghost {\n background: transparent;\n color: var(--zest-text-secondary);\n}\n\n.zest-btn--ghost:hover {\n background: var(--zest-bg-secondary);\n color: var(--zest-text);\n}\n\n/* Modal */\n.zest-modal-overlay {\n position: fixed;\n inset: 0;\n z-index: 999998;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n background: rgba(0, 0, 0, 0.5);\n animation: zest-fade-in 0.2s ease-out;\n}\n\n@keyframes zest-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.zest-modal {\n width: 100%;\n max-width: 500px;\n max-height: 90vh;\n overflow-y: auto;\n background: var(--zest-bg);\n border-radius: var(--zest-radius);\n box-shadow: var(--zest-shadow);\n animation: zest-modal-in 0.3s ease-out;\n}\n\n@keyframes zest-modal-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n.zest-modal__header {\n padding: 20px 20px 0;\n}\n\n.zest-modal__title {\n margin: 0 0 8px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-modal__description {\n margin: 0;\n font-size: 14px;\n color: var(--zest-text-secondary);\n}\n\n.zest-modal__body {\n padding: 20px;\n}\n\n.zest-modal__footer {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n padding: 0 20px 20px;\n}\n\n/* Categories */\n.zest-category {\n padding: 16px;\n margin-bottom: 12px;\n background: var(--zest-bg-secondary);\n border-radius: var(--zest-radius-sm);\n}\n\n.zest-category:last-child {\n margin-bottom: 0;\n}\n\n.zest-category__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.zest-category__info {\n flex: 1;\n}\n\n.zest-category__label {\n display: block;\n font-size: 14px;\n font-weight: 600;\n color: var(--zest-text);\n}\n\n.zest-category__description {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--zest-text-secondary);\n}\n\n/* Toggle Switch */\n.zest-toggle {\n position: relative;\n width: 44px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.zest-toggle__input {\n position: absolute;\n opacity: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n margin: 0;\n}\n\n.zest-toggle__input:disabled {\n cursor: not-allowed;\n}\n\n.zest-toggle__slider {\n position: absolute;\n inset: 0;\n background: var(--zest-border);\n border-radius: 12px;\n transition: background-color 0.2s ease;\n pointer-events: none;\n}\n\n.zest-toggle__slider::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 20px;\n height: 20px;\n background: #ffffff;\n border-radius: 50%;\n transition: transform 0.2s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider {\n background: var(--zest-accent);\n}\n\n.zest-toggle__input:checked + .zest-toggle__slider::before {\n transform: translateX(20px);\n}\n\n.zest-toggle__input:focus-visible + .zest-toggle__slider {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-toggle__input:disabled + .zest-toggle__slider {\n opacity: 0.6;\n}\n\n/* Widget */\n.zest-widget {\n position: fixed;\n z-index: 999997;\n bottom: 20px;\n left: 20px;\n}\n\n.zest-widget__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 48px;\n height: 48px;\n padding: 0;\n background: var(--zest-bg);\n border: 1px solid var(--zest-border);\n border-radius: 50%;\n box-shadow: var(--zest-shadow);\n cursor: pointer;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n\n.zest-widget__btn:hover {\n transform: scale(1.05);\n box-shadow: 0 12px 28px -5px rgba(0, 0, 0, 0.15);\n}\n\n.zest-widget__btn:focus-visible {\n outline: 2px solid var(--zest-accent);\n outline-offset: 2px;\n}\n\n.zest-widget__icon {\n width: 24px;\n height: 24px;\n fill: var(--zest-text);\n}\n\n/* Link */\n.zest-link {\n color: var(--zest-accent);\n text-decoration: none;\n}\n\n.zest-link:hover {\n text-decoration: underline;\n}\n\n/* Mobile */\n@media (max-width: 480px) {\n .zest-banner {\n left: 10px;\n right: 10px;\n max-width: none;\n transform: none;\n }\n\n .zest-banner--bottom,\n .zest-banner--bottom-left,\n .zest-banner--bottom-right {\n bottom: 10px;\n }\n\n .zest-banner--top {\n top: 10px;\n transform: none;\n }\n\n @keyframes zest-slide-in {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .zest-banner__buttons {\n flex-direction: column;\n }\n\n .zest-btn {\n width: 100%;\n }\n\n .zest-modal-overlay {\n padding: 10px;\n }\n\n .zest-widget {\n bottom: 10px;\n left: 10px;\n }\n}\n\n/* Hidden utility */\n.zest-hidden {\n display: none !important;\n}\n${o}\n`}let xt=null,vt=null;const kt=new Set(["bottom","bottom-left","bottom-right","top"]);function _t(t={}){if(xt)return xt;const n=H();xt=document.createElement("zest-banner"),xt.setAttribute("data-theme",n.theme||"light"),vt=xt.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=wt(n),vt.appendChild(o);const a=document.createElement("div");a.innerHTML=function(t){const n=t.labels.banner,o=t.position||"bottom";return`\n <div class="zest-banner zest-banner--${kt.has(o)?o:"bottom"}" role="dialog" aria-modal="false" aria-label="${e(n.title)}">\n <h2 class="zest-banner__title">${e(n.title)}</h2>\n <p class="zest-banner__description">${e(n.description)}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${e(n.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${e(n.rejectAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${e(n.settings)}\n </button>\n </div>\n </div>\n `}(n),vt.appendChild(a.firstElementChild);const s=vt.querySelector(".zest-banner");return s.addEventListener("click",e=>{const n=e.target.dataset.action;if(n)switch(n){case"accept-all":t.onAcceptAll?.();break;case"reject-all":t.onRejectAll?.();break;case"settings":t.onSettings?.()}}),s.addEventListener("keydown",e=>{"Escape"===e.key&&t.onSettings?.()}),document.body.appendChild(xt),requestAnimationFrame(()=>{const t=vt.querySelector("button");t?.focus()}),xt}function At(t={}){xt?xt.classList.remove("zest-hidden"):_t(t)}function Ct(){xt&&(xt.remove(),xt=null,vt=null)}let St=null,jt=null,Et={};function $t(t,n){const o=t.labels.modal,a=Object.values(t.categories||O).map(t=>function(t,n,o){const a=o?"disabled":"",s=n?"checked":"",r=e(t.id),i=e(t.label);return`\n <div class="zest-category">\n <div class="zest-category__header">\n <div class="zest-category__info">\n <span class="zest-category__label">${i}</span>\n <p class="zest-category__description">${e(t.description)}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${r}"\n ${s}\n ${a}\n aria-label="${i}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `}(t,n[t.id]??t.default,t.required)).join(""),s=t.policyUrl?function(t){if("string"!=typeof t||0===t.length)return null;const e=t.trim();if(0===e.length)return null;if(/^[/?#]/.test(e))return e;const n=e.match(/^([a-z][a-z0-9+.-]*):/i);if(!n)return e;const o=n[1].toLowerCase();return"http"===o||"https"===o||"mailto"===o||"tel"===o?e:null}(t.policyUrl):null,r=s?`<a href="${e(s)}" class="zest-link" target="_blank" rel="noopener noreferrer">Privacy Policy</a>`:"";return`\n <div class="zest-modal-overlay" role="dialog" aria-modal="true" aria-label="${e(o.title)}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${e(o.title)}</h2>\n <p class="zest-modal__description">${e(o.description)} ${r}</p>\n </div>\n <div class="zest-modal__body">\n ${a}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${e(o.save)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${e(o.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${e(o.rejectAll)}\n </button>\n </div>\n </div>\n </div>\n `}function Nt(){if(!jt)return Et;const t=jt.querySelectorAll(".zest-toggle__input"),e={essential:!0};return t.forEach(t=>{const n=t.dataset.category;n&&"essential"!==n&&(e[n]=t.checked)}),e}function Rt(){St&&(St.remove(),St=null,jt=null)}let Lt=null,Mt=null;function Dt(t={}){if(Lt)return Lt;const n=H();Lt=document.createElement("zest-widget"),Lt.setAttribute("data-theme",n.theme||"light"),Mt=Lt.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=wt(n),Mt.appendChild(o);const a=document.createElement("div");a.innerHTML=function(t){const n=e(t.labels.widget.label);return`\n <div class="zest-widget">\n <button type="button" class="zest-widget__btn" aria-label="${n}" title="${n}">\n <span class="zest-widget__icon"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10c0-.728-.078-1.437-.225-2.12a1 1 0 0 0-1.482-.63 3 3 0 0 1-4.086-3.72 1 1 0 0 0-.793-1.263A10.05 10.05 0 0 0 12 2zm0 2c.178 0 .354.006.528.017a5 5 0 0 0 5.955 5.955c.011.174.017.35.017.528 0 4.418-3.582 8-8 8s-8-3.582-8-8 3.582-8 8-8zm-4 6a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm5 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-2 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"/></svg></span>\n </button>\n </div>\n `}(n),Mt.appendChild(a.firstElementChild);return Mt.querySelector(".zest-widget__btn").addEventListener("click",()=>{t.onClick?.()}),document.body.appendChild(Lt),Lt}function Ot(t={}){Lt?Lt.style.display="":Dt(t)}function qt(){Lt&&(Lt.style.display="none")}function Pt(){mt();const t=ht();Ct(),Rt(),t?.showWidget&&Ot({onClick:It})}function Tt(){!function(){if(!dt)return null;const t=et(ut.expiration);T(t.current,ut,!1),rt(t.current),it(t.current,t.previous),i(ut.callbacks?.onReject),i(ut.callbacks?.onChange,t.current)}();const t=ht();Ct(),Rt(),t?.showWidget&&Ot({onClick:It})}function Wt(t){!function(t){if(!dt)return null;const e=Q(t,ut.expiration);T(e.current,ut,!1);const n=Object.keys(e.current).filter(t=>e.current[t]&&!e.previous[t]);n.length>0&&ft(n),Object.entries(t||{}).some(([t,e])=>"essential"!==t&&e)?st(e.current,e.previous):rt(e.current),it(e.current,e.previous),i(ut.callbacks?.onChange,e.current)}(t);const e=ht();Rt(),e?.showWidget&&Ot({onClick:It})}function It(){Ct(),qt(),function(t={},e={}){if(St)return St;const n=H();Et={...t},St=document.createElement("zest-modal"),St.setAttribute("data-theme",n.theme||"light"),jt=St.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=wt(n),jt.appendChild(o);const a=document.createElement("div");a.innerHTML=$t(n,t),jt.appendChild(a.firstElementChild);const s=jt.querySelector(".zest-modal-overlay");s.addEventListener("click",t=>{const n=t.target.dataset.action;if(n)switch(n){case"save":e.onSave?.(Nt());break;case"accept-all":e.onAcceptAll?.();break;case"reject-all":e.onRejectAll?.()}else t.target===s&&e.onClose?.()}),s.addEventListener("keydown",t=>{"Escape"===t.key&&e.onClose?.()}),jt.querySelectorAll(".zest-toggle__input").forEach(t=>{t.addEventListener("change",()=>{Et=Nt()})}),document.body.appendChild(St),requestAnimationFrame(()=>{const t=jt.querySelector("button");t?.focus()})}(V(),{onSave:Wt,onAcceptAll:Pt,onRejectAll:Tt,onClose:Ut}),ct("modal")}function Ut(){Rt(),lt("modal");const t=ht();nt()&&t?.showWidget?Ot({onClick:It}):At({onAcceptAll:Pt,onRejectAll:Tt,onSettings:It})}function Zt(t={}){const{alreadyInitialized:e,hasDecision:n,dntApplied:o}=gt(t);if(e)return console.warn("[Zest] Already initialized"),Yt;const a=ht();return n||o?a?.showWidget&&Ot({onClick:It}):(At({onAcceptAll:Pt,onRejectAll:Tt,onSettings:It}),ct("banner")),Yt}const Yt={init:Zt,show(){yt()?(Rt(),qt(),At({onAcceptAll:Pt,onRejectAll:Tt,onSettings:It}),ct("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){Ct(),lt("banner")},showSettings(){yt()?It():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){Rt(),lt("modal")},getConsent:V,hasConsent:tt,hasConsentDecision:nt,getConsentProof:function(){try{const t=J().match(RegExp(F+"=([^;]+)"));if(t){return r(JSON.parse(decodeURIComponent(t[1])),q())}}catch(t){}return null},isDoNotTrackEnabled:P,getDNTDetails:function(){if("undefined"==typeof navigator)return{enabled:!1,source:null};const t=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===t||"yes"===t||!0===t?{enabled:!0,source:"dnt"}:!0===navigator.globalPrivacyControl?{enabled:!0,source:"gpc"}:{enabled:!1,source:null}},acceptAll(){yt()?Pt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){yt()?Tt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){bt(),Rt(),Lt&&(Lt.remove(),Lt=null,Mt=null),yt()&&(At({onAcceptAll:Pt,onRejectAll:Tt,onSettings:It}),ct("banner"))},getConfig:H,on:function(t,e){return document.addEventListener(t,e),()=>document.removeEventListener(t,e)},once:function(t,e){document.addEventListener(t,e,{once:!0})},EVENTS:ot};if("undefined"!=typeof window){try{Object.defineProperty(window,"Zest",{value:Object.freeze(Yt),writable:!1,configurable:!1,enumerable:!0})}catch(t){window.Zest=Yt}const t=()=>{!1!==Z().autoInit&&Zt(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}return Yt}();
|
package/dist/zest.ru.js
CHANGED
|
@@ -258,10 +258,47 @@ var Zest = (function () {
|
|
|
258
258
|
|
|
259
259
|
let patterns = { ...DEFAULT_PATTERNS };
|
|
260
260
|
|
|
261
|
+
/** Escape a string so it can be embedded in a regex literal verbatim. */
|
|
262
|
+
function escapeRegex(value) {
|
|
263
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Append patterns to a single category without replacing what's already
|
|
268
|
+
* there. Used by `essentialKeys` and `essentialPatterns` config to extend
|
|
269
|
+
* the strictly-necessary category with consumer-specific entries while
|
|
270
|
+
* keeping the built-in defaults (zest_*, csrf*, xsrf*, etc.).
|
|
271
|
+
*
|
|
272
|
+
* `keys` is an array of exact storage/cookie names; each one is
|
|
273
|
+
* compiled as a fully-anchored regex via `escapeRegex`.
|
|
274
|
+
* `patternStrings` is an array of regex source strings, each validated
|
|
275
|
+
* via `safeRegExp`. Invalid entries are dropped silently.
|
|
276
|
+
*/
|
|
277
|
+
function appendPatternsToCategory(category, { keys = [], patternStrings = [] } = {}) {
|
|
278
|
+
if (!patterns[category]) patterns[category] = [];
|
|
279
|
+
|
|
280
|
+
for (const key of keys) {
|
|
281
|
+
if (typeof key !== 'string' || !key) continue;
|
|
282
|
+
const re = safeRegExp(`^${escapeRegex(key)}$`);
|
|
283
|
+
if (re) patterns[category].push(re);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
for (const p of patternStrings) {
|
|
287
|
+
if (typeof p !== 'string' || !p) continue;
|
|
288
|
+
const re = safeRegExp(p);
|
|
289
|
+
if (re) patterns[category].push(re);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
261
293
|
/**
|
|
262
294
|
* Set custom patterns. User-supplied strings are validated with safeRegExp,
|
|
263
295
|
* which rejects catastrophic-backtracking shapes and syntax errors.
|
|
264
296
|
* Invalid patterns are silently dropped with a console warning.
|
|
297
|
+
*
|
|
298
|
+
* Note: this REPLACES the patterns for any category present in
|
|
299
|
+
* `customPatterns`. To extend the essential category without losing the
|
|
300
|
+
* built-in defaults, use `appendPatternsToCategory()` (or pass
|
|
301
|
+
* `essentialKeys` / `essentialPatterns` to `Zest.init()`).
|
|
265
302
|
*/
|
|
266
303
|
function setPatterns(customPatterns) {
|
|
267
304
|
patterns = { ...DEFAULT_PATTERNS };
|
|
@@ -1292,6 +1329,32 @@ var Zest = (function () {
|
|
|
1292
1329
|
// Blocking mode: 'manual' | 'safe' | 'strict' | 'doomsday'
|
|
1293
1330
|
mode: 'safe',
|
|
1294
1331
|
|
|
1332
|
+
// Interceptor toggles. By default Zest installs cookie + storage
|
|
1333
|
+
// interceptors that route writes through the consent layer. Consumers
|
|
1334
|
+
// who manage gating themselves (typically headless mode with custom
|
|
1335
|
+
// analytics integrations) can opt out per channel.
|
|
1336
|
+
intercept: {
|
|
1337
|
+
cookies: true,
|
|
1338
|
+
storage: true,
|
|
1339
|
+
scripts: true
|
|
1340
|
+
},
|
|
1341
|
+
|
|
1342
|
+
// Strictly-necessary declarations. Both fields *append* to whatever
|
|
1343
|
+
// the essential category already matches via the pattern matcher
|
|
1344
|
+
// defaults — they do not replace.
|
|
1345
|
+
//
|
|
1346
|
+
// - essentialKeys: array of exact storage / cookie names to treat
|
|
1347
|
+
// as strictly-necessary. Easiest case.
|
|
1348
|
+
// - essentialPatterns: array of regex source strings, validated via
|
|
1349
|
+
// safeRegExp. For prefix or family matches.
|
|
1350
|
+
//
|
|
1351
|
+
// Use these instead of `patterns.essential` when you only want to
|
|
1352
|
+
// ADD entries to the essential category without replacing the
|
|
1353
|
+
// built-in patterns (zest_*, csrf*, xsrf*, session*, __host-*,
|
|
1354
|
+
// __secure-*).
|
|
1355
|
+
essentialKeys: [],
|
|
1356
|
+
essentialPatterns: [],
|
|
1357
|
+
|
|
1295
1358
|
// Custom domains to block (in addition to mode-based blocking)
|
|
1296
1359
|
blockedDomains: [], // days
|
|
1297
1360
|
|
|
@@ -1374,6 +1437,28 @@ var Zest = (function () {
|
|
|
1374
1437
|
config.patterns = userConfig.patterns;
|
|
1375
1438
|
}
|
|
1376
1439
|
|
|
1440
|
+
// Interceptor toggles — shallow-merge so consumers can pass partial
|
|
1441
|
+
// overrides like `intercept: { storage: false }` without losing the
|
|
1442
|
+
// other defaults.
|
|
1443
|
+
if (userConfig.intercept && typeof userConfig.intercept === 'object') {
|
|
1444
|
+
config.intercept = {
|
|
1445
|
+
...DEFAULTS.intercept,
|
|
1446
|
+
...userConfig.intercept
|
|
1447
|
+
};
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
// Strictly-necessary declarations
|
|
1451
|
+
if (Array.isArray(userConfig.essentialKeys)) {
|
|
1452
|
+
config.essentialKeys = userConfig.essentialKeys.filter(
|
|
1453
|
+
(k) => typeof k === 'string' && k.length > 0 && k.length <= 200
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
if (Array.isArray(userConfig.essentialPatterns)) {
|
|
1457
|
+
config.essentialPatterns = userConfig.essentialPatterns.filter(
|
|
1458
|
+
(p) => typeof p === 'string' && p.length > 0 && p.length <= 500
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1377
1462
|
return config;
|
|
1378
1463
|
}
|
|
1379
1464
|
|
|
@@ -1816,13 +1901,32 @@ var Zest = (function () {
|
|
|
1816
1901
|
setPatterns(currentConfig.patterns);
|
|
1817
1902
|
}
|
|
1818
1903
|
|
|
1904
|
+
// Append consumer-declared strictly-necessary entries on top of
|
|
1905
|
+
// whatever's already in the essential category. This is the friendly
|
|
1906
|
+
// alternative to overriding via `patterns.essential` directly.
|
|
1907
|
+
if (
|
|
1908
|
+
(Array.isArray(currentConfig.essentialKeys) && currentConfig.essentialKeys.length > 0) ||
|
|
1909
|
+
(Array.isArray(currentConfig.essentialPatterns) && currentConfig.essentialPatterns.length > 0)
|
|
1910
|
+
) {
|
|
1911
|
+
appendPatternsToCategory('essential', {
|
|
1912
|
+
keys: currentConfig.essentialKeys,
|
|
1913
|
+
patternStrings: currentConfig.essentialPatterns
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1819
1917
|
setConsentChecker$2(checkConsent);
|
|
1820
1918
|
setConsentChecker$1(checkConsent);
|
|
1821
1919
|
setConsentChecker(checkConsent);
|
|
1822
1920
|
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1921
|
+
// Interceptor toggles. By default everything is intercepted (back-compat
|
|
1922
|
+
// with v2.0 / v2.1). Consumers that gate scripts and storage themselves
|
|
1923
|
+
// can opt out per channel via `intercept: { storage: false, … }`.
|
|
1924
|
+
const intercept = currentConfig.intercept || { cookies: true, storage: true, scripts: true };
|
|
1925
|
+
if (intercept.cookies !== false) interceptCookies();
|
|
1926
|
+
if (intercept.storage !== false) interceptStorage();
|
|
1927
|
+
if (intercept.scripts !== false) {
|
|
1928
|
+
startScriptBlocking(currentConfig.mode, currentConfig.blockedDomains);
|
|
1929
|
+
}
|
|
1826
1930
|
|
|
1827
1931
|
const consent = loadConsent();
|
|
1828
1932
|
initialized = true;
|