@freshjuice/zest 0.1.0 → 1.0.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/README.md +46 -0
- package/dist/zest.de.js +104 -1
- package/dist/zest.de.js.map +1 -1
- package/dist/zest.de.min.js +1 -1
- package/dist/zest.en.js +104 -1
- package/dist/zest.en.js.map +1 -1
- package/dist/zest.en.min.js +1 -1
- package/dist/zest.es.js +104 -1
- package/dist/zest.es.js.map +1 -1
- package/dist/zest.es.min.js +1 -1
- package/dist/zest.esm.js +104 -1
- package/dist/zest.esm.js.map +1 -1
- package/dist/zest.esm.min.js +1 -1
- package/dist/zest.fr.js +104 -1
- package/dist/zest.fr.js.map +1 -1
- package/dist/zest.fr.min.js +1 -1
- package/dist/zest.it.js +104 -1
- package/dist/zest.it.js.map +1 -1
- package/dist/zest.it.min.js +1 -1
- package/dist/zest.ja.js +104 -1
- package/dist/zest.ja.js.map +1 -1
- package/dist/zest.ja.min.js +1 -1
- package/dist/zest.js +104 -1
- package/dist/zest.js.map +1 -1
- package/dist/zest.min.js +1 -1
- package/dist/zest.nl.js +104 -1
- package/dist/zest.nl.js.map +1 -1
- package/dist/zest.nl.min.js +1 -1
- package/dist/zest.pl.js +104 -1
- package/dist/zest.pl.js.map +1 -1
- package/dist/zest.pl.min.js +1 -1
- package/dist/zest.pt.js +104 -1
- package/dist/zest.pt.js.map +1 -1
- package/dist/zest.pt.min.js +1 -1
- package/dist/zest.ru.js +104 -1
- package/dist/zest.ru.js.map +1 -1
- package/dist/zest.ru.min.js +1 -1
- package/dist/zest.uk.js +104 -1
- package/dist/zest.uk.js.map +1 -1
- package/dist/zest.uk.min.js +1 -1
- package/dist/zest.zh.js +104 -1
- package/dist/zest.zh.js.map +1 -1
- package/dist/zest.zh.min.js +1 -1
- package/package.json +5 -4
- package/src/api/public-api.js +97 -0
- package/src/config/defaults.js +150 -0
- package/src/config/parser.js +104 -0
- package/src/core/categories.js +52 -0
- package/src/core/cookie-interceptor.js +116 -0
- package/src/core/dnt.js +56 -0
- package/src/core/known-trackers.js +168 -0
- package/src/core/pattern-matcher.js +96 -0
- package/src/core/script-blocker.js +308 -0
- package/src/core/storage-interceptor.js +169 -0
- package/src/i18n/lang-en.js +54 -0
- package/src/i18n/single/lang-de.js +55 -0
- package/src/i18n/single/lang-en.js +55 -0
- package/src/i18n/single/lang-es.js +55 -0
- package/src/i18n/single/lang-fr.js +55 -0
- package/src/i18n/single/lang-it.js +55 -0
- package/src/i18n/single/lang-ja.js +55 -0
- package/src/i18n/single/lang-nl.js +55 -0
- package/src/i18n/single/lang-pl.js +55 -0
- package/src/i18n/single/lang-pt.js +55 -0
- package/src/i18n/single/lang-ru.js +55 -0
- package/src/i18n/single/lang-uk.js +55 -0
- package/src/i18n/single/lang-zh.js +55 -0
- package/src/i18n/translations.js +546 -0
- package/src/index.js +377 -0
- package/src/integrations/consent-signals.js +71 -0
- package/src/storage/consent-store.js +177 -0
- package/src/storage/events.js +84 -0
- package/src/ui/banner.js +130 -0
- package/src/ui/modal.js +211 -0
- package/src/ui/styles.js +498 -0
- package/src/ui/widget.js +103 -0
package/dist/zest.es.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Zest=function(){"use strict";const t={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 e={...t};function n(t){for(const[n,o]of Object.entries(e))if(o.some(e=>e.test(t)))return n;return"marketing"}let o=null;const a=[];let s=()=>!1;function r(){return o}let i=null,c=null;const l=[],d=[];let u=()=>!1;function p(t,e,o){return new Proxy(t,{get(t,o){if("setItem"===o)return(o,a)=>{const s=n(o);u(s)?t.setItem(o,a):e.push({key:o,value:a,category:s,timestamp:Date.now()})};const a=t[o];return"function"==typeof a?a.bind(t):a}})}const m={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"]},f={analytics:[...m.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:[...m.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 g(t,e){try{const n=new URL(t).hostname.toLowerCase(),o=t.toLowerCase();for(const t of e)if(t.endsWith(".")){if(n.includes(t.slice(0,-1)))return!0}else{if(n===t||n.endsWith("."+t))return!0;if(o.includes(t))return!0}}catch(t){}return!1}function b(t,e="safe"){const n="strict"===e?f:m;for(const[e,o]of Object.entries(n))if(g(t,o))return e;return null}const z=[];let y=null,h="safe",x=[],w=()=>!1;function v(t){const e=t.getAttribute("data-consent-category");if(e)return e;if(t.hasAttribute("data-zest-allow"))return null;const n=t.src;if(!n)return null;const o=function(t){if(!t||0===x.length)return null;try{const e=new URL(t).hostname.toLowerCase();for(const t of x){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}(n);if(o)return o;switch(h){case"manual":default:return null;case"safe":case"strict":return b(n,h);case"doomsday":return 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}}(n)?b(n,"strict")||"marketing":null}}function k(t){if(t.hasAttribute("data-zest-processed"))return!1;const e=v(t);if(!e)return t.setAttribute("data-zest-processed","allowed"),!1;if(w(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,timestamp:Date.now()};return t.setAttribute("data-zest-processed","blocked"),t.setAttribute("data-consent-category",e),t.type="text/plain",t.src&&(t.setAttribute("data-blocked-src",t.src),t.removeAttribute("src")),z.push(n),!0}function _(t){const e=document.createElement("script");t.src?e.src=t.src:t.inline&&(e.textContent=t.inline),t.async&&(e.async=!0),t.defer&&(e.defer=!0),e.setAttribute("data-zest-processed","executed"),e.setAttribute("data-consent-executed","true"),document.head.appendChild(e)}function A(t){for(const e of t)for(const t of e.addedNodes)if("SCRIPT"!==t.nodeName||t.hasAttribute("data-zest-processed")||k(t),t.querySelectorAll){t.querySelectorAll("script:not([data-zest-processed])").forEach(k)}}function C(t="safe",e=[]){return h=t,x=e,document.querySelectorAll("script:not([data-zest-processed])").forEach(k),y=new MutationObserver(A),y.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const S={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 E(){if("undefined"==typeof navigator)return!1;const t=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===t||"yes"===t||!0===t||!0===navigator.globalPrivacyControl}const j={labels:{banner:{title:"Valoramos tu privacidad",description:'Utilizamos cookies para mejorar tu experiencia de navegación, ofrecer contenido personalizado y analizar nuestro tráfico. Al hacer clic en "Aceptar todo", consientes el uso de cookies.',acceptAll:"Aceptar todo",rejectAll:"Rechazar todo",settings:"Configuración"},modal:{title:"Configuración de privacidad",description:"Gestiona tus preferencias de cookies. Puedes activar o desactivar diferentes tipos de cookies a continuación.",save:"Guardar preferencias",acceptAll:"Aceptar todo",rejectAll:"Rechazar todo"},widget:{label:"Configuración de cookies"}},categories:{essential:{label:"Esenciales",description:"Necesarias para el funcionamiento del sitio web. No se pueden desactivar."},functional:{label:"Funcionales",description:"Permiten funciones personalizadas como preferencias de idioma y temas."},analytics:{label:"Analíticas",description:"Nos ayudan a entender cómo los visitantes interactúan con nuestro sitio web."},marketing:{label:"Marketing",description:"Se utilizan para mostrar anuncios relevantes y medir el rendimiento de las campañas."}}};const R={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:S,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:"",mode:"safe",blockedDomains:[],policyUrl:null,imprintUrl:null,callbacks:{onAccept:null,onReject:null,onChange:null,onReady:null}};function N(t){const e={...R};t||(t={});const n=["lang","position","theme","accentColor","autoInit","showWidget","expiration","policyUrl","imprintUrl","customStyles","mode","blockedDomains","respectDNT","dntBehavior"];for(const o of n)void 0!==t[o]&&(e[o]=t[o]);e.lang="es";const o=j,a=o.labels||{},s=t.labels||{};e.labels={banner:{...R.labels.banner,...a.banner,...s.banner},modal:{...R.labels.modal,...a.modal,...s.modal},widget:{...R.labels.widget,...a.widget,...s.widget}};const r=o.categories||{},i=t.categories||{};e.categories={...R.categories};for(const t of Object.keys(R.categories))e.categories[t]={...R.categories[t],...r[t],...i[t]};return t.callbacks&&(e.callbacks={...R.callbacks,...t.callbacks}),t.patterns&&(e.patterns=t.patterns),e}function $(){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");return l&&(e.expiration=parseInt(l,10)),e}();return N({...t,...e})}let D=null;function T(){return D||(D=$()),D}const O="zest_consent";let q=null;function L(t){const e=r();e?.set?e.set.call(document,t):document.cookie=t}function M(){const t=r();return t?.get?t.get.call(document):document.cookie}function I(){try{const t=M().match(RegExp(O+"=([^;]+)"));if(t){const e=JSON.parse(decodeURIComponent(t[1]));return q=e.categories||{essential:!0,functional:!1,analytics:!1,marketing:!1},{...q}}}catch(t){}return q={essential:!0,functional:!1,analytics:!1,marketing:!1},{...q}}function U(){return q||(q=I()),{...q}}function P(t,e=365){const n=q?{...q}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return q={essential:!0,functional:!!t.functional,analytics:!!t.analytics,marketing:!!t.marketing},function(t=365){q||(q={essential:!0,functional:!1,analytics:!1,marketing:!1});const e={version:"1.0",timestamp:Date.now(),categories:q},n=new Date(Date.now()+24*t*60*60*1e3).toUTCString();L(`${O}=${encodeURIComponent(JSON.stringify(e))}; expires=${n}; path=/; SameSite=Lax`)}(e),{current:{...q},previous:n}}function W(t){return q||(q=I()),!0===q[t]}function Z(t=365){return P({functional:!1,analytics:!1,marketing:!1},t)}function Y(){try{return M().includes(O)}catch(t){return!1}}const H={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function B(t,e={}){const n=new CustomEvent(t,{detail:e,bubbles:!0,cancelable:!0});return document.dispatchEvent(n),n}function F(t,e){return B(H.CONSENT,{consent:t,previous:e})}function J(t){return B(H.REJECT,{consent:t})}function G(t,e){return B(H.CHANGE,{consent:t,previous:e})}function X(t="banner"){return B(H.SHOW,{type:t})}function V(t="banner"){return B(H.HIDE,{type:t})}function K(t){const e=t.accentColor||"#4F46E5";return`\n:host {\n --zest-accent: ${e};\n --zest-accent-hover: ${function(t,e){const n=parseInt(t.replace("#",""),16),o=Math.round(2.55*e);return"#"+(16777216+65536*Math.min(255,Math.max(0,(n>>16)+o))+256*Math.min(255,Math.max(0,(n>>8&255)+o))+Math.min(255,Math.max(0,(255&n)+o))).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${t.customStyles||""}\n`}let Q=null,tt=null;function et(t={}){Q?Q.classList.remove("zest-hidden"):function(t={}){if(Q)return Q;const e=T();Q=document.createElement("zest-banner"),Q.setAttribute("data-theme",e.theme||"light"),tt=Q.attachShadow({mode:"open"});const n=document.createElement("style");n.textContent=K(e),tt.appendChild(n);const o=document.createElement("div");o.innerHTML=function(t){const e=t.labels.banner;return`\n <div class="zest-banner zest-banner--${t.position||"bottom"}" role="dialog" aria-modal="false" aria-label="${e.title}">\n <h2 class="zest-banner__title">${e.title}</h2>\n <p class="zest-banner__description">${e.description}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${e.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${e.rejectAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${e.settings}\n </button>\n </div>\n </div>\n `}(e),tt.appendChild(o.firstElementChild);const a=tt.querySelector(".zest-banner");a.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?.()}}),a.addEventListener("keydown",e=>{"Escape"===e.key&&t.onSettings?.()}),document.body.appendChild(Q),requestAnimationFrame(()=>{const t=tt.querySelector("button");t?.focus()})}(t)}function nt(){Q&&(Q.remove(),Q=null,tt=null)}let ot=null,at=null,st={};function rt(){if(!at)return st;const t=at.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 it(t={},e={}){if(ot)return ot;const n=T();st={...t},ot=document.createElement("zest-modal"),ot.setAttribute("data-theme",n.theme||"light"),at=ot.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=K(n),at.appendChild(o);const a=document.createElement("div");a.innerHTML=function(t,e){const n=t.labels.modal,o=Object.values(t.categories||S).map(t=>{return`\n <div class="zest-category">\n <div class="zest-category__header">\n <div class="zest-category__info">\n <span class="zest-category__label">${(n=t).label}</span>\n <p class="zest-category__description">${n.description}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${n.id}"\n ${e[t.id]??t.default?"checked":""}\n ${t.required?"disabled":""}\n aria-label="${n.label}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `;var n}).join("");return`\n <div class="zest-modal-overlay" role="dialog" aria-modal="true" aria-label="${n.title}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${n.title}</h2>\n <p class="zest-modal__description">${n.description} ${t.policyUrl?`<a href="${t.policyUrl}" class="zest-link" target="_blank" rel="noopener">Privacy Policy</a>`:""}</p>\n </div>\n <div class="zest-modal__body">\n ${o}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${n.save}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${n.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${n.rejectAll}\n </button>\n </div>\n </div>\n </div>\n `}(n,t),at.appendChild(a.firstElementChild);const s=at.querySelector(".zest-modal-overlay");return s.addEventListener("click",t=>{const n=t.target.dataset.action;if(n)switch(n){case"save":e.onSave?.(rt());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?.()}),at.querySelectorAll(".zest-toggle__input").forEach(t=>{t.addEventListener("change",()=>{st=rt()})}),document.body.appendChild(ot),requestAnimationFrame(()=>{const t=at.querySelector("button");t?.focus()}),ot}function ct(){ot&&(ot.remove(),ot=null,at=null)}let lt=null,dt=null;function ut(t={}){lt?lt.style.display="":function(t={}){if(lt)return lt;const e=T();lt=document.createElement("zest-widget"),lt.setAttribute("data-theme",e.theme||"light"),dt=lt.attachShadow({mode:"open"});const n=document.createElement("style");n.textContent=K(e),dt.appendChild(n);const o=document.createElement("div");o.innerHTML=function(t){const e=t.labels.widget;return`\n <div class="zest-widget">\n <button type="button" class="zest-widget__btn" aria-label="${e.label}" title="${e.label}">\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),dt.appendChild(o.firstElementChild),dt.querySelector(".zest-widget__btn").addEventListener("click",()=>{t.onClick?.()}),document.body.appendChild(lt)}(t)}function pt(){lt&&(lt.style.display="none")}let mt=!1,ft=null;function gt(t){return W(t)}function bt(t){!function(t){const e=[];for(const n of a)t.includes(n.category)?o?.set&&o.set.call(document,n.value):e.push(n);a.length=0,a.push(...e)}(t),function(t){const e=[];for(const n of l)t.includes(n.category)?i?.setItem(n.key,n.value):e.push(n);l.length=0,l.push(...e);const n=[];for(const e of d)t.includes(e.category)?c?.setItem(e.key,e.value):n.push(e);d.length=0,d.push(...n)}(t),function(t){const e=[];for(const n of z)t.includes(n.category)?_(n):e.push(n);z.length=0,z.push(...e),document.querySelectorAll('script[data-zest-processed="blocked"]').forEach(e=>{const n=e.getAttribute("data-consent-category");if(t.includes(n)){const t=document.createElement("script"),n=e.getAttribute("data-blocked-src");n?t.src=n:t.textContent=e.textContent,e.async&&(t.async=!0),e.defer&&(t.defer=!0),t.setAttribute("data-zest-processed","executed"),t.setAttribute("data-consent-executed","true"),e.parentNode?.replaceChild(t,e)}})}(t)}function zt(){const t=function(t=365){return P({functional:!0,analytics:!0,marketing:!0},t)}(ft.expiration),e=Object.keys(S);nt(),ct(),bt(e),ft.showWidget&&ut({onClick:xt}),F(t.current,t.previous),G(t.current,t.previous),ft.callbacks?.onAccept?.(t.current),ft.callbacks?.onChange?.(t.current)}function yt(){const t=Z(ft.expiration);nt(),ct(),ft.showWidget&&ut({onClick:xt}),J(t.current),G(t.current,t.previous),ft.callbacks?.onReject?.(),ft.callbacks?.onChange?.(t.current)}function ht(t){const e=P(t,ft.expiration),n=Object.keys(e.current).filter(t=>e.current[t]&&!e.previous[t]);n.length>0&&bt(n),ct(),ft.showWidget&&ut({onClick:xt});Object.entries(t).some(([t,e])=>"essential"!==t&&e)?F(e.current,e.previous):J(e.current),G(e.current,e.previous),ft.callbacks?.onChange?.(e.current)}function xt(){nt(),pt(),it(U(),{onSave:ht,onAcceptAll:zt,onRejectAll:yt,onClose:wt}),X("modal")}function wt(){ct(),V("modal"),Y()&&ft.showWidget?ut({onClick:xt}):et({onAcceptAll:zt,onRejectAll:yt,onSettings:xt})}function vt(r={}){if(mt)return console.warn("[Zest] Already initialized"),kt;ft=function(t){return D=N(t),D}(r),ft.patterns&&function(n){e={...t};for(const[t,o]of Object.entries(n))Array.isArray(o)&&(e[t]=o.map(t=>t instanceof RegExp?t:RegExp(t)))}(ft.patterns),s=gt,function(t){u=t}(gt),function(t){w=t}(gt),o=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),o?Object.defineProperty(document,"cookie",{get:()=>o.get.call(document),set(t){const e=function(t){const e=t.match(/^([^=]+)/);return e?e[1].trim():null}(t);if(!e)return;const r=n(e);s(r)?o.set.call(document,t):a.push({value:t,name:e,category:r,timestamp:Date.now()})},configurable:!0}):console.warn("[Zest] Could not get cookie descriptor"),function(){try{return i=window.localStorage,c=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:p(i,l),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:p(c,d),configurable:!0,writable:!1}),!0}catch(t){return console.warn("[Zest] Could not intercept storage APIs:",t),!1}}(),C(ft.mode,ft.blockedDomains);const m=I();mt=!0;let f=!1;if(E()&&ft.respectDNT&&"ignore"!==ft.dntBehavior&&"reject"===ft.dntBehavior&&!Y()){const t=Z(ft.expiration);f=!0,J(t.current),G(t.current,t.previous),ft.callbacks?.onReject?.(),ft.callbacks?.onChange?.(t.current)}return function(t){B(H.READY,{consent:t})}(m),ft.callbacks?.onReady?.(m),Y()||f?ft.showWidget&&ut({onClick:xt}):(et({onAcceptAll:zt,onRejectAll:yt,onSettings:xt}),X("banner")),kt}const kt={init:vt,show(){mt?(ct(),pt(),et({onAcceptAll:zt,onRejectAll:yt,onSettings:xt}),X("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){nt(),V("banner")},showSettings(){mt?xt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){ct(),V("modal")},getConsent:U,hasConsent:W,hasConsentDecision:Y,getConsentProof:function(){try{const t=M().match(RegExp(O+"=([^;]+)"));if(t)return JSON.parse(decodeURIComponent(t[1]))}catch(t){}return null},isDoNotTrackEnabled:E,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(){mt?zt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){mt?yt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){L(O+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"),q=null,ct(),lt&&(lt.remove(),lt=null,dt=null),mt&&(et({onAcceptAll:zt,onRejectAll:yt,onSettings:xt}),X("banner"))},getConfig:T,EVENTS:H};if("undefined"!=typeof window){window.Zest=kt;const t=()=>{!1!==$().autoInit&&vt(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}return kt}();
|
|
1
|
+
var Zest=function(){"use strict";const t={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 n={...t};function e(t){for(const[e,o]of Object.entries(n))if(o.some(n=>n.test(t)))return e;return"marketing"}let o=null;const a=[];let s=()=>!1;function r(){return o}let i=null,c=null;const l=[],d=[];let u=()=>!1;function p(t,n,o){return new Proxy(t,{get(t,o){if("setItem"===o)return(o,a)=>{const s=e(o);u(s)?t.setItem(o,a):n.push({key:o,value:a,category:s,timestamp:Date.now()})};const a=t[o];return"function"==typeof a?a.bind(t):a}})}const g={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"]},m={analytics:[...g.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:[...g.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 f(t,n){try{const e=new URL(t).hostname.toLowerCase(),o=t.toLowerCase();for(const t of n)if(t.endsWith(".")){if(e.includes(t.slice(0,-1)))return!0}else{if(e===t||e.endsWith("."+t))return!0;if(o.includes(t))return!0}}catch(t){}return!1}function b(t,n="safe"){const e="strict"===n?m:g;for(const[n,o]of Object.entries(e))if(f(t,o))return n;return null}const y=[];let z=null,h="safe",w=[],x=()=>!1;function v(t){const n=t.getAttribute("data-consent-category");if(n)return n;if(t.hasAttribute("data-zest-allow"))return null;const e=t.src;if(!e)return null;const o=function(t){if(!t||0===w.length)return null;try{const n=new URL(t).hostname.toLowerCase();for(const t of w){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}(e);if(o)return o;switch(h){case"manual":default:return null;case"safe":case"strict":return b(e,h);case"doomsday":return 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}}(e)?b(e,"strict")||"marketing":null}}function k(t){if(t.hasAttribute("data-zest-processed"))return!1;const n=v(t);if(!n)return t.setAttribute("data-zest-processed","allowed"),!1;if(x(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,timestamp:Date.now()};return t.setAttribute("data-zest-processed","blocked"),t.setAttribute("data-consent-category",n),t.type="text/plain",t.src&&(t.setAttribute("data-blocked-src",t.src),t.removeAttribute("src")),y.push(e),!0}function _(t){const n=document.createElement("script");t.src?n.src=t.src:t.inline&&(n.textContent=t.inline),t.async&&(n.async=!0),t.defer&&(n.defer=!0),n.setAttribute("data-zest-processed","executed"),n.setAttribute("data-consent-executed","true"),document.head.appendChild(n)}function A(t){for(const n of t)for(const t of n.addedNodes)if("SCRIPT"!==t.nodeName||t.hasAttribute("data-zest-processed")||k(t),t.querySelectorAll){t.querySelectorAll("script:not([data-zest-processed])").forEach(k)}}function C(t="safe",n=[]){return h=t,w=n,document.querySelectorAll("script:not([data-zest-processed])").forEach(k),z=new MutationObserver(A),z.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const S={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 E(){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 j(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 R={labels:{banner:{title:"Valoramos tu privacidad",description:'Utilizamos cookies para mejorar tu experiencia de navegación, ofrecer contenido personalizado y analizar nuestro tráfico. Al hacer clic en "Aceptar todo", consientes el uso de cookies.',acceptAll:"Aceptar todo",rejectAll:"Rechazar todo",settings:"Configuración"},modal:{title:"Configuración de privacidad",description:"Gestiona tus preferencias de cookies. Puedes activar o desactivar diferentes tipos de cookies a continuación.",save:"Guardar preferencias",acceptAll:"Aceptar todo",rejectAll:"Rechazar todo"},widget:{label:"Configuración de cookies"}},categories:{essential:{label:"Esenciales",description:"Necesarias para el funcionamiento del sitio web. No se pueden desactivar."},functional:{label:"Funcionales",description:"Permiten funciones personalizadas como preferencias de idioma y temas."},analytics:{label:"Analíticas",description:"Nos ayudan a entender cómo los visitantes interactúan con nuestro sitio web."},marketing:{label:"Marketing",description:"Se utilizan para mostrar anuncios relevantes y medir el rendimiento de las campañas."}}};const M={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:S,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 N(t){const n={...M};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="es";const o=R,a=o.labels||{},s=t.labels||{};n.labels={banner:{...M.labels.banner,...a.banner,...s.banner},modal:{...M.labels.modal,...a.modal,...s.modal},widget:{...M.labels.widget,...a.widget,...s.widget}};const r=o.categories||{},i=t.categories||{};n.categories={...M.categories};for(const t of Object.keys(M.categories))n.categories[t]={...M.categories[t],...r[t],...i[t]};return t.callbacks&&(n.callbacks={...M.callbacks,...t.callbacks}),t.patterns&&(n.patterns=t.patterns),n}function $(){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 N({...t,...n})}let D=null;function q(){return D||(D=$()),D}const L="zest_consent";let T=null;function O(t){const n=r();n?.set?n.set.call(document,t):document.cookie=t}function I(){const t=r();return t?.get?t.get.call(document):document.cookie}function U(){try{const t=I().match(RegExp(L+"=([^;]+)"));if(t){const n=JSON.parse(decodeURIComponent(t[1]));return T=n.categories||{essential:!0,functional:!1,analytics:!1,marketing:!1},{...T}}}catch(t){}return T={essential:!0,functional:!1,analytics:!1,marketing:!1},{...T}}function P(){return T||(T=U()),{...T}}function W(t,n=365){const e=T?{...T}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return T={essential:!0,functional:!!t.functional,analytics:!!t.analytics,marketing:!!t.marketing},function(t=365){T||(T={essential:!0,functional:!1,analytics:!1,marketing:!1});const n={version:"1.0",timestamp:Date.now(),categories:T},e=new Date(Date.now()+24*t*60*60*1e3).toUTCString();O(`${L}=${encodeURIComponent(JSON.stringify(n))}; expires=${e}; path=/; SameSite=Lax`)}(n),{current:{...T},previous:e}}function Z(t){return T||(T=U()),!0===T[t]}function Y(t=365){return W({functional:!1,analytics:!1,marketing:!1},t)}function H(){try{return I().includes(L)}catch(t){return!1}}const B={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function G(t,n={}){const e=new CustomEvent(t,{detail:n,bubbles:!0,cancelable:!0});return document.dispatchEvent(e),e}function F(t,n){return G(B.CONSENT,{consent:t,previous:n})}function J(t){return G(B.REJECT,{consent:t})}function X(t,n){return G(B.CHANGE,{consent:t,previous:n})}function V(t="banner"){return G(B.SHOW,{type:t})}function K(t="banner"){return G(B.HIDE,{type:t})}function Q(t){const n=t.accentColor||"#4F46E5";return`\n:host {\n --zest-accent: ${n};\n --zest-accent-hover: ${function(t,n){const e=parseInt(t.replace("#",""),16),o=Math.round(2.55*n);return"#"+(16777216+65536*Math.min(255,Math.max(0,(e>>16)+o))+256*Math.min(255,Math.max(0,(e>>8&255)+o))+Math.min(255,Math.max(0,(255&e)+o))).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${t.customStyles||""}\n`}let tt=null,nt=null;function et(t={}){tt?tt.classList.remove("zest-hidden"):function(t={}){if(tt)return tt;const n=q();tt=document.createElement("zest-banner"),tt.setAttribute("data-theme",n.theme||"light"),nt=tt.attachShadow({mode:"open"});const e=document.createElement("style");e.textContent=Q(n),nt.appendChild(e);const o=document.createElement("div");o.innerHTML=function(t){const n=t.labels.banner;return`\n <div class="zest-banner zest-banner--${t.position||"bottom"}" role="dialog" aria-modal="false" aria-label="${n.title}">\n <h2 class="zest-banner__title">${n.title}</h2>\n <p class="zest-banner__description">${n.description}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${n.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${n.rejectAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${n.settings}\n </button>\n </div>\n </div>\n `}(n),nt.appendChild(o.firstElementChild);const a=nt.querySelector(".zest-banner");a.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?.()}}),a.addEventListener("keydown",n=>{"Escape"===n.key&&t.onSettings?.()}),document.body.appendChild(tt),requestAnimationFrame(()=>{const t=nt.querySelector("button");t?.focus()})}(t)}function ot(){tt&&(tt.remove(),tt=null,nt=null)}let at=null,st=null,rt={};function it(){if(!st)return rt;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 ct(t={},n={}){if(at)return at;const e=q();rt={...t},at=document.createElement("zest-modal"),at.setAttribute("data-theme",e.theme||"light"),st=at.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=Q(e),st.appendChild(o);const a=document.createElement("div");a.innerHTML=function(t,n){const e=t.labels.modal,o=Object.values(t.categories||S).map(t=>{return`\n <div class="zest-category">\n <div class="zest-category__header">\n <div class="zest-category__info">\n <span class="zest-category__label">${(e=t).label}</span>\n <p class="zest-category__description">${e.description}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${e.id}"\n ${n[t.id]??t.default?"checked":""}\n ${t.required?"disabled":""}\n aria-label="${e.label}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `;var e}).join("");return`\n <div class="zest-modal-overlay" role="dialog" aria-modal="true" aria-label="${e.title}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${e.title}</h2>\n <p class="zest-modal__description">${e.description} ${t.policyUrl?`<a href="${t.policyUrl}" class="zest-link" target="_blank" rel="noopener">Privacy Policy</a>`:""}</p>\n </div>\n <div class="zest-modal__body">\n ${o}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${e.save}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${e.acceptAll}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${e.rejectAll}\n </button>\n </div>\n </div>\n </div>\n `}(e,t),st.appendChild(a.firstElementChild);const s=st.querySelector(".zest-modal-overlay");return s.addEventListener("click",t=>{const e=t.target.dataset.action;if(e)switch(e){case"save":n.onSave?.(it());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",()=>{rt=it()})}),document.body.appendChild(at),requestAnimationFrame(()=>{const t=st.querySelector("button");t?.focus()}),at}function lt(){at&&(at.remove(),at=null,st=null)}let dt=null,ut=null;function pt(t={}){dt?dt.style.display="":function(t={}){if(dt)return dt;const n=q();dt=document.createElement("zest-widget"),dt.setAttribute("data-theme",n.theme||"light"),ut=dt.attachShadow({mode:"open"});const e=document.createElement("style");e.textContent=Q(n),ut.appendChild(e);const o=document.createElement("div");o.innerHTML=function(t){const n=t.labels.widget;return`\n <div class="zest-widget">\n <button type="button" class="zest-widget__btn" aria-label="${n.label}" title="${n.label}">\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),ut.appendChild(o.firstElementChild),ut.querySelector(".zest-widget__btn").addEventListener("click",()=>{t.onClick?.()}),document.body.appendChild(dt)}(t)}function gt(){dt&&(dt.style.display="none")}let mt=!1,ft=null;function bt(t){return Z(t)}function yt(t){!function(t){const n=[];for(const e of a)t.includes(e.category)?o?.set&&o.set.call(document,e.value):n.push(e);a.length=0,a.push(...n)}(t),function(t){const n=[];for(const e of l)t.includes(e.category)?i?.setItem(e.key,e.value):n.push(e);l.length=0,l.push(...n);const e=[];for(const n of d)t.includes(n.category)?c?.setItem(n.key,n.value):e.push(n);d.length=0,d.push(...e)}(t),function(t){const n=[];for(const e of y)t.includes(e.category)?_(e):n.push(e);y.length=0,y.push(...n),document.querySelectorAll('script[data-zest-processed="blocked"]').forEach(n=>{const e=n.getAttribute("data-consent-category");if(t.includes(e)){const t=document.createElement("script"),e=n.getAttribute("data-blocked-src");e?t.src=e:t.textContent=n.textContent,n.async&&(t.async=!0),n.defer&&(t.defer=!0),t.setAttribute("data-zest-processed","executed"),t.setAttribute("data-consent-executed","true"),n.parentNode?.replaceChild(t,n)}})}(t)}function zt(){const t=function(t=365){return W({functional:!0,analytics:!0,marketing:!0},t)}(ft.expiration),n=Object.keys(S);j(t.current,ft,!1),ot(),lt(),yt(n),ft.showWidget&&pt({onClick:xt}),F(t.current,t.previous),X(t.current,t.previous),ft.callbacks?.onAccept?.(t.current),ft.callbacks?.onChange?.(t.current)}function ht(){const t=Y(ft.expiration);j(t.current,ft,!1),ot(),lt(),ft.showWidget&&pt({onClick:xt}),J(t.current),X(t.current,t.previous),ft.callbacks?.onReject?.(),ft.callbacks?.onChange?.(t.current)}function wt(t){const n=W(t,ft.expiration);j(n.current,ft,!1);const e=Object.keys(n.current).filter(t=>n.current[t]&&!n.previous[t]);e.length>0&&yt(e),lt(),ft.showWidget&&pt({onClick:xt});Object.entries(t).some(([t,n])=>"essential"!==t&&n)?F(n.current,n.previous):J(n.current),X(n.current,n.previous),ft.callbacks?.onChange?.(n.current)}function xt(){ot(),gt(),ct(P(),{onSave:wt,onAcceptAll:zt,onRejectAll:ht,onClose:vt}),V("modal")}function vt(){lt(),K("modal"),H()&&ft.showWidget?pt({onClick:xt}):et({onAcceptAll:zt,onRejectAll:ht,onSettings:xt})}function kt(r={}){if(mt)return console.warn("[Zest] Already initialized"),_t;ft=function(t){return D=N(t),D}(r),j({functional:!1,analytics:!1,marketing:!1},ft,!0),ft.patterns&&function(e){n={...t};for(const[t,o]of Object.entries(e))Array.isArray(o)&&(n[t]=o.map(t=>t instanceof RegExp?t:RegExp(t)))}(ft.patterns),s=bt,function(t){u=t}(bt),function(t){x=t}(bt),o=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),o?Object.defineProperty(document,"cookie",{get:()=>o.get.call(document),set(t){const n=function(t){const n=t.match(/^([^=]+)/);return n?n[1].trim():null}(t);if(!n)return;const r=e(n);s(r)?o.set.call(document,t):a.push({value:t,name:n,category:r,timestamp:Date.now()})},configurable:!0}):console.warn("[Zest] Could not get cookie descriptor"),function(){try{return i=window.localStorage,c=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:p(i,l),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:p(c,d),configurable:!0,writable:!1}),!0}catch(t){return console.warn("[Zest] Could not intercept storage APIs:",t),!1}}(),C(ft.mode,ft.blockedDomains);const g=U();mt=!0,H()&&j(g,ft,!1);let m=!1;if(E()&&ft.respectDNT&&"ignore"!==ft.dntBehavior&&"reject"===ft.dntBehavior&&!H()){const t=Y(ft.expiration);m=!0,j(t.current,ft,!1),J(t.current),X(t.current,t.previous),ft.callbacks?.onReject?.(),ft.callbacks?.onChange?.(t.current)}return function(t){G(B.READY,{consent:t})}(g),ft.callbacks?.onReady?.(g),H()||m?ft.showWidget&&pt({onClick:xt}):(et({onAcceptAll:zt,onRejectAll:ht,onSettings:xt}),V("banner")),_t}const _t={init:kt,show(){mt?(lt(),gt(),et({onAcceptAll:zt,onRejectAll:ht,onSettings:xt}),V("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){ot(),K("banner")},showSettings(){mt?xt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){lt(),K("modal")},getConsent:P,hasConsent:Z,hasConsentDecision:H,getConsentProof:function(){try{const t=I().match(RegExp(L+"=([^;]+)"));if(t)return JSON.parse(decodeURIComponent(t[1]))}catch(t){}return null},isDoNotTrackEnabled:E,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(){mt?zt():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){mt?ht():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){O(L+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"),T=null,lt(),dt&&(dt.remove(),dt=null,ut=null),mt&&(et({onAcceptAll:zt,onRejectAll:ht,onSettings:xt}),V("banner"))},getConfig:q,EVENTS:B};if("undefined"!=typeof window){window.Zest=_t;const t=()=>{!1!==$().autoInit&&kt(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}return _t}();
|
package/dist/zest.esm.js
CHANGED
|
@@ -839,6 +839,78 @@ function getDNTDetails() {
|
|
|
839
839
|
return { enabled: false, source: null };
|
|
840
840
|
}
|
|
841
841
|
|
|
842
|
+
/**
|
|
843
|
+
* Consent Signals - Optional vendor consent mode integrations
|
|
844
|
+
*
|
|
845
|
+
* Pushes consent state to Google Consent Mode v2 and/or Microsoft UET
|
|
846
|
+
* Consent Mode when enabled via config.
|
|
847
|
+
*/
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Map Zest consent state to Google Consent Mode v2 signals
|
|
851
|
+
*/
|
|
852
|
+
function toGoogleSignals(consent) {
|
|
853
|
+
const g = (val) => val ? 'granted' : 'denied';
|
|
854
|
+
return {
|
|
855
|
+
ad_storage: g(consent.marketing),
|
|
856
|
+
ad_user_data: g(consent.marketing),
|
|
857
|
+
ad_personalization: g(consent.marketing),
|
|
858
|
+
analytics_storage: g(consent.analytics),
|
|
859
|
+
functionality_storage: 'granted', // essential is always true
|
|
860
|
+
personalization_storage: g(consent.functional)
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Push consent signal to Google via gtag or dataLayer fallback.
|
|
866
|
+
* Uses a local function to preserve the `arguments` object shape
|
|
867
|
+
* that gtag/dataLayer expects (not an array).
|
|
868
|
+
*/
|
|
869
|
+
function pushGoogle(type, signals) {
|
|
870
|
+
window.dataLayer = window.dataLayer || [];
|
|
871
|
+
if (typeof window.gtag === 'function') {
|
|
872
|
+
window.gtag('consent', type, signals);
|
|
873
|
+
} else {
|
|
874
|
+
function gtagFallback() { window.dataLayer.push(arguments); }
|
|
875
|
+
gtagFallback('consent', type, signals);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Map Zest consent state to Microsoft UET signal.
|
|
881
|
+
* Microsoft UET only exposes ad_storage.
|
|
882
|
+
*/
|
|
883
|
+
function toMicrosoftSignals(consent) {
|
|
884
|
+
return { ad_storage: consent.marketing ? 'granted' : 'denied' };
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Push consent signal to Microsoft UET
|
|
889
|
+
*/
|
|
890
|
+
function pushMicrosoft(type, signals) {
|
|
891
|
+
window.uetq = window.uetq || [];
|
|
892
|
+
window.uetq.push('consent', type, signals);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Apply consent signals to enabled vendor integrations.
|
|
897
|
+
*
|
|
898
|
+
* @param {Object} consent Current Zest consent state
|
|
899
|
+
* @param {Object} config Merged Zest config
|
|
900
|
+
* @param {boolean} isDefault true on first call (pushes 'default'), false for updates
|
|
901
|
+
*/
|
|
902
|
+
function applyConsentSignals(consent, config, isDefault) {
|
|
903
|
+
const type = isDefault ? 'default' : 'update';
|
|
904
|
+
|
|
905
|
+
if (config.consentModeGoogle) {
|
|
906
|
+
pushGoogle(type, toGoogleSignals(consent));
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (config.consentModeMicrosoft) {
|
|
910
|
+
pushMicrosoft(type, toMicrosoftSignals(consent));
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
842
914
|
/**
|
|
843
915
|
* Built-in translations for Zest
|
|
844
916
|
* Language is auto-detected from <html lang=""> or navigator.language
|
|
@@ -1438,6 +1510,10 @@ const DEFAULTS = {
|
|
|
1438
1510
|
// Custom styles to inject into Shadow DOM
|
|
1439
1511
|
customStyles: '',
|
|
1440
1512
|
|
|
1513
|
+
// Vendor consent mode integrations (optional)
|
|
1514
|
+
consentModeGoogle: false,
|
|
1515
|
+
consentModeMicrosoft: false,
|
|
1516
|
+
|
|
1441
1517
|
// Blocking mode: 'manual' | 'safe' | 'strict' | 'doomsday'
|
|
1442
1518
|
mode: 'safe',
|
|
1443
1519
|
|
|
@@ -1468,7 +1544,7 @@ function mergeConfig(userConfig) {
|
|
|
1468
1544
|
}
|
|
1469
1545
|
|
|
1470
1546
|
// Simple properties
|
|
1471
|
-
const simpleKeys = ['lang', 'position', 'theme', 'accentColor', 'autoInit', 'showWidget', 'expiration', 'policyUrl', 'imprintUrl', 'customStyles', 'mode', 'blockedDomains', 'respectDNT', 'dntBehavior'];
|
|
1547
|
+
const simpleKeys = ['lang', 'position', 'theme', 'accentColor', 'autoInit', 'showWidget', 'expiration', 'policyUrl', 'imprintUrl', 'customStyles', 'mode', 'blockedDomains', 'respectDNT', 'dntBehavior', 'consentModeGoogle', 'consentModeMicrosoft'];
|
|
1472
1548
|
for (const key of simpleKeys) {
|
|
1473
1549
|
if (userConfig[key] !== undefined) {
|
|
1474
1550
|
config[key] = userConfig[key];
|
|
@@ -1578,6 +1654,13 @@ function parseDataAttributes() {
|
|
|
1578
1654
|
const expiration = script.getAttribute('data-expiration');
|
|
1579
1655
|
if (expiration) config.expiration = parseInt(expiration, 10);
|
|
1580
1656
|
|
|
1657
|
+
// Consent mode integrations
|
|
1658
|
+
const consentModeGoogle = script.getAttribute('data-consent-mode-google');
|
|
1659
|
+
if (consentModeGoogle !== null) config.consentModeGoogle = consentModeGoogle !== 'false';
|
|
1660
|
+
|
|
1661
|
+
const consentModeMicrosoft = script.getAttribute('data-consent-mode-microsoft');
|
|
1662
|
+
if (consentModeMicrosoft !== null) config.consentModeMicrosoft = consentModeMicrosoft !== 'false';
|
|
1663
|
+
|
|
1581
1664
|
return config;
|
|
1582
1665
|
}
|
|
1583
1666
|
|
|
@@ -2809,6 +2892,8 @@ function handleAcceptAll() {
|
|
|
2809
2892
|
const result = acceptAll(config.expiration);
|
|
2810
2893
|
const categories = getCategoryIds();
|
|
2811
2894
|
|
|
2895
|
+
applyConsentSignals(result.current, config, false);
|
|
2896
|
+
|
|
2812
2897
|
hideBanner();
|
|
2813
2898
|
hideModal();
|
|
2814
2899
|
|
|
@@ -2830,6 +2915,8 @@ function handleAcceptAll() {
|
|
|
2830
2915
|
function handleRejectAll() {
|
|
2831
2916
|
const result = rejectAll(config.expiration);
|
|
2832
2917
|
|
|
2918
|
+
applyConsentSignals(result.current, config, false);
|
|
2919
|
+
|
|
2833
2920
|
hideBanner();
|
|
2834
2921
|
hideModal();
|
|
2835
2922
|
|
|
@@ -2849,6 +2936,8 @@ function handleRejectAll() {
|
|
|
2849
2936
|
function handleSavePreferences(selections) {
|
|
2850
2937
|
const result = updateConsent(selections, config.expiration);
|
|
2851
2938
|
|
|
2939
|
+
applyConsentSignals(result.current, config, false);
|
|
2940
|
+
|
|
2852
2941
|
// Find newly allowed categories
|
|
2853
2942
|
const newlyAllowed = Object.keys(result.current).filter(
|
|
2854
2943
|
cat => result.current[cat] && !result.previous[cat]
|
|
@@ -2927,6 +3016,13 @@ function init(userConfig = {}) {
|
|
|
2927
3016
|
// Merge config
|
|
2928
3017
|
config = setConfig(userConfig);
|
|
2929
3018
|
|
|
3019
|
+
// Push default denied state to vendor consent mode APIs (must happen before scripts load)
|
|
3020
|
+
applyConsentSignals(
|
|
3021
|
+
{ functional: false, analytics: false, marketing: false },
|
|
3022
|
+
config,
|
|
3023
|
+
true
|
|
3024
|
+
);
|
|
3025
|
+
|
|
2930
3026
|
// Set patterns if provided
|
|
2931
3027
|
if (config.patterns) {
|
|
2932
3028
|
setPatterns(config.patterns);
|
|
@@ -2947,6 +3043,11 @@ function init(userConfig = {}) {
|
|
|
2947
3043
|
|
|
2948
3044
|
initialized = true;
|
|
2949
3045
|
|
|
3046
|
+
// Push update for returning visitors with saved consent
|
|
3047
|
+
if (hasConsentDecision()) {
|
|
3048
|
+
applyConsentSignals(consent, config, false);
|
|
3049
|
+
}
|
|
3050
|
+
|
|
2950
3051
|
// Check Do Not Track / Global Privacy Control
|
|
2951
3052
|
const dntEnabled = isDoNotTrackEnabled();
|
|
2952
3053
|
let dntApplied = false;
|
|
@@ -2957,6 +3058,8 @@ function init(userConfig = {}) {
|
|
|
2957
3058
|
const result = rejectAll(config.expiration);
|
|
2958
3059
|
dntApplied = true;
|
|
2959
3060
|
|
|
3061
|
+
applyConsentSignals(result.current, config, false);
|
|
3062
|
+
|
|
2960
3063
|
// Emit events
|
|
2961
3064
|
emitReject(result.current);
|
|
2962
3065
|
emitChange(result.current, result.previous);
|