@freshjuice/zest 2.0.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.
Files changed (53) hide show
  1. package/dist/zest.d.ts +247 -0
  2. package/dist/zest.de.js +107 -3
  3. package/dist/zest.de.js.map +1 -1
  4. package/dist/zest.de.min.js +1 -1
  5. package/dist/zest.en.js +107 -3
  6. package/dist/zest.en.js.map +1 -1
  7. package/dist/zest.en.min.js +1 -1
  8. package/dist/zest.es.js +107 -3
  9. package/dist/zest.es.js.map +1 -1
  10. package/dist/zest.es.min.js +1 -1
  11. package/dist/zest.esm.js +107 -3
  12. package/dist/zest.esm.js.map +1 -1
  13. package/dist/zest.esm.min.js +1 -1
  14. package/dist/zest.fr.js +107 -3
  15. package/dist/zest.fr.js.map +1 -1
  16. package/dist/zest.fr.min.js +1 -1
  17. package/dist/zest.headless.d.ts +211 -0
  18. package/dist/zest.headless.esm.js +107 -3
  19. package/dist/zest.headless.esm.js.map +1 -1
  20. package/dist/zest.headless.esm.min.js +1 -1
  21. package/dist/zest.it.js +107 -3
  22. package/dist/zest.it.js.map +1 -1
  23. package/dist/zest.it.min.js +1 -1
  24. package/dist/zest.ja.js +107 -3
  25. package/dist/zest.ja.js.map +1 -1
  26. package/dist/zest.ja.min.js +1 -1
  27. package/dist/zest.js +107 -3
  28. package/dist/zest.js.map +1 -1
  29. package/dist/zest.min.js +1 -1
  30. package/dist/zest.nl.js +107 -3
  31. package/dist/zest.nl.js.map +1 -1
  32. package/dist/zest.nl.min.js +1 -1
  33. package/dist/zest.pl.js +107 -3
  34. package/dist/zest.pl.js.map +1 -1
  35. package/dist/zest.pl.min.js +1 -1
  36. package/dist/zest.pt.js +107 -3
  37. package/dist/zest.pt.js.map +1 -1
  38. package/dist/zest.pt.min.js +1 -1
  39. package/dist/zest.ru.js +107 -3
  40. package/dist/zest.ru.js.map +1 -1
  41. package/dist/zest.ru.min.js +1 -1
  42. package/dist/zest.uk.js +107 -3
  43. package/dist/zest.uk.js.map +1 -1
  44. package/dist/zest.uk.min.js +1 -1
  45. package/dist/zest.zh.js +107 -3
  46. package/dist/zest.zh.js.map +1 -1
  47. package/dist/zest.zh.min.js +1 -1
  48. package/package.json +9 -2
  49. package/src/config/defaults.js +48 -0
  50. package/src/core/pattern-matcher.js +37 -0
  51. package/src/core-lifecycle.js +23 -4
  52. package/src/types/zest.d.ts +247 -0
  53. package/src/types/zest.headless.d.ts +211 -0
package/dist/zest.min.js CHANGED
@@ -1 +1 @@
1
- var Zest=function(){"use strict";const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","`":"&#96;"};function t(t){if(null==t)return"";return("string"==typeof t?t:t+"").replace(/[&<>"'`]/g,t=>e[t])}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 i(e,t){if(e instanceof RegExp)return e;if("string"!=typeof e)return null;if(e.length>500)return null;for(const t of o)if(t.test(e))return null;try{return RegExp(e,t)}catch(e){return null}}const a=new Set(["__proto__","constructor","prototype"]);function s(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return null;const n={version:"string"==typeof e.version?e.version:null,timestamp:"number"==typeof e.timestamp&&Number.isFinite(e.timestamp)?e.timestamp:null,categories:{}},o=e.categories;if(!o||"object"!=typeof o||Array.isArray(o))return null;for(const e of t)a.has(e)||Object.prototype.hasOwnProperty.call(o,e)&&(n.categories[e]=!0===o[e]);return t.includes("essential")&&(n.categories.essential=!0),n}function r(e,...t){if("function"==typeof e)try{return e(...t)}catch(e){try{console.error("[Zest] User callback threw:",e)}catch(e){}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(e){for(const[t,n]of Object.entries(l))if(n.some(t=>t.test(e)))return t;return"marketing"}let u=null;const p=[];let g=()=>!1;function f(){return u}let m=null,b=null;const y=[],z=[];let h=()=>!1;function k(e,t,n){return new Proxy(e,{get(e,n){if("setItem"===n)return(n,o)=>{const i=d(n);h(i)?e.setItem(n,o):200>t.length&&t.push({key:n,value:o,category:i,timestamp:Date.now()})};const o=e[n];return"function"==typeof o?o.bind(e):o}})}const w={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:[...w.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:[...w.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 x(e,t){let n;try{n=new URL(e)}catch(e){return!1}const o=n.hostname.toLowerCase(),i=n.pathname.toLowerCase();for(const e of t){if("string"!=typeof e)continue;const t=e.toLowerCase();if(t.endsWith(".")){const e=t.slice(0,-1);if(o.split(".").some(t=>t===e)||o.startsWith(t))return!0;continue}const n=t.indexOf("/");if(-1!==n){const e=t.slice(0,n),a=t.slice(n);if((o===e||o.endsWith("."+e))&&i.startsWith(a))return!0;continue}if(o===t||o.endsWith("."+t))return!0}return!1}function A(e,t="safe"){const n="strict"===t?v:w;for(const[t,o]of Object.entries(n))if(x(e,o))return t;return null}const _=new Set(["functional","analytics","marketing"]),j=[];let C=null,S="safe",E=[],N=()=>!1;function M(e){if(e.hasAttribute("data-zest-allow"))return null;const t=e.getAttribute("data-consent-category"),n=t&&_.has(t)?t:null,o=e.src;if(!o)return n;const i=function(e){if(!e||0===E.length)return null;try{const t=new URL(e).hostname.toLowerCase();for(const e of E){const n="string"==typeof e?e:e.domain,o="string"==typeof e?"marketing":e.category||"marketing";if(t===n||t.endsWith("."+n))return o}}catch(e){}return null}(o);let a=null;switch(S){case"manual":break;case"safe":case"strict":a=A(o,S);break;case"doomsday":(function(e){try{const t=new URL(e).hostname,n=window.location.hostname,o=e=>e.replace(/^www\./,"");return o(t)!==o(n)}catch(e){return!1}})(o)&&(a=A(o,"strict")||"marketing")}return a||i||n}function R(e){if(e.hasAttribute("data-zest-processed"))return!1;const t=M(e);if(!t)return e.setAttribute("data-zest-processed","allowed"),!1;if(N(t))return e.setAttribute("data-zest-processed","allowed"),!1;const n={category:t,src:e.src||"",inline:e.textContent,type:e.type,async:e.async,defer:e.defer,element:e,timestamp:Date.now()};return e.setAttribute("data-zest-processed","blocked"),e.setAttribute("data-consent-category",t),e.type="text/plain",e.src&&e.removeAttribute("src"),500>j.length&&j.push(n),!0}function $(e){for(const t of e)for(const e of t.addedNodes)if("SCRIPT"!==e.nodeName||e.hasAttribute("data-zest-processed")||R(e),e.querySelectorAll){e.querySelectorAll("script:not([data-zest-processed])").forEach(R)}}function W(e="safe",t=[]){return S=e,E=t,document.querySelectorAll("script:not([data-zest-processed])").forEach(R),C=new MutationObserver($),C.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const L={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 D(){return Object.keys(L)}function T(){if("undefined"==typeof navigator)return!1;const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e||!0===navigator.globalPrivacyControl}function U(e,t,n){const o=n?"default":"update";t.consentModeGoogle&&function(e,t){if(window.dataLayer=window.dataLayer||[],"function"==typeof window.gtag)window.gtag("consent",e,t);else{function n(){window.dataLayer.push(arguments)}n("consent",e,t)}}(o,function(e){const t=e=>e?"granted":"denied";return{ad_storage:t(e.marketing),ad_user_data:t(e.marketing),ad_personalization:t(e.marketing),analytics_storage:t(e.analytics),functionality_storage:"granted",personalization_storage:t(e.functional)}}(e)),t.consentModeMicrosoft&&function(e,t){window.uetq=window.uetq||[],window.uetq.push("consent",e,t)}(o,function(e){return{ad_storage:e.marketing?"granted":"denied"}}(e))}const q={en:{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"}},categories:{essential:{label:"Essential",description:"Required for the website to function properly. Cannot be disabled."},functional:{label:"Functional",description:"Enable personalized features like language preferences and themes."},analytics:{label:"Analytics",description:"Help us understand how visitors interact with our website."},marketing:{label:"Marketing",description:"Used to deliver relevant advertisements and track campaign performance."}}},de:{labels:{banner:{title:"Wir respektieren Ihre Privatsphäre",description:'Wir verwenden Cookies, um Ihr Surferlebnis zu verbessern, personalisierte Inhalte bereitzustellen und unseren Datenverkehr zu analysieren. Mit einem Klick auf „Alle akzeptieren" stimmen Sie der Verwendung von Cookies zu.',acceptAll:"Alle akzeptieren",rejectAll:"Alle ablehnen",settings:"Einstellungen"},modal:{title:"Datenschutzeinstellungen",description:"Verwalten Sie Ihre Cookie-Einstellungen. Sie können verschiedene Arten von Cookies unten aktivieren oder deaktivieren.",save:"Einstellungen speichern",acceptAll:"Alle akzeptieren",rejectAll:"Alle ablehnen"},widget:{label:"Cookie-Einstellungen"}},categories:{essential:{label:"Notwendig",description:"Erforderlich für die ordnungsgemäße Funktion der Website. Können nicht deaktiviert werden."},functional:{label:"Funktional",description:"Ermöglichen personalisierte Funktionen wie Spracheinstellungen und Designs."},analytics:{label:"Analytisch",description:"Helfen uns zu verstehen, wie Besucher mit unserer Website interagieren."},marketing:{label:"Marketing",description:"Werden verwendet, um relevante Werbung anzuzeigen und die Kampagnenleistung zu messen."}}},es:{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."}}},fr:{labels:{banner:{title:"Nous respectons votre vie privée",description:"Nous utilisons des cookies pour améliorer votre expérience de navigation, proposer du contenu personnalisé et analyser notre trafic. En cliquant sur « Tout accepter », vous consentez à l'utilisation de cookies.",acceptAll:"Tout accepter",rejectAll:"Tout refuser",settings:"Paramètres"},modal:{title:"Paramètres de confidentialité",description:"Gérez vos préférences en matière de cookies. Vous pouvez activer ou désactiver différents types de cookies ci-dessous.",save:"Enregistrer les préférences",acceptAll:"Tout accepter",rejectAll:"Tout refuser"},widget:{label:"Paramètres des cookies"}},categories:{essential:{label:"Essentiels",description:"Nécessaires au bon fonctionnement du site. Ne peuvent pas être désactivés."},functional:{label:"Fonctionnels",description:"Permettent des fonctionnalités personnalisées comme les préférences de langue et de thème."},analytics:{label:"Analytiques",description:"Nous aident à comprendre comment les visiteurs interagissent avec notre site."},marketing:{label:"Marketing",description:"Utilisés pour afficher des publicités pertinentes et mesurer les performances des campagnes."}}},it:{labels:{banner:{title:"Rispettiamo la tua privacy",description:'Utilizziamo i cookie per migliorare la tua esperienza di navigazione, fornire contenuti personalizzati e analizzare il nostro traffico. Cliccando su "Accetta tutto", acconsenti all\'uso dei cookie.',acceptAll:"Accetta tutto",rejectAll:"Rifiuta tutto",settings:"Impostazioni"},modal:{title:"Impostazioni privacy",description:"Gestisci le tue preferenze sui cookie. Puoi attivare o disattivare diversi tipi di cookie qui sotto.",save:"Salva preferenze",acceptAll:"Accetta tutto",rejectAll:"Rifiuta tutto"},widget:{label:"Impostazioni cookie"}},categories:{essential:{label:"Essenziali",description:"Necessari per il corretto funzionamento del sito. Non possono essere disattivati."},functional:{label:"Funzionali",description:"Abilitano funzionalità personalizzate come preferenze di lingua e tema."},analytics:{label:"Analitici",description:"Ci aiutano a capire come i visitatori interagiscono con il nostro sito."},marketing:{label:"Marketing",description:"Utilizzati per mostrare annunci pertinenti e misurare le prestazioni delle campagne."}}},pt:{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."}}},nl:{labels:{banner:{title:"Wij respecteren uw privacy",description:'Wij gebruiken cookies om uw browse-ervaring te verbeteren, gepersonaliseerde inhoud aan te bieden en ons verkeer te analyseren. Door op "Alles accepteren" te klikken, stemt u in met het gebruik van cookies.',acceptAll:"Alles accepteren",rejectAll:"Alles weigeren",settings:"Instellingen"},modal:{title:"Privacy-instellingen",description:"Beheer uw cookievoorkeuren. U kunt hieronder verschillende soorten cookies in- of uitschakelen.",save:"Voorkeuren opslaan",acceptAll:"Alles accepteren",rejectAll:"Alles weigeren"},widget:{label:"Cookie-instellingen"}},categories:{essential:{label:"Essentieel",description:"Noodzakelijk voor de goede werking van de website. Kunnen niet worden uitgeschakeld."},functional:{label:"Functioneel",description:"Maken gepersonaliseerde functies mogelijk zoals taal- en themavoorkeuren."},analytics:{label:"Analytisch",description:"Helpen ons te begrijpen hoe bezoekers onze website gebruiken."},marketing:{label:"Marketing",description:"Worden gebruikt om relevante advertenties te tonen en campagneprestaties te meten."}}},pl:{labels:{banner:{title:"Szanujemy Twoją prywatność",description:'Używamy plików cookie, aby poprawić Twoje wrażenia z przeglądania, dostarczać spersonalizowane treści i analizować nasz ruch. Klikając „Zaakceptuj wszystko", wyrażasz zgodę na używanie plików cookie.',acceptAll:"Zaakceptuj wszystko",rejectAll:"Odrzuć wszystko",settings:"Ustawienia"},modal:{title:"Ustawienia prywatności",description:"Zarządzaj swoimi preferencjami dotyczącymi plików cookie. Możesz włączyć lub wyłączyć różne typy plików cookie poniżej.",save:"Zapisz preferencje",acceptAll:"Zaakceptuj wszystko",rejectAll:"Odrzuć wszystko"},widget:{label:"Ustawienia plików cookie"}},categories:{essential:{label:"Niezbędne",description:"Wymagane do prawidłowego działania strony. Nie można ich wyłączyć."},functional:{label:"Funkcjonalne",description:"Umożliwiają spersonalizowane funkcje, takie jak preferencje językowe i motywy."},analytics:{label:"Analityczne",description:"Pomagają nam zrozumieć, jak odwiedzający korzystają z naszej strony."},marketing:{label:"Marketingowe",description:"Służą do wyświetlania odpowiednich reklam i mierzenia skuteczności kampanii."}}},uk:{labels:{banner:{title:"Ми цінуємо вашу конфіденційність",description:"Ми використовуємо файли cookie для покращення вашого досвіду перегляду, надання персоналізованого контенту та аналізу нашого трафіку. Натискаючи «Прийняти все», ви погоджуєтесь на використання файлів cookie.",acceptAll:"Прийняти все",rejectAll:"Відхилити все",settings:"Налаштування"},modal:{title:"Налаштування конфіденційності",description:"Керуйте своїми налаштуваннями файлів cookie. Ви можете ввімкнути або вимкнути різні типи файлів cookie нижче.",save:"Зберегти налаштування",acceptAll:"Прийняти все",rejectAll:"Відхилити все"},widget:{label:"Налаштування cookie"}},categories:{essential:{label:"Необхідні",description:"Потрібні для правильної роботи сайту. Не можуть бути вимкнені."},functional:{label:"Функціональні",description:"Дозволяють персоналізовані функції, такі як мовні налаштування та теми."},analytics:{label:"Аналітичні",description:"Допомагають нам зрозуміти, як відвідувачі взаємодіють з нашим сайтом."},marketing:{label:"Маркетингові",description:"Використовуються для показу релевантної реклами та вимірювання ефективності кампаній."}}},ru:{labels:{banner:{title:"Мы ценим вашу конфиденциальность",description:"Мы используем файлы cookie для улучшения вашего опыта просмотра, предоставления персонализированного контента и анализа нашего трафика. Нажимая «Принять все», вы соглашаетесь на использование файлов cookie.",acceptAll:"Принять все",rejectAll:"Отклонить все",settings:"Настройки"},modal:{title:"Настройки конфиденциальности",description:"Управляйте своими настройками файлов cookie. Вы можете включить или отключить различные типы файлов cookie ниже.",save:"Сохранить настройки",acceptAll:"Принять все",rejectAll:"Отклонить все"},widget:{label:"Настройки cookie"}},categories:{essential:{label:"Необходимые",description:"Требуются для правильной работы сайта. Не могут быть отключены."},functional:{label:"Функциональные",description:"Позволяют использовать персонализированные функции, такие как языковые настройки и темы."},analytics:{label:"Аналитические",description:"Помогают нам понять, как посетители взаимодействуют с нашим сайтом."},marketing:{label:"Маркетинговые",description:"Используются для показа релевантной рекламы и измерения эффективности кампаний."}}},ja:{labels:{banner:{title:"プライバシーを尊重します",description:"当サイトでは、ブラウジング体験の向上、パーソナライズされたコンテンツの提供、トラフィックの分析のためにCookieを使用しています。「すべて同意」をクリックすると、Cookieの使用に同意したことになります。",acceptAll:"すべて同意",rejectAll:"すべて拒否",settings:"設定"},modal:{title:"プライバシー設定",description:"Cookieの設定を管理できます。以下で各種Cookieを有効または無効にできます。",save:"設定を保存",acceptAll:"すべて同意",rejectAll:"すべて拒否"},widget:{label:"Cookie設定"}},categories:{essential:{label:"必須",description:"サイトの正常な動作に必要です。無効にすることはできません。"},functional:{label:"機能性",description:"言語設定やテーマなどのパーソナライズ機能を有効にします。"},analytics:{label:"分析",description:"訪問者がサイトをどのように利用しているかを理解するのに役立ちます。"},marketing:{label:"マーケティング",description:"関連性の高い広告を表示し、キャンペーンの効果を測定するために使用されます。"}}},zh:{labels:{banner:{title:"我们重视您的隐私",description:'我们使用Cookie来改善您的浏览体验、提供个性化内容并分析我们的流量。点击"全部接受"即表示您同意我们使用Cookie。',acceptAll:"全部接受",rejectAll:"全部拒绝",settings:"设置"},modal:{title:"隐私设置",description:"管理您的Cookie偏好设置。您可以在下方启用或禁用不同类型的Cookie。",save:"保存设置",acceptAll:"全部接受",rejectAll:"全部拒绝"},widget:{label:"Cookie设置"}},categories:{essential:{label:"必要",description:"网站正常运行所必需的。无法禁用。"},functional:{label:"功能性",description:"启用个性化功能,如语言偏好和主题设置。"},analytics:{label:"分析",description:"帮助我们了解访问者如何与网站互动。"},marketing:{label:"营销",description:"用于展示相关广告并衡量营销活动效果。"}}}};function I(e){if(!e)return"en";const t=e.slice(0,2).toLowerCase();return q[t]?t:"en"}const O={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:L,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 P(e){const t={...O};e||(e={});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!==e[o]&&(t[o]=e[o]);const o=function(e){if(e&&"auto"!==e)return I(e);const t=document.documentElement.lang;if(t){const e=I(t);if(q[e])return e}if("undefined"!=typeof navigator&&navigator.language){const e=I(navigator.language);if(q[e])return e}return"en"}(t.lang);t.lang=o;const i=q[o]||q.en;const a=i.labels||{},s=e.labels||{};t.labels={banner:{...O.labels.banner,...a.banner,...s.banner},modal:{...O.labels.modal,...a.modal,...s.modal},widget:{...O.labels.widget,...a.widget,...s.widget}};const r=i.categories||{},c=e.categories||{};t.categories={...O.categories};for(const e of Object.keys(O.categories))t.categories[e]={...O.categories[e],...r[e],...c[e]};return e.callbacks&&(t.callbacks={...O.callbacks,...e.callbacks}),e.patterns&&(t.patterns=e.patterns),t}function Z(){const e="undefined"!=typeof window&&window.ZestConfig?window.ZestConfig:{},t=function(){const e=document.currentScript||document.querySelector("script[data-zest]")||document.querySelector('script[src*="zest"]');if(!e)return{};const t={},n=e.getAttribute("data-position");n&&(t.position=n);const o=e.getAttribute("data-theme");o&&(t.theme=o);const i=e.getAttribute("data-accent")||e.getAttribute("data-accent-color");i&&(t.accentColor=i);const a=e.getAttribute("data-policy-url")||e.getAttribute("data-privacy-url");a&&(t.policyUrl=a);const s=e.getAttribute("data-imprint-url");s&&(t.imprintUrl=s);const r=e.getAttribute("data-show-widget");null!==r&&(t.showWidget="false"!==r);const c=e.getAttribute("data-auto-init");null!==c&&(t.autoInit="false"!==c);const l=e.getAttribute("data-expiration");l&&(t.expiration=parseInt(l,10));const d=e.getAttribute("data-consent-mode-google");null!==d&&(t.consentModeGoogle="false"!==d);const u=e.getAttribute("data-consent-mode-microsoft");return null!==u&&(t.consentModeMicrosoft="false"!==u),t}();return P({...e,...t})}let F=null;function H(){return F||(F=Z()),F}const Y="zest_consent";function B(){try{return"undefined"!=typeof location&&"https:"===location.protocol?"; Secure":""}catch(e){return""}}let G=null;function V(e){const t=f();t?.set?t.set.call(document,e):document.cookie=e}function J(){const e=f();return e?.get?e.get.call(document):document.cookie}function K(){try{const e=J().match(RegExp(Y+"=([^;]+)"));if(e){const t=s(JSON.parse(decodeURIComponent(e[1])),D());if(t&&t.categories)return G={essential:!0,functional:!1,analytics:!1,marketing:!1,...t.categories},{...G}}}catch(e){}return G={essential:!0,functional:!1,analytics:!1,marketing:!1},{...G}}function X(){return G||(G=K()),{...G}}function Q(e,t=365){const n=G?{...G}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return G={essential:!0,functional:!!e.functional,analytics:!!e.analytics,marketing:!!e.marketing},function(e=365){G||(G={essential:!0,functional:!1,analytics:!1,marketing:!1});const t={version:"1.0",timestamp:Date.now(),categories:G},n=new Date(Date.now()+24*e*60*60*1e3).toUTCString();V(`${Y}=${encodeURIComponent(JSON.stringify(t))}; expires=${n}; path=/; SameSite=Lax${B()}`)}(t),{current:{...G},previous:n}}function ee(e){return G||(G=K()),!0===G[e]}function te(e=365){return Q({functional:!1,analytics:!1,marketing:!1},e)}function ne(){try{return J().includes(Y)}catch(e){return!1}}const oe={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function ie(e,t={}){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return document.dispatchEvent(n),n}function ae(e,t){return ie(oe.CONSENT,{consent:e,previous:t})}function se(e){return ie(oe.REJECT,{consent:e})}function re(e,t){return ie(oe.CHANGE,{consent:e,previous:t})}function ce(e="banner"){return ie(oe.SHOW,{type:e})}function le(e="banner"){return ie(oe.HIDE,{type:e})}let de=!1,ue=null;function pe(e){return ee(e)}function ge(e){!function(e){const t=[];for(const n of p)e.includes(n.category)?u?.set&&u.set.call(document,n.value):t.push(n);p.length=0,p.push(...t)}(e),function(e){const t=[];for(const n of y)e.includes(n.category)?m?.setItem(n.key,n.value):t.push(n);y.length=0,y.push(...t);const n=[];for(const t of z)e.includes(t.category)?b?.setItem(t.key,t.value):n.push(t);z.length=0,z.push(...n)}(e),function(e){const t=[];for(const n of j){if(!e.includes(n.category)){t.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 i=n.element;i&&i.isConnected&&i.parentNode?i.parentNode.replaceChild(o,i):document.head.appendChild(o)}j.length=0,j.push(...t)}(e)}function fe(e={}){if(de)return{alreadyInitialized:!0,config:ue,consent:K(),hasDecision:ne(),dntApplied:!1};F=P(e),ue=F,U({functional:!1,analytics:!1,marketing:!1},ue,!0),ue.patterns&&function(e){if(l={...c},e&&"object"==typeof e)for(const[t,n]of Object.entries(e)){if(!Array.isArray(n))continue;const e=[];for(const t of n){const n=i(t);if(n)e.push(n);else try{console.warn("[Zest] Rejected unsafe pattern:",t)}catch(e){}}l[t]=e}}(ue.patterns),g=pe,function(e){h=e}(pe),function(e){N=e}(pe),u=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),u?Object.defineProperty(document,"cookie",{get:()=>u.get.call(document),set(e){const t=function(e){const t=e.match(/^([^=]+)/);return t?t[1].trim():null}(e);if(!t)return;const n=d(t);g(n)?u.set.call(document,e):100>p.length&&p.push({value:e,name:t,category:n,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:k(m,y),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:k(b,z),configurable:!0,writable:!1}),!0}catch(e){return console.warn("[Zest] Could not intercept storage APIs:",e),!1}}(),W(ue.mode,ue.blockedDomains);const t=K();de=!0,ne()&&U(t,ue,!1);let n=!1;if(T()&&ue.respectDNT&&"ignore"!==ue.dntBehavior&&"reject"===ue.dntBehavior&&!ne()){const e=te(ue.expiration);n=!0,U(e.current,ue,!1),se(e.current),re(e.current,e.previous),r(ue.callbacks?.onReject),r(ue.callbacks?.onChange,e.current)}return function(e){ie(oe.READY,{consent:e})}(t),r(ue.callbacks?.onReady,t),{alreadyInitialized:!1,config:ue,consent:t,hasDecision:ne(),dntApplied:n}}function me(){if(!de)return null;const e=function(e=365){return Q({functional:!0,analytics:!0,marketing:!0},e)}(ue.expiration);return U(e.current,ue,!1),ge(D()),ae(e.current,e.previous),re(e.current,e.previous),r(ue.callbacks?.onAccept,e.current),r(ue.callbacks?.onChange,e.current),e}function be(){V(`${Y}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax${B()}`),G=null}function ye(){return de}function ze(){return ue}const he="#4F46E5";function ke(e){const t=function(e){if("string"!=typeof e)return null;const t=e.trim();return/^#[0-9a-fA-F]{3,8}$/.test(t)||n.has(t.toLowerCase())||/^(rgb|rgba|hsl|hsla)\(\s*[\d.,%\s/]+\s*\)$/i.test(t)?t:null}(e.accentColor)||he,o=function(e){if("string"!=typeof e||0===e.length)return"";if(e.length>2e4)return"";let t=e.replace(/\/\*[\s\S]*?\*\//g,"");return t=t.replace(/@import\s+[^;]+;?/gi,""),t=t.replace(/@charset\s+[^;]+;?/gi,""),t=t.replace(/url\(\s*(['"]?)([^)'"]+)\1\s*\)/gi,(e,t,n)=>{const o=n.trim().toLowerCase();return o.startsWith("https:")||o.startsWith("data:image/")||o.startsWith("/")||o.startsWith("#")?e:"url(#)"}),t=t.replace(/\.zest-btn--secondary\s*\{[^}]*\}/gi,""),t=t.replace(/\[data-action\s*=\s*["']reject-all["']\]\s*\{[^}]*\}/gi,""),t=t.replace(/\[data-action\s*=\s*["']accept-all["']\]\s*\{[^}]*\}/gi,""),t=t.replace(/expression\s*\([^)]*\)/gi,""),t=t.replace(/-moz-binding\s*:[^;}]*/gi,""),t}(e.customStyles);return`\n:host {\n --zest-accent: ${t};\n --zest-accent-hover: ${function(e,t){"string"==typeof e&&/^#[0-9a-fA-F]{3,8}$/.test(e.trim())||(e=he);let n=e.trim().replace("#","");3===n.length&&(n=n.split("").map(e=>e+e).join(""));8===n.length&&(n=n.slice(0,6));6!==n.length&&(n="4F46E5");const o=parseInt(n,16),i=Math.round(2.55*t);return"#"+(16777216+65536*Math.min(255,Math.max(0,(o>>16)+i))+256*Math.min(255,Math.max(0,(o>>8&255)+i))+Math.min(255,Math.max(0,(255&o)+i))).toString(16).slice(1)}(t,-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 we=null,ve=null;const xe=new Set(["bottom","bottom-left","bottom-right","top"]);function Ae(e={}){if(we)return we;const n=H();we=document.createElement("zest-banner"),we.setAttribute("data-theme",n.theme||"light"),ve=we.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=ke(n),ve.appendChild(o);const i=document.createElement("div");i.innerHTML=function(e){const n=e.labels.banner,o=e.position||"bottom";return`\n <div class="zest-banner zest-banner--${xe.has(o)?o:"bottom"}" role="dialog" aria-modal="false" aria-label="${t(n.title)}">\n <h2 class="zest-banner__title">${t(n.title)}</h2>\n <p class="zest-banner__description">${t(n.description)}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${t(n.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${t(n.rejectAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${t(n.settings)}\n </button>\n </div>\n </div>\n `}(n),ve.appendChild(i.firstElementChild);const a=ve.querySelector(".zest-banner");return a.addEventListener("click",t=>{const n=t.target.dataset.action;if(n)switch(n){case"accept-all":e.onAcceptAll?.();break;case"reject-all":e.onRejectAll?.();break;case"settings":e.onSettings?.()}}),a.addEventListener("keydown",t=>{"Escape"===t.key&&e.onSettings?.()}),document.body.appendChild(we),requestAnimationFrame(()=>{const e=ve.querySelector("button");e?.focus()}),we}function _e(e={}){we?we.classList.remove("zest-hidden"):Ae(e)}function je(){we&&(we.remove(),we=null,ve=null)}let Ce=null,Se=null,Ee={};function Ne(e,n){const o=e.labels.modal,i=Object.values(e.categories||L).map(e=>function(e,n,o){const i=o?"disabled":"",a=n?"checked":"",s=t(e.id),r=t(e.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">${r}</span>\n <p class="zest-category__description">${t(e.description)}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${s}"\n ${a}\n ${i}\n aria-label="${r}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `}(e,n[e.id]??e.default,e.required)).join(""),a=e.policyUrl?function(e){if("string"!=typeof e||0===e.length)return null;const t=e.trim();if(0===t.length)return null;if(/^[/?#]/.test(t))return t;const n=t.match(/^([a-z][a-z0-9+.-]*):/i);if(!n)return t;const o=n[1].toLowerCase();return"http"===o||"https"===o||"mailto"===o||"tel"===o?t:null}(e.policyUrl):null,s=a?`<a href="${t(a)}" 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="${t(o.title)}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${t(o.title)}</h2>\n <p class="zest-modal__description">${t(o.description)} ${s}</p>\n </div>\n <div class="zest-modal__body">\n ${i}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${t(o.save)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${t(o.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${t(o.rejectAll)}\n </button>\n </div>\n </div>\n </div>\n `}function Me(){if(!Se)return Ee;const e=Se.querySelectorAll(".zest-toggle__input"),t={essential:!0};return e.forEach(e=>{const n=e.dataset.category;n&&"essential"!==n&&(t[n]=e.checked)}),t}function Re(){Ce&&(Ce.remove(),Ce=null,Se=null)}let $e=null,We=null;function Le(e={}){if($e)return $e;const n=H();$e=document.createElement("zest-widget"),$e.setAttribute("data-theme",n.theme||"light"),We=$e.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=ke(n),We.appendChild(o);const i=document.createElement("div");i.innerHTML=function(e){const n=t(e.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),We.appendChild(i.firstElementChild);return We.querySelector(".zest-widget__btn").addEventListener("click",()=>{e.onClick?.()}),document.body.appendChild($e),$e}function De(e={}){$e?$e.style.display="":Le(e)}function Te(){$e&&($e.style.display="none")}function Ue(){me();const e=ze();je(),Re(),e?.showWidget&&De({onClick:Oe})}function qe(){!function(){if(!de)return null;const e=te(ue.expiration);U(e.current,ue,!1),se(e.current),re(e.current,e.previous),r(ue.callbacks?.onReject),r(ue.callbacks?.onChange,e.current)}();const e=ze();je(),Re(),e?.showWidget&&De({onClick:Oe})}function Ie(e){!function(e){if(!de)return null;const t=Q(e,ue.expiration);U(t.current,ue,!1);const n=Object.keys(t.current).filter(e=>t.current[e]&&!t.previous[e]);n.length>0&&ge(n),Object.entries(e||{}).some(([e,t])=>"essential"!==e&&t)?ae(t.current,t.previous):se(t.current),re(t.current,t.previous),r(ue.callbacks?.onChange,t.current)}(e);const t=ze();Re(),t?.showWidget&&De({onClick:Oe})}function Oe(){je(),Te(),function(e={},t={}){if(Ce)return Ce;const n=H();Ee={...e},Ce=document.createElement("zest-modal"),Ce.setAttribute("data-theme",n.theme||"light"),Se=Ce.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=ke(n),Se.appendChild(o);const i=document.createElement("div");i.innerHTML=Ne(n,e),Se.appendChild(i.firstElementChild);const a=Se.querySelector(".zest-modal-overlay");a.addEventListener("click",e=>{const n=e.target.dataset.action;if(n)switch(n){case"save":t.onSave?.(Me());break;case"accept-all":t.onAcceptAll?.();break;case"reject-all":t.onRejectAll?.()}else e.target===a&&t.onClose?.()}),a.addEventListener("keydown",e=>{"Escape"===e.key&&t.onClose?.()}),Se.querySelectorAll(".zest-toggle__input").forEach(e=>{e.addEventListener("change",()=>{Ee=Me()})}),document.body.appendChild(Ce),requestAnimationFrame(()=>{const e=Se.querySelector("button");e?.focus()})}(X(),{onSave:Ie,onAcceptAll:Ue,onRejectAll:qe,onClose:Pe}),ce("modal")}function Pe(){Re(),le("modal");const e=ze();ne()&&e?.showWidget?De({onClick:Oe}):_e({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe})}function Ze(e={}){const{alreadyInitialized:t,hasDecision:n,dntApplied:o}=fe(e);if(t)return console.warn("[Zest] Already initialized"),Fe;const i=ze();return n||o?i?.showWidget&&De({onClick:Oe}):(_e({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe}),ce("banner")),Fe}const Fe={init:Ze,show(){ye()?(Re(),Te(),_e({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe}),ce("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){je(),le("banner")},showSettings(){ye()?Oe():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){Re(),le("modal")},getConsent:X,hasConsent:ee,hasConsentDecision:ne,getConsentProof:function(){try{const e=J().match(RegExp(Y+"=([^;]+)"));if(e){return s(JSON.parse(decodeURIComponent(e[1])),D())}}catch(e){}return null},isDoNotTrackEnabled:T,getDNTDetails:function(){if("undefined"==typeof navigator)return{enabled:!1,source:null};const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e?{enabled:!0,source:"dnt"}:!0===navigator.globalPrivacyControl?{enabled:!0,source:"gpc"}:{enabled:!1,source:null}},acceptAll(){ye()?Ue():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){ye()?qe():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){be(),Re(),$e&&($e.remove(),$e=null,We=null),ye()&&(_e({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe}),ce("banner"))},getConfig:H,on:function(e,t){return document.addEventListener(e,t),()=>document.removeEventListener(e,t)},once:function(e,t){document.addEventListener(e,t,{once:!0})},EVENTS:oe};if("undefined"!=typeof window){try{Object.defineProperty(window,"Zest",{value:Object.freeze(Fe),writable:!1,configurable:!1,enumerable:!0})}catch(e){window.Zest=Fe}const e=()=>{!1!==Z().autoInit&&Ze(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}return Fe}();
1
+ var Zest=function(){"use strict";const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","`":"&#96;"};function t(t){if(null==t)return"";return("string"==typeof t?t:t+"").replace(/[&<>"'`]/g,t=>e[t])}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 i(e,t){if(e instanceof RegExp)return e;if("string"!=typeof e)return null;if(e.length>500)return null;for(const t of o)if(t.test(e))return null;try{return RegExp(e,t)}catch(e){return null}}const a=new Set(["__proto__","constructor","prototype"]);function s(e,t){if(!e||"object"!=typeof e||Array.isArray(e))return null;const n={version:"string"==typeof e.version?e.version:null,timestamp:"number"==typeof e.timestamp&&Number.isFinite(e.timestamp)?e.timestamp:null,categories:{}},o=e.categories;if(!o||"object"!=typeof o||Array.isArray(o))return null;for(const e of t)a.has(e)||Object.prototype.hasOwnProperty.call(o,e)&&(n.categories[e]=!0===o[e]);return t.includes("essential")&&(n.categories.essential=!0),n}function r(e,...t){if("function"==typeof e)try{return e(...t)}catch(e){try{console.error("[Zest] User callback threw:",e)}catch(e){}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(e){return(e+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function u(e){for(const[t,n]of Object.entries(l))if(n.some(t=>t.test(e)))return t;return"marketing"}let p=null;const g=[];let f=()=>!1;function m(){return p}let b=null,y=null;const z=[],h=[];let k=()=>!1;function w(e,t,n){return new Proxy(e,{get(e,n){if("setItem"===n)return(n,o)=>{const i=u(n);k(i)?e.setItem(n,o):200>t.length&&t.push({key:n,value:o,category:i,timestamp:Date.now()})};const o=e[n];return"function"==typeof o?o.bind(e):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"]},x={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 A(e,t){let n;try{n=new URL(e)}catch(e){return!1}const o=n.hostname.toLowerCase(),i=n.pathname.toLowerCase();for(const e of t){if("string"!=typeof e)continue;const t=e.toLowerCase();if(t.endsWith(".")){const e=t.slice(0,-1);if(o.split(".").some(t=>t===e)||o.startsWith(t))return!0;continue}const n=t.indexOf("/");if(-1!==n){const e=t.slice(0,n),a=t.slice(n);if((o===e||o.endsWith("."+e))&&i.startsWith(a))return!0;continue}if(o===t||o.endsWith("."+t))return!0}return!1}function _(e,t="safe"){const n="strict"===t?x:v;for(const[t,o]of Object.entries(n))if(A(e,o))return t;return null}const j=new Set(["functional","analytics","marketing"]),C=[];let S=null,E="safe",N=[],M=()=>!1;function R(e){if(e.hasAttribute("data-zest-allow"))return null;const t=e.getAttribute("data-consent-category"),n=t&&j.has(t)?t:null,o=e.src;if(!o)return n;const i=function(e){if(!e||0===N.length)return null;try{const t=new URL(e).hostname.toLowerCase();for(const e of N){const n="string"==typeof e?e:e.domain,o="string"==typeof e?"marketing":e.category||"marketing";if(t===n||t.endsWith("."+n))return o}}catch(e){}return null}(o);let a=null;switch(E){case"manual":break;case"safe":case"strict":a=_(o,E);break;case"doomsday":(function(e){try{const t=new URL(e).hostname,n=window.location.hostname,o=e=>e.replace(/^www\./,"");return o(t)!==o(n)}catch(e){return!1}})(o)&&(a=_(o,"strict")||"marketing")}return a||i||n}function $(e){if(e.hasAttribute("data-zest-processed"))return!1;const t=R(e);if(!t)return e.setAttribute("data-zest-processed","allowed"),!1;if(M(t))return e.setAttribute("data-zest-processed","allowed"),!1;const n={category:t,src:e.src||"",inline:e.textContent,type:e.type,async:e.async,defer:e.defer,element:e,timestamp:Date.now()};return e.setAttribute("data-zest-processed","blocked"),e.setAttribute("data-consent-category",t),e.type="text/plain",e.src&&e.removeAttribute("src"),500>C.length&&C.push(n),!0}function P(e){for(const t of e)for(const e of t.addedNodes)if("SCRIPT"!==e.nodeName||e.hasAttribute("data-zest-processed")||$(e),e.querySelectorAll){e.querySelectorAll("script:not([data-zest-processed])").forEach($)}}function W(e="safe",t=[]){return E=e,N=t,document.querySelectorAll("script:not([data-zest-processed])").forEach($),S=new MutationObserver(P),S.observe(document.documentElement,{childList:!0,subtree:!0}),!0}const L={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 D(){return Object.keys(L)}function T(){if("undefined"==typeof navigator)return!1;const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e||!0===navigator.globalPrivacyControl}function U(e,t,n){const o=n?"default":"update";t.consentModeGoogle&&function(e,t){if(window.dataLayer=window.dataLayer||[],"function"==typeof window.gtag)window.gtag("consent",e,t);else{function n(){window.dataLayer.push(arguments)}n("consent",e,t)}}(o,function(e){const t=e=>e?"granted":"denied";return{ad_storage:t(e.marketing),ad_user_data:t(e.marketing),ad_personalization:t(e.marketing),analytics_storage:t(e.analytics),functionality_storage:"granted",personalization_storage:t(e.functional)}}(e)),t.consentModeMicrosoft&&function(e,t){window.uetq=window.uetq||[],window.uetq.push("consent",e,t)}(o,function(e){return{ad_storage:e.marketing?"granted":"denied"}}(e))}const q={en:{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"}},categories:{essential:{label:"Essential",description:"Required for the website to function properly. Cannot be disabled."},functional:{label:"Functional",description:"Enable personalized features like language preferences and themes."},analytics:{label:"Analytics",description:"Help us understand how visitors interact with our website."},marketing:{label:"Marketing",description:"Used to deliver relevant advertisements and track campaign performance."}}},de:{labels:{banner:{title:"Wir respektieren Ihre Privatsphäre",description:'Wir verwenden Cookies, um Ihr Surferlebnis zu verbessern, personalisierte Inhalte bereitzustellen und unseren Datenverkehr zu analysieren. Mit einem Klick auf „Alle akzeptieren" stimmen Sie der Verwendung von Cookies zu.',acceptAll:"Alle akzeptieren",rejectAll:"Alle ablehnen",settings:"Einstellungen"},modal:{title:"Datenschutzeinstellungen",description:"Verwalten Sie Ihre Cookie-Einstellungen. Sie können verschiedene Arten von Cookies unten aktivieren oder deaktivieren.",save:"Einstellungen speichern",acceptAll:"Alle akzeptieren",rejectAll:"Alle ablehnen"},widget:{label:"Cookie-Einstellungen"}},categories:{essential:{label:"Notwendig",description:"Erforderlich für die ordnungsgemäße Funktion der Website. Können nicht deaktiviert werden."},functional:{label:"Funktional",description:"Ermöglichen personalisierte Funktionen wie Spracheinstellungen und Designs."},analytics:{label:"Analytisch",description:"Helfen uns zu verstehen, wie Besucher mit unserer Website interagieren."},marketing:{label:"Marketing",description:"Werden verwendet, um relevante Werbung anzuzeigen und die Kampagnenleistung zu messen."}}},es:{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."}}},fr:{labels:{banner:{title:"Nous respectons votre vie privée",description:"Nous utilisons des cookies pour améliorer votre expérience de navigation, proposer du contenu personnalisé et analyser notre trafic. En cliquant sur « Tout accepter », vous consentez à l'utilisation de cookies.",acceptAll:"Tout accepter",rejectAll:"Tout refuser",settings:"Paramètres"},modal:{title:"Paramètres de confidentialité",description:"Gérez vos préférences en matière de cookies. Vous pouvez activer ou désactiver différents types de cookies ci-dessous.",save:"Enregistrer les préférences",acceptAll:"Tout accepter",rejectAll:"Tout refuser"},widget:{label:"Paramètres des cookies"}},categories:{essential:{label:"Essentiels",description:"Nécessaires au bon fonctionnement du site. Ne peuvent pas être désactivés."},functional:{label:"Fonctionnels",description:"Permettent des fonctionnalités personnalisées comme les préférences de langue et de thème."},analytics:{label:"Analytiques",description:"Nous aident à comprendre comment les visiteurs interagissent avec notre site."},marketing:{label:"Marketing",description:"Utilisés pour afficher des publicités pertinentes et mesurer les performances des campagnes."}}},it:{labels:{banner:{title:"Rispettiamo la tua privacy",description:'Utilizziamo i cookie per migliorare la tua esperienza di navigazione, fornire contenuti personalizzati e analizzare il nostro traffico. Cliccando su "Accetta tutto", acconsenti all\'uso dei cookie.',acceptAll:"Accetta tutto",rejectAll:"Rifiuta tutto",settings:"Impostazioni"},modal:{title:"Impostazioni privacy",description:"Gestisci le tue preferenze sui cookie. Puoi attivare o disattivare diversi tipi di cookie qui sotto.",save:"Salva preferenze",acceptAll:"Accetta tutto",rejectAll:"Rifiuta tutto"},widget:{label:"Impostazioni cookie"}},categories:{essential:{label:"Essenziali",description:"Necessari per il corretto funzionamento del sito. Non possono essere disattivati."},functional:{label:"Funzionali",description:"Abilitano funzionalità personalizzate come preferenze di lingua e tema."},analytics:{label:"Analitici",description:"Ci aiutano a capire come i visitatori interagiscono con il nostro sito."},marketing:{label:"Marketing",description:"Utilizzati per mostrare annunci pertinenti e misurare le prestazioni delle campagne."}}},pt:{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."}}},nl:{labels:{banner:{title:"Wij respecteren uw privacy",description:'Wij gebruiken cookies om uw browse-ervaring te verbeteren, gepersonaliseerde inhoud aan te bieden en ons verkeer te analyseren. Door op "Alles accepteren" te klikken, stemt u in met het gebruik van cookies.',acceptAll:"Alles accepteren",rejectAll:"Alles weigeren",settings:"Instellingen"},modal:{title:"Privacy-instellingen",description:"Beheer uw cookievoorkeuren. U kunt hieronder verschillende soorten cookies in- of uitschakelen.",save:"Voorkeuren opslaan",acceptAll:"Alles accepteren",rejectAll:"Alles weigeren"},widget:{label:"Cookie-instellingen"}},categories:{essential:{label:"Essentieel",description:"Noodzakelijk voor de goede werking van de website. Kunnen niet worden uitgeschakeld."},functional:{label:"Functioneel",description:"Maken gepersonaliseerde functies mogelijk zoals taal- en themavoorkeuren."},analytics:{label:"Analytisch",description:"Helpen ons te begrijpen hoe bezoekers onze website gebruiken."},marketing:{label:"Marketing",description:"Worden gebruikt om relevante advertenties te tonen en campagneprestaties te meten."}}},pl:{labels:{banner:{title:"Szanujemy Twoją prywatność",description:'Używamy plików cookie, aby poprawić Twoje wrażenia z przeglądania, dostarczać spersonalizowane treści i analizować nasz ruch. Klikając „Zaakceptuj wszystko", wyrażasz zgodę na używanie plików cookie.',acceptAll:"Zaakceptuj wszystko",rejectAll:"Odrzuć wszystko",settings:"Ustawienia"},modal:{title:"Ustawienia prywatności",description:"Zarządzaj swoimi preferencjami dotyczącymi plików cookie. Możesz włączyć lub wyłączyć różne typy plików cookie poniżej.",save:"Zapisz preferencje",acceptAll:"Zaakceptuj wszystko",rejectAll:"Odrzuć wszystko"},widget:{label:"Ustawienia plików cookie"}},categories:{essential:{label:"Niezbędne",description:"Wymagane do prawidłowego działania strony. Nie można ich wyłączyć."},functional:{label:"Funkcjonalne",description:"Umożliwiają spersonalizowane funkcje, takie jak preferencje językowe i motywy."},analytics:{label:"Analityczne",description:"Pomagają nam zrozumieć, jak odwiedzający korzystają z naszej strony."},marketing:{label:"Marketingowe",description:"Służą do wyświetlania odpowiednich reklam i mierzenia skuteczności kampanii."}}},uk:{labels:{banner:{title:"Ми цінуємо вашу конфіденційність",description:"Ми використовуємо файли cookie для покращення вашого досвіду перегляду, надання персоналізованого контенту та аналізу нашого трафіку. Натискаючи «Прийняти все», ви погоджуєтесь на використання файлів cookie.",acceptAll:"Прийняти все",rejectAll:"Відхилити все",settings:"Налаштування"},modal:{title:"Налаштування конфіденційності",description:"Керуйте своїми налаштуваннями файлів cookie. Ви можете ввімкнути або вимкнути різні типи файлів cookie нижче.",save:"Зберегти налаштування",acceptAll:"Прийняти все",rejectAll:"Відхилити все"},widget:{label:"Налаштування cookie"}},categories:{essential:{label:"Необхідні",description:"Потрібні для правильної роботи сайту. Не можуть бути вимкнені."},functional:{label:"Функціональні",description:"Дозволяють персоналізовані функції, такі як мовні налаштування та теми."},analytics:{label:"Аналітичні",description:"Допомагають нам зрозуміти, як відвідувачі взаємодіють з нашим сайтом."},marketing:{label:"Маркетингові",description:"Використовуються для показу релевантної реклами та вимірювання ефективності кампаній."}}},ru:{labels:{banner:{title:"Мы ценим вашу конфиденциальность",description:"Мы используем файлы cookie для улучшения вашего опыта просмотра, предоставления персонализированного контента и анализа нашего трафика. Нажимая «Принять все», вы соглашаетесь на использование файлов cookie.",acceptAll:"Принять все",rejectAll:"Отклонить все",settings:"Настройки"},modal:{title:"Настройки конфиденциальности",description:"Управляйте своими настройками файлов cookie. Вы можете включить или отключить различные типы файлов cookie ниже.",save:"Сохранить настройки",acceptAll:"Принять все",rejectAll:"Отклонить все"},widget:{label:"Настройки cookie"}},categories:{essential:{label:"Необходимые",description:"Требуются для правильной работы сайта. Не могут быть отключены."},functional:{label:"Функциональные",description:"Позволяют использовать персонализированные функции, такие как языковые настройки и темы."},analytics:{label:"Аналитические",description:"Помогают нам понять, как посетители взаимодействуют с нашим сайтом."},marketing:{label:"Маркетинговые",description:"Используются для показа релевантной рекламы и измерения эффективности кампаний."}}},ja:{labels:{banner:{title:"プライバシーを尊重します",description:"当サイトでは、ブラウジング体験の向上、パーソナライズされたコンテンツの提供、トラフィックの分析のためにCookieを使用しています。「すべて同意」をクリックすると、Cookieの使用に同意したことになります。",acceptAll:"すべて同意",rejectAll:"すべて拒否",settings:"設定"},modal:{title:"プライバシー設定",description:"Cookieの設定を管理できます。以下で各種Cookieを有効または無効にできます。",save:"設定を保存",acceptAll:"すべて同意",rejectAll:"すべて拒否"},widget:{label:"Cookie設定"}},categories:{essential:{label:"必須",description:"サイトの正常な動作に必要です。無効にすることはできません。"},functional:{label:"機能性",description:"言語設定やテーマなどのパーソナライズ機能を有効にします。"},analytics:{label:"分析",description:"訪問者がサイトをどのように利用しているかを理解するのに役立ちます。"},marketing:{label:"マーケティング",description:"関連性の高い広告を表示し、キャンペーンの効果を測定するために使用されます。"}}},zh:{labels:{banner:{title:"我们重视您的隐私",description:'我们使用Cookie来改善您的浏览体验、提供个性化内容并分析我们的流量。点击"全部接受"即表示您同意我们使用Cookie。',acceptAll:"全部接受",rejectAll:"全部拒绝",settings:"设置"},modal:{title:"隐私设置",description:"管理您的Cookie偏好设置。您可以在下方启用或禁用不同类型的Cookie。",save:"保存设置",acceptAll:"全部接受",rejectAll:"全部拒绝"},widget:{label:"Cookie设置"}},categories:{essential:{label:"必要",description:"网站正常运行所必需的。无法禁用。"},functional:{label:"功能性",description:"启用个性化功能,如语言偏好和主题设置。"},analytics:{label:"分析",description:"帮助我们了解访问者如何与网站互动。"},marketing:{label:"营销",description:"用于展示相关广告并衡量营销活动效果。"}}}};function I(e){if(!e)return"en";const t=e.slice(0,2).toLowerCase();return q[t]?t:"en"}const O={lang:"auto",position:"bottom",theme:"auto",accentColor:"#0071e3",categories:L,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 Z(e){const t={...O};e||(e={});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!==e[o]&&(t[o]=e[o]);const o=function(e){if(e&&"auto"!==e)return I(e);const t=document.documentElement.lang;if(t){const e=I(t);if(q[e])return e}if("undefined"!=typeof navigator&&navigator.language){const e=I(navigator.language);if(q[e])return e}return"en"}(t.lang);t.lang=o;const i=q[o]||q.en;const a=i.labels||{},s=e.labels||{};t.labels={banner:{...O.labels.banner,...a.banner,...s.banner},modal:{...O.labels.modal,...a.modal,...s.modal},widget:{...O.labels.widget,...a.widget,...s.widget}};const r=i.categories||{},c=e.categories||{};t.categories={...O.categories};for(const e of Object.keys(O.categories))t.categories[e]={...O.categories[e],...r[e],...c[e]};return e.callbacks&&(t.callbacks={...O.callbacks,...e.callbacks}),e.patterns&&(t.patterns=e.patterns),e.intercept&&"object"==typeof e.intercept&&(t.intercept={...O.intercept,...e.intercept}),Array.isArray(e.essentialKeys)&&(t.essentialKeys=e.essentialKeys.filter(e=>"string"==typeof e&&e.length>0&&200>=e.length)),Array.isArray(e.essentialPatterns)&&(t.essentialPatterns=e.essentialPatterns.filter(e=>"string"==typeof e&&e.length>0&&500>=e.length)),t}function F(){const e="undefined"!=typeof window&&window.ZestConfig?window.ZestConfig:{},t=function(){const e=document.currentScript||document.querySelector("script[data-zest]")||document.querySelector('script[src*="zest"]');if(!e)return{};const t={},n=e.getAttribute("data-position");n&&(t.position=n);const o=e.getAttribute("data-theme");o&&(t.theme=o);const i=e.getAttribute("data-accent")||e.getAttribute("data-accent-color");i&&(t.accentColor=i);const a=e.getAttribute("data-policy-url")||e.getAttribute("data-privacy-url");a&&(t.policyUrl=a);const s=e.getAttribute("data-imprint-url");s&&(t.imprintUrl=s);const r=e.getAttribute("data-show-widget");null!==r&&(t.showWidget="false"!==r);const c=e.getAttribute("data-auto-init");null!==c&&(t.autoInit="false"!==c);const l=e.getAttribute("data-expiration");l&&(t.expiration=parseInt(l,10));const d=e.getAttribute("data-consent-mode-google");null!==d&&(t.consentModeGoogle="false"!==d);const u=e.getAttribute("data-consent-mode-microsoft");return null!==u&&(t.consentModeMicrosoft="false"!==u),t}();return Z({...e,...t})}let H=null;function Y(){return H||(H=F()),H}const B="zest_consent";function G(){try{return"undefined"!=typeof location&&"https:"===location.protocol?"; Secure":""}catch(e){return""}}let K=null;function V(e){const t=m();t?.set?t.set.call(document,e):document.cookie=e}function J(){const e=m();return e?.get?e.get.call(document):document.cookie}function X(){try{const e=J().match(RegExp(B+"=([^;]+)"));if(e){const t=s(JSON.parse(decodeURIComponent(e[1])),D());if(t&&t.categories)return K={essential:!0,functional:!1,analytics:!1,marketing:!1,...t.categories},{...K}}}catch(e){}return K={essential:!0,functional:!1,analytics:!1,marketing:!1},{...K}}function Q(){return K||(K=X()),{...K}}function ee(e,t=365){const n=K?{...K}:{essential:!0,functional:!1,analytics:!1,marketing:!1};return K={essential:!0,functional:!!e.functional,analytics:!!e.analytics,marketing:!!e.marketing},function(e=365){K||(K={essential:!0,functional:!1,analytics:!1,marketing:!1});const t={version:"1.0",timestamp:Date.now(),categories:K},n=new Date(Date.now()+24*e*60*60*1e3).toUTCString();V(`${B}=${encodeURIComponent(JSON.stringify(t))}; expires=${n}; path=/; SameSite=Lax${G()}`)}(t),{current:{...K},previous:n}}function te(e){return K||(K=X()),!0===K[e]}function ne(e=365){return ee({functional:!1,analytics:!1,marketing:!1},e)}function oe(){try{return J().includes(B)}catch(e){return!1}}const ie={READY:"zest:ready",CONSENT:"zest:consent",REJECT:"zest:reject",CHANGE:"zest:change",SHOW:"zest:show",HIDE:"zest:hide"};function ae(e,t={}){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return document.dispatchEvent(n),n}function se(e,t){return ae(ie.CONSENT,{consent:e,previous:t})}function re(e){return ae(ie.REJECT,{consent:e})}function ce(e,t){return ae(ie.CHANGE,{consent:e,previous:t})}function le(e="banner"){return ae(ie.SHOW,{type:e})}function de(e="banner"){return ae(ie.HIDE,{type:e})}let ue=!1,pe=null;function ge(e){return te(e)}function fe(e){!function(e){const t=[];for(const n of g)e.includes(n.category)?p?.set&&p.set.call(document,n.value):t.push(n);g.length=0,g.push(...t)}(e),function(e){const t=[];for(const n of z)e.includes(n.category)?b?.setItem(n.key,n.value):t.push(n);z.length=0,z.push(...t);const n=[];for(const t of h)e.includes(t.category)?y?.setItem(t.key,t.value):n.push(t);h.length=0,h.push(...n)}(e),function(e){const t=[];for(const n of C){if(!e.includes(n.category)){t.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 i=n.element;i&&i.isConnected&&i.parentNode?i.parentNode.replaceChild(o,i):document.head.appendChild(o)}C.length=0,C.push(...t)}(e)}function me(e={}){if(ue)return{alreadyInitialized:!0,config:pe,consent:X(),hasDecision:oe(),dntApplied:!1};H=Z(e),pe=H,U({functional:!1,analytics:!1,marketing:!1},pe,!0),pe.patterns&&function(e){if(l={...c},e&&"object"==typeof e)for(const[t,n]of Object.entries(e)){if(!Array.isArray(n))continue;const e=[];for(const t of n){const n=i(t);if(n)e.push(n);else try{console.warn("[Zest] Rejected unsafe pattern:",t)}catch(e){}}l[t]=e}}(pe.patterns),(Array.isArray(pe.essentialKeys)&&pe.essentialKeys.length>0||Array.isArray(pe.essentialPatterns)&&pe.essentialPatterns.length>0)&&function(e,{keys:t=[],patternStrings:n=[]}={}){l[e]||(l[e]=[]);for(const n of t){if("string"!=typeof n||!n)continue;const t=i(`^${d(n)}$`);t&&l[e].push(t)}for(const t of n){if("string"!=typeof t||!t)continue;const n=i(t);n&&l[e].push(n)}}("essential",{keys:pe.essentialKeys,patternStrings:pe.essentialPatterns}),f=ge,function(e){k=e}(ge),function(e){M=e}(ge);const t=pe.intercept||{cookies:!0,storage:!0,scripts:!0};!1!==t.cookies&&(p=Object.getOwnPropertyDescriptor(Document.prototype,"cookie"),p?Object.defineProperty(document,"cookie",{get:()=>p.get.call(document),set(e){const t=function(e){const t=e.match(/^([^=]+)/);return t?t[1].trim():null}(e);if(!t)return;const n=u(t);f(n)?p.set.call(document,e):100>g.length&&g.push({value:e,name:t,category:n,timestamp:Date.now()})},configurable:!1}):console.warn("[Zest] Could not get cookie descriptor")),!1!==t.storage&&function(){try{return b=window.localStorage,y=window.sessionStorage,Object.defineProperty(window,"localStorage",{value:w(b,z),configurable:!0,writable:!1}),Object.defineProperty(window,"sessionStorage",{value:w(y,h),configurable:!0,writable:!1}),!0}catch(e){return console.warn("[Zest] Could not intercept storage APIs:",e),!1}}(),!1!==t.scripts&&W(pe.mode,pe.blockedDomains);const n=X();ue=!0,oe()&&U(n,pe,!1);let o=!1;if(T()&&pe.respectDNT&&"ignore"!==pe.dntBehavior&&"reject"===pe.dntBehavior&&!oe()){const e=ne(pe.expiration);o=!0,U(e.current,pe,!1),re(e.current),ce(e.current,e.previous),r(pe.callbacks?.onReject),r(pe.callbacks?.onChange,e.current)}return function(e){ae(ie.READY,{consent:e})}(n),r(pe.callbacks?.onReady,n),{alreadyInitialized:!1,config:pe,consent:n,hasDecision:oe(),dntApplied:o}}function be(){if(!ue)return null;const e=function(e=365){return ee({functional:!0,analytics:!0,marketing:!0},e)}(pe.expiration);return U(e.current,pe,!1),fe(D()),se(e.current,e.previous),ce(e.current,e.previous),r(pe.callbacks?.onAccept,e.current),r(pe.callbacks?.onChange,e.current),e}function ye(){V(`${B}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; SameSite=Lax${G()}`),K=null}function ze(){return ue}function he(){return pe}const ke="#4F46E5";function we(e){const t=function(e){if("string"!=typeof e)return null;const t=e.trim();return/^#[0-9a-fA-F]{3,8}$/.test(t)||n.has(t.toLowerCase())||/^(rgb|rgba|hsl|hsla)\(\s*[\d.,%\s/]+\s*\)$/i.test(t)?t:null}(e.accentColor)||ke,o=function(e){if("string"!=typeof e||0===e.length)return"";if(e.length>2e4)return"";let t=e.replace(/\/\*[\s\S]*?\*\//g,"");return t=t.replace(/@import\s+[^;]+;?/gi,""),t=t.replace(/@charset\s+[^;]+;?/gi,""),t=t.replace(/url\(\s*(['"]?)([^)'"]+)\1\s*\)/gi,(e,t,n)=>{const o=n.trim().toLowerCase();return o.startsWith("https:")||o.startsWith("data:image/")||o.startsWith("/")||o.startsWith("#")?e:"url(#)"}),t=t.replace(/\.zest-btn--secondary\s*\{[^}]*\}/gi,""),t=t.replace(/\[data-action\s*=\s*["']reject-all["']\]\s*\{[^}]*\}/gi,""),t=t.replace(/\[data-action\s*=\s*["']accept-all["']\]\s*\{[^}]*\}/gi,""),t=t.replace(/expression\s*\([^)]*\)/gi,""),t=t.replace(/-moz-binding\s*:[^;}]*/gi,""),t}(e.customStyles);return`\n:host {\n --zest-accent: ${t};\n --zest-accent-hover: ${function(e,t){"string"==typeof e&&/^#[0-9a-fA-F]{3,8}$/.test(e.trim())||(e=ke);let n=e.trim().replace("#","");3===n.length&&(n=n.split("").map(e=>e+e).join(""));8===n.length&&(n=n.slice(0,6));6!==n.length&&(n="4F46E5");const o=parseInt(n,16),i=Math.round(2.55*t);return"#"+(16777216+65536*Math.min(255,Math.max(0,(o>>16)+i))+256*Math.min(255,Math.max(0,(o>>8&255)+i))+Math.min(255,Math.max(0,(255&o)+i))).toString(16).slice(1)}(t,-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 ve=null,xe=null;const Ae=new Set(["bottom","bottom-left","bottom-right","top"]);function _e(e={}){if(ve)return ve;const n=Y();ve=document.createElement("zest-banner"),ve.setAttribute("data-theme",n.theme||"light"),xe=ve.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=we(n),xe.appendChild(o);const i=document.createElement("div");i.innerHTML=function(e){const n=e.labels.banner,o=e.position||"bottom";return`\n <div class="zest-banner zest-banner--${Ae.has(o)?o:"bottom"}" role="dialog" aria-modal="false" aria-label="${t(n.title)}">\n <h2 class="zest-banner__title">${t(n.title)}</h2>\n <p class="zest-banner__description">${t(n.description)}</p>\n <div class="zest-banner__buttons">\n <button type="button" class="zest-btn zest-btn--primary" data-action="accept-all">\n ${t(n.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="reject-all">\n ${t(n.rejectAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="settings">\n ${t(n.settings)}\n </button>\n </div>\n </div>\n `}(n),xe.appendChild(i.firstElementChild);const a=xe.querySelector(".zest-banner");return a.addEventListener("click",t=>{const n=t.target.dataset.action;if(n)switch(n){case"accept-all":e.onAcceptAll?.();break;case"reject-all":e.onRejectAll?.();break;case"settings":e.onSettings?.()}}),a.addEventListener("keydown",t=>{"Escape"===t.key&&e.onSettings?.()}),document.body.appendChild(ve),requestAnimationFrame(()=>{const e=xe.querySelector("button");e?.focus()}),ve}function je(e={}){ve?ve.classList.remove("zest-hidden"):_e(e)}function Ce(){ve&&(ve.remove(),ve=null,xe=null)}let Se=null,Ee=null,Ne={};function Me(e,n){const o=e.labels.modal,i=Object.values(e.categories||L).map(e=>function(e,n,o){const i=o?"disabled":"",a=n?"checked":"",s=t(e.id),r=t(e.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">${r}</span>\n <p class="zest-category__description">${t(e.description)}</p>\n </div>\n <label class="zest-toggle">\n <input\n type="checkbox"\n class="zest-toggle__input"\n data-category="${s}"\n ${a}\n ${i}\n aria-label="${r}"\n >\n <span class="zest-toggle__slider"></span>\n </label>\n </div>\n </div>\n `}(e,n[e.id]??e.default,e.required)).join(""),a=e.policyUrl?function(e){if("string"!=typeof e||0===e.length)return null;const t=e.trim();if(0===t.length)return null;if(/^[/?#]/.test(t))return t;const n=t.match(/^([a-z][a-z0-9+.-]*):/i);if(!n)return t;const o=n[1].toLowerCase();return"http"===o||"https"===o||"mailto"===o||"tel"===o?t:null}(e.policyUrl):null,s=a?`<a href="${t(a)}" 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="${t(o.title)}">\n <div class="zest-modal">\n <div class="zest-modal__header">\n <h2 class="zest-modal__title">${t(o.title)}</h2>\n <p class="zest-modal__description">${t(o.description)} ${s}</p>\n </div>\n <div class="zest-modal__body">\n ${i}\n </div>\n <div class="zest-modal__footer">\n <button type="button" class="zest-btn zest-btn--primary" data-action="save">\n ${t(o.save)}\n </button>\n <button type="button" class="zest-btn zest-btn--secondary" data-action="accept-all">\n ${t(o.acceptAll)}\n </button>\n <button type="button" class="zest-btn zest-btn--ghost" data-action="reject-all">\n ${t(o.rejectAll)}\n </button>\n </div>\n </div>\n </div>\n `}function Re(){if(!Ee)return Ne;const e=Ee.querySelectorAll(".zest-toggle__input"),t={essential:!0};return e.forEach(e=>{const n=e.dataset.category;n&&"essential"!==n&&(t[n]=e.checked)}),t}function $e(){Se&&(Se.remove(),Se=null,Ee=null)}let Pe=null,We=null;function Le(e={}){if(Pe)return Pe;const n=Y();Pe=document.createElement("zest-widget"),Pe.setAttribute("data-theme",n.theme||"light"),We=Pe.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=we(n),We.appendChild(o);const i=document.createElement("div");i.innerHTML=function(e){const n=t(e.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),We.appendChild(i.firstElementChild);return We.querySelector(".zest-widget__btn").addEventListener("click",()=>{e.onClick?.()}),document.body.appendChild(Pe),Pe}function De(e={}){Pe?Pe.style.display="":Le(e)}function Te(){Pe&&(Pe.style.display="none")}function Ue(){be();const e=he();Ce(),$e(),e?.showWidget&&De({onClick:Oe})}function qe(){!function(){if(!ue)return null;const e=ne(pe.expiration);U(e.current,pe,!1),re(e.current),ce(e.current,e.previous),r(pe.callbacks?.onReject),r(pe.callbacks?.onChange,e.current)}();const e=he();Ce(),$e(),e?.showWidget&&De({onClick:Oe})}function Ie(e){!function(e){if(!ue)return null;const t=ee(e,pe.expiration);U(t.current,pe,!1);const n=Object.keys(t.current).filter(e=>t.current[e]&&!t.previous[e]);n.length>0&&fe(n),Object.entries(e||{}).some(([e,t])=>"essential"!==e&&t)?se(t.current,t.previous):re(t.current),ce(t.current,t.previous),r(pe.callbacks?.onChange,t.current)}(e);const t=he();$e(),t?.showWidget&&De({onClick:Oe})}function Oe(){Ce(),Te(),function(e={},t={}){if(Se)return Se;const n=Y();Ne={...e},Se=document.createElement("zest-modal"),Se.setAttribute("data-theme",n.theme||"light"),Ee=Se.attachShadow({mode:"open"});const o=document.createElement("style");o.textContent=we(n),Ee.appendChild(o);const i=document.createElement("div");i.innerHTML=Me(n,e),Ee.appendChild(i.firstElementChild);const a=Ee.querySelector(".zest-modal-overlay");a.addEventListener("click",e=>{const n=e.target.dataset.action;if(n)switch(n){case"save":t.onSave?.(Re());break;case"accept-all":t.onAcceptAll?.();break;case"reject-all":t.onRejectAll?.()}else e.target===a&&t.onClose?.()}),a.addEventListener("keydown",e=>{"Escape"===e.key&&t.onClose?.()}),Ee.querySelectorAll(".zest-toggle__input").forEach(e=>{e.addEventListener("change",()=>{Ne=Re()})}),document.body.appendChild(Se),requestAnimationFrame(()=>{const e=Ee.querySelector("button");e?.focus()})}(Q(),{onSave:Ie,onAcceptAll:Ue,onRejectAll:qe,onClose:Ze}),le("modal")}function Ze(){$e(),de("modal");const e=he();oe()&&e?.showWidget?De({onClick:Oe}):je({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe})}function Fe(e={}){const{alreadyInitialized:t,hasDecision:n,dntApplied:o}=me(e);if(t)return console.warn("[Zest] Already initialized"),He;const i=he();return n||o?i?.showWidget&&De({onClick:Oe}):(je({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe}),le("banner")),He}const He={init:Fe,show(){ze()?($e(),Te(),je({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe}),le("banner")):console.warn("[Zest] Not initialized. Call Zest.init() first.")},hide(){Ce(),de("banner")},showSettings(){ze()?Oe():console.warn("[Zest] Not initialized. Call Zest.init() first.")},hideSettings(){$e(),de("modal")},getConsent:Q,hasConsent:te,hasConsentDecision:oe,getConsentProof:function(){try{const e=J().match(RegExp(B+"=([^;]+)"));if(e){return s(JSON.parse(decodeURIComponent(e[1])),D())}}catch(e){}return null},isDoNotTrackEnabled:T,getDNTDetails:function(){if("undefined"==typeof navigator)return{enabled:!1,source:null};const e=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack;return"1"===e||"yes"===e||!0===e?{enabled:!0,source:"dnt"}:!0===navigator.globalPrivacyControl?{enabled:!0,source:"gpc"}:{enabled:!1,source:null}},acceptAll(){ze()?Ue():console.warn("[Zest] Not initialized. Call Zest.init() first.")},rejectAll(){ze()?qe():console.warn("[Zest] Not initialized. Call Zest.init() first.")},reset(){ye(),$e(),Pe&&(Pe.remove(),Pe=null,We=null),ze()&&(je({onAcceptAll:Ue,onRejectAll:qe,onSettings:Oe}),le("banner"))},getConfig:Y,on:function(e,t){return document.addEventListener(e,t),()=>document.removeEventListener(e,t)},once:function(e,t){document.addEventListener(e,t,{once:!0})},EVENTS:ie};if("undefined"!=typeof window){try{Object.defineProperty(window,"Zest",{value:Object.freeze(He),writable:!1,configurable:!1,enumerable:!0})}catch(e){window.Zest=He}const e=()=>{!1!==F().autoInit&&Fe(window.ZestConfig)};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}return He}();
package/dist/zest.nl.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
- interceptCookies();
1824
- interceptStorage();
1825
- startScriptBlocking(currentConfig.mode, currentConfig.blockedDomains);
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;