@consenti/api 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +917 -207
- package/dist/chunk-IY4L6MNB.js +2 -0
- package/dist/chunk-IY4L6MNB.js.map +1 -0
- package/dist/chunk-O5UG4OYI.js +2 -0
- package/dist/chunk-O5UG4OYI.js.map +1 -0
- package/dist/dashboard/assets/ApiConfig-CE-Noelz.js +1 -0
- package/dist/dashboard/assets/ArchivedProfileList-Bw-fx-BD.js +1 -0
- package/dist/dashboard/assets/AuditLog-D6HiTQ1o.js +1 -0
- package/dist/dashboard/assets/ChangePassword-D2rPkzD1.js +1 -0
- package/dist/dashboard/assets/ConfirmDialog-DTtw7VJ-.js +1 -0
- package/dist/dashboard/assets/ConsentList-BWOvPOMG.js +1 -0
- package/dist/dashboard/assets/ConsentTemplateEditor-BKIEnLmA.js +1 -0
- package/dist/dashboard/assets/ConsentTemplateList-DCys2nM3.js +1 -0
- package/dist/dashboard/assets/HeadingTagInput-BTjrdzlS.js +1 -0
- package/dist/dashboard/assets/HowItWorks-AeyjfQGO.js +1 -0
- package/dist/dashboard/assets/PermissionGate-Bhhf7SMh.js +1 -0
- package/dist/dashboard/assets/PreviewPane-Dq5K1h2L.js +35 -0
- package/dist/dashboard/assets/ProfileEditor-BXtaE0tL.js +2 -0
- package/dist/dashboard/assets/ProfileList-CWKSAgu0.js +1 -0
- package/dist/dashboard/assets/ProfileVersionHistory-1h8sUgog.js +3 -0
- package/dist/dashboard/assets/RecordDetailModal-FaFhzQXi.js +1 -0
- package/dist/dashboard/assets/Reports-DWEjQOKh.js +1 -0
- package/dist/dashboard/assets/RoleList-BSGoqlzp.js +1 -0
- package/dist/dashboard/assets/Select-DjJNwlbY.js +1 -0
- package/dist/dashboard/assets/Settings-CVYrlyLm.js +1 -0
- package/dist/dashboard/assets/SetupWizard-4NTb5bZj.js +1 -0
- package/dist/dashboard/assets/Table-DH_jh8_N.js +1 -0
- package/dist/dashboard/assets/TenantList-5AwFtoHf.js +1 -0
- package/dist/dashboard/assets/UITemplateEditor-9A55scBe.js +1 -0
- package/dist/dashboard/assets/UITemplateList-BS7X4u4F.js +1 -0
- package/dist/dashboard/assets/UserList-SPkMyFRy.js +1 -0
- package/dist/dashboard/assets/VendorList-C5fPhr6U.js +1 -0
- package/dist/dashboard/assets/VisitorList-COP1SyNd.js +1 -0
- package/dist/dashboard/assets/check-o5cp1s2J.js +1 -0
- package/dist/dashboard/assets/client-ymc9nwWr.js +1 -0
- package/dist/dashboard/assets/copy-C01KoUUH.js +1 -0
- package/dist/dashboard/assets/createLucideIcon-MdjI3m3u.js +1 -0
- package/dist/dashboard/assets/de-DET92Jb5.js +5 -0
- package/dist/dashboard/assets/debounce-DlvAAT2V.js +1 -0
- package/dist/dashboard/assets/dist-DlhLroYC.js +1 -0
- package/dist/dashboard/assets/es-CJNunrnU.js +5 -0
- package/dist/dashboard/assets/external-link-DVe00ZBK.js +1 -0
- package/dist/dashboard/assets/fr-akfTuf5x.js +5 -0
- package/dist/dashboard/assets/history-CHTts_m2.js +1 -0
- package/dist/dashboard/assets/index-DW3qOrry.css +2 -0
- package/dist/dashboard/assets/index-H_Zm0X-u.js +6 -0
- package/dist/dashboard/assets/ja-B0nLWkOd.js +5 -0
- package/dist/dashboard/assets/profiles-DmrdGv7t.js +1 -0
- package/dist/dashboard/assets/roles-C0dJPFl4.js +1 -0
- package/dist/dashboard/assets/search-Bd2RdDRh.js +1 -0
- package/dist/dashboard/assets/templates-B2xiivh4.js +1 -0
- package/dist/dashboard/assets/templates-CnMoLavN.js +1 -0
- package/dist/dashboard/assets/trash-2-BBnkdgm_.js +1 -0
- package/dist/dashboard/assets/trash-Dj1jhzHJ.js +1 -0
- package/dist/dashboard/assets/useHashQuery-B5ytMIMp.js +1 -0
- package/dist/dashboard/assets/users-czK8LRVh.js +1 -0
- package/dist/dashboard/assets/x-BRuyBEQP.js +1 -0
- package/dist/dashboard/assets/zh-CN-Dxg3G-BL.js +5 -0
- package/dist/dashboard/index.html +4 -2
- package/dist/dist-Z5RVTVBT.js +2 -0
- package/dist/dist-Z5RVTVBT.js.map +1 -0
- package/dist/index.cjs +129 -9089
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +963 -254
- package/dist/index.d.ts +963 -254
- package/dist/index.js +129 -9043
- package/dist/index.js.map +1 -1
- package/dist/profiles-XTYPWLVC.js +2 -0
- package/dist/profiles-XTYPWLVC.js.map +1 -0
- package/dist/widget/widget.css +1 -0
- package/dist/widget/widget.js +1 -2304
- package/package.json +19 -12
- package/dist/dashboard/assets/index-BBbhHyc_.js +0 -2637
- package/dist/dashboard/assets/index-DYK73WL5.css +0 -1
package/dist/widget/widget.js
CHANGED
|
@@ -1,2305 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var Consenti = (() => {
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __esm = (fn, res) => function __init() {
|
|
8
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
9
|
-
};
|
|
10
|
-
var __export = (target, all) => {
|
|
11
|
-
for (var name in all)
|
|
12
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
-
};
|
|
14
|
-
var __copyProps = (to, from, except, desc) => {
|
|
15
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
-
for (let key of __getOwnPropNames(from))
|
|
17
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
-
|
|
24
|
-
// src/utils/hmac.ts
|
|
25
|
-
var hmac_exports = {};
|
|
26
|
-
__export(hmac_exports, {
|
|
27
|
-
signValue: () => signValue,
|
|
28
|
-
verifyValue: () => verifyValue
|
|
29
|
-
});
|
|
30
|
-
async function importHmacKey(rawKey) {
|
|
31
|
-
const keyData = new TextEncoder().encode(rawKey);
|
|
32
|
-
return crypto.subtle.importKey(
|
|
33
|
-
"raw",
|
|
34
|
-
keyData,
|
|
35
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
36
|
-
false,
|
|
37
|
-
["sign", "verify"]
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
async function signValue(value, key) {
|
|
41
|
-
const cryptoKey = await importHmacKey(key);
|
|
42
|
-
const data = new TextEncoder().encode(value);
|
|
43
|
-
const signature = await crypto.subtle.sign("HMAC", cryptoKey, data);
|
|
44
|
-
return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
45
|
-
}
|
|
46
|
-
async function verifyValue(value, signature, key) {
|
|
47
|
-
const expected = await signValue(value, key);
|
|
48
|
-
return expected === signature;
|
|
49
|
-
}
|
|
50
|
-
var init_hmac = __esm({
|
|
51
|
-
"src/utils/hmac.ts"() {
|
|
52
|
-
"use strict";
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// src/utils/http.ts
|
|
57
|
-
var http_exports = {};
|
|
58
|
-
__export(http_exports, {
|
|
59
|
-
httpRequest: () => httpRequest
|
|
60
|
-
});
|
|
61
|
-
async function httpRequest(url, options = {}, authToken) {
|
|
62
|
-
const headers = {
|
|
63
|
-
"Content-Type": "application/json",
|
|
64
|
-
...options.headers
|
|
65
|
-
};
|
|
66
|
-
if (authToken) {
|
|
67
|
-
headers["Authorization"] = `Bearer ${authToken}`;
|
|
68
|
-
}
|
|
69
|
-
const res = await fetch(url, { ...options, headers });
|
|
70
|
-
if (!res.ok) {
|
|
71
|
-
throw new Error(`[Consenti] HTTP ${res.status} ${res.statusText} \u2014 ${url}`);
|
|
72
|
-
}
|
|
73
|
-
return res.json();
|
|
74
|
-
}
|
|
75
|
-
var init_http = __esm({
|
|
76
|
-
"src/utils/http.ts"() {
|
|
77
|
-
"use strict";
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// src/index.ts
|
|
82
|
-
var src_exports = {};
|
|
83
|
-
__export(src_exports, {
|
|
84
|
-
ConsentScript: () => ConsentScript,
|
|
85
|
-
ConsentiPlugin: () => ConsentiPlugin,
|
|
86
|
-
ConsentiProfile: () => ConsentiProfile,
|
|
87
|
-
ConsentiSetup: () => ConsentiSetup,
|
|
88
|
-
CookieTrigger: () => CookieTrigger
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// src/styles/consenti-css.ts
|
|
92
|
-
var CONSENTI_CSS = `:root{--consenti-color-bg: #ffffff;--consenti-color-text: #1a2e4a;--consenti-color-primary: #1565c0;--consenti-color-primary-text: #ffffff;--consenti-color-secondary: #f0f4f8;--consenti-color-secondary-text: #1a2e4a;--consenti-color-border: #dbe4ee;--consenti-color-overlay: rgba(26, 52, 96, 0.55);--consenti-font-family: system-ui, -apple-system, sans-serif;--consenti-font-size-base: 14px;--consenti-font-size-heading: 16px;--consenti-font-weight-heading: 600;--consenti-line-height: 1.5;--consenti-spacing-sm: 8px;--consenti-spacing-md: 16px;--consenti-spacing-lg: 24px;--consenti-border-radius: 8px;--consenti-border-radius-btn: 4px;--consenti-shadow: 0 4px 24px rgba(21, 101, 192, 0.14);--consenti-color-accent: #d32f2f;--consenti-color-accent-text: #ffffff;--consenti-toggle-bg-on: #43a047;--consenti-toggle-bg-off: #c8d6e8;--consenti-toggle-knob: #ffffff;--consenti-toggle-width: 44px;--consenti-toggle-height: 24px;--consenti-z-banner: 9999;--consenti-z-overlay: 9998;--consenti-z-modal: 10000}.consenti-root--dark{--consenti-color-bg: #1e2535;--consenti-color-text: #e2e8f0;--consenti-color-primary: #4a9eff;--consenti-color-primary-text: #ffffff;--consenti-color-secondary: #2a3447;--consenti-color-secondary-text: #cbd5e1;--consenti-color-border: #374151;--consenti-color-overlay: rgba(0, 0, 0, 0.65);--consenti-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);--consenti-toggle-bg-off: #4b5563}.consenti-overlay{position:fixed;inset:0;background:var(--consenti-color-overlay);z-index:var(--consenti-z-overlay)}.consenti-btn{display:inline-flex;align-items:center;justify-content:center;padding:var(--consenti-spacing-sm) var(--consenti-spacing-md);border:none;border-radius:var(--consenti-border-radius-btn);font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);font-weight:500;line-height:1;cursor:pointer;text-decoration:none;transition:opacity .15s ease}.consenti-btn:focus-visible{outline:2px solid var(--consenti-color-primary);outline-offset:2px}.consenti-btn:hover{opacity:.9}.consenti-btn--primary{background:var(--consenti-color-primary);color:var(--consenti-color-primary-text)}.consenti-btn--secondary{background:var(--consenti-color-secondary);color:var(--consenti-color-secondary-text)}.consenti-btn--text{background:rgba(0,0,0,0);color:var(--consenti-color-primary);padding-left:0;padding-right:0;text-decoration:underline}.consenti-btn--accent{background:var(--consenti-color-accent);color:var(--consenti-color-accent-text)}.consenti-btn--close{background:rgba(0,0,0,0);color:var(--consenti-color-text);font-size:20px;line-height:1;padding:4px 8px;border-radius:50%}.consenti-btn--close:hover{background:var(--consenti-color-secondary);opacity:1}.consenti-banner{position:fixed;left:0;right:0;z-index:var(--consenti-z-banner);background:var(--consenti-color-bg);color:var(--consenti-color-text);font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);line-height:var(--consenti-line-height);box-shadow:var(--consenti-shadow);padding:var(--consenti-spacing-lg);display:flex;flex-wrap:wrap;align-items:center;gap:var(--consenti-spacing-md)}.consenti-banner--top{top:0;border-bottom:1px solid var(--consenti-color-border)}@media(prefers-reduced-motion: no-preference){.consenti-banner--top{animation:consenti-slide-down .2s ease-out}}.consenti-banner--bottom{bottom:0;border-top:1px solid var(--consenti-color-border)}@media(prefers-reduced-motion: no-preference){.consenti-banner--bottom{animation:consenti-slide-up .2s ease-out}}.consenti-banner--middle{top:50%;transform:translateY(-50%);left:50%;right:auto;transform:translate(-50%, -50%);width:min(600px,90vw);border-radius:var(--consenti-border-radius)}.consenti-banner--left-bottom{bottom:var(--consenti-spacing-lg);left:var(--consenti-spacing-lg);right:auto;width:min(400px,90vw);border-radius:var(--consenti-border-radius)}.consenti-banner--right-bottom{bottom:var(--consenti-spacing-lg);right:var(--consenti-spacing-lg);left:auto;width:min(400px,90vw);border-radius:var(--consenti-border-radius)}.consenti-banner__text-container{flex:1;min-width:200px}.consenti-banner__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin:0 0 var(--consenti-spacing-sm);width:100%}.consenti-banner__text{margin:0}.consenti-banner__links{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);margin-top:var(--consenti-spacing-sm)}.consenti-banner__link{font-size:.85em;text-decoration:underline;text-underline-offset:2px}.consenti-banner__controls{position:absolute;top:var(--consenti-spacing-sm);right:var(--consenti-spacing-sm);display:flex;align-items:center;gap:4px}.consenti-banner__buttons{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);align-items:center}.consenti-banner--top .consenti-banner__buttons,.consenti-banner--bottom .consenti-banner__buttons{margin-left:2vw}@keyframes consenti-slide-up{from{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes consenti-slide-down{from{transform:translateY(-100%)}to{transform:translateY(0)}}.consenti-modal{position:fixed;inset:0;z-index:var(--consenti-z-modal);display:flex;font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);color:var(--consenti-color-text);line-height:var(--consenti-line-height)}.consenti-modal--passthrough{pointer-events:none}.consenti-modal--passthrough .consenti-modal__container{pointer-events:auto}.consenti-modal--center{align-items:center;justify-content:center}.consenti-modal--left{align-items:stretch;justify-content:flex-start}.consenti-modal--left .consenti-modal__container{border-radius:0 var(--consenti-border-radius) var(--consenti-border-radius) 0;height:100%;max-height:100vh}.consenti-modal--right{align-items:stretch;justify-content:flex-end}.consenti-modal--right .consenti-modal__container{border-radius:0;height:100%;max-height:100vh}.consenti-modal__overlay{position:absolute;inset:0;background:var(--consenti-color-overlay)}.consenti-modal__container{position:relative;z-index:1;background:var(--consenti-color-bg);border-radius:var(--consenti-border-radius);box-shadow:var(--consenti-shadow);width:min(560px,90vw);max-height:85vh;display:flex;flex-direction:column;overflow:hidden}@media(prefers-reduced-motion: no-preference){.consenti-modal__container{animation:consenti-fade-in .15s ease-out}}.consenti-modal__header{display:flex;align-items:center;justify-content:space-between;padding:var(--consenti-spacing-md) var(--consenti-spacing-lg);border-bottom:1px solid var(--consenti-color-border);flex-shrink:0}.consenti-modal__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin:0;flex:1}.consenti-modal__header-controls{display:flex;align-items:center;gap:4px;flex-shrink:0}.consenti-modal__close{flex-shrink:0}.consenti-modal__links{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);padding:var(--consenti-spacing-sm) var(--consenti-spacing-lg)}.consenti-modal__link{font-size:.85em;text-decoration:underline;text-underline-offset:2px}.consenti-modal__subheading{padding:var(--consenti-spacing-sm) var(--consenti-spacing-lg) 0;margin:0;color:#6b7280;font-size:13px}.consenti-modal__text{padding:var(--consenti-spacing-sm) var(--consenti-spacing-lg)}.consenti-modal__body{overflow-y:auto;flex:1;padding:0 var(--consenti-spacing-lg)}.consenti-modal__categories{display:flex;flex-direction:column;gap:var(--consenti-spacing-md);padding:var(--consenti-spacing-md) 0}.consenti-modal__buttons{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);padding:var(--consenti-spacing-md) var(--consenti-spacing-lg);border-top:1px solid var(--consenti-color-border);flex-shrink:0}.consenti-modal__receipt-option{margin:0 var(--consenti-spacing-lg);padding-top:var(--consenti-spacing-md);border-top:1px solid var(--consenti-color-border);flex-shrink:0}.consenti-modal__receipt-label{display:flex;align-items:center;gap:var(--consenti-spacing-sm);font-size:var(--consenti-font-size-base);cursor:pointer}.consenti-modal__receipt-checkbox{width:16px;height:16px;flex-shrink:0;cursor:pointer}.consenti-modal__receipt-desc{margin:4px 0 0 24px;font-size:12px;color:#6b7280}@keyframes consenti-fade-in{from{opacity:0;transform:scale(0.97)}to{opacity:1;transform:scale(1)}}.consenti-category{padding:var(--consenti-spacing-md) 0;border-bottom:1px solid var(--consenti-color-border)}.consenti-category:last-child{border-bottom:none}.consenti-category--mandatory .consenti-category__toggle{opacity:.6;cursor:default}.consenti-category__header{display:flex;align-items:center;justify-content:space-between;gap:var(--consenti-spacing-md);margin-bottom:var(--consenti-spacing-sm)}.consenti-category__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin:0}.consenti-category__text{color:#4b5563;font-size:13px;margin:0}.consenti-category__li-desc{margin:var(--consenti-spacing-sm) 0 0;font-size:12px;color:#6b7280;font-style:italic}.consenti-category__toggle{flex-shrink:0;position:relative;width:var(--consenti-toggle-width);height:var(--consenti-toggle-height);border-radius:calc(var(--consenti-toggle-height)/2);background:var(--consenti-toggle-bg-off);border:none;cursor:pointer;transition:background .2s ease;padding:0}.consenti-category__toggle:focus-visible{outline:2px solid var(--consenti-color-primary);outline-offset:2px}.consenti-category__toggle[aria-checked=true]{background:var(--consenti-toggle-bg-on)}.consenti-category__toggle--mandatory{cursor:default}.consenti-category__toggle-knob{position:absolute;top:2px;left:2px;width:calc(var(--consenti-toggle-height) - 4px);height:calc(var(--consenti-toggle-height) - 4px);border-radius:50%;background:var(--consenti-toggle-knob);transition:transform .2s ease;display:block}[aria-checked=true] .consenti-category__toggle-knob{transform:translateX(calc(var(--consenti-toggle-width) - var(--consenti-toggle-height)))}.consenti-locale-switcher{position:relative;display:inline-flex}.consenti-locale-switcher__btn{font-size:1rem;line-height:1;cursor:pointer}.consenti-locale-switcher__list{position:absolute;top:calc(100% + 4px);right:0;z-index:calc(var(--consenti-z-modal) + 1);background:var(--consenti-color-bg);border:1px solid var(--consenti-color-border);border-radius:var(--consenti-border-radius);box-shadow:var(--consenti-shadow);list-style:none;margin:0;padding:4px 0;min-width:80px}.consenti-locale-switcher__list li{display:block}.consenti-locale-switcher__option{display:block;width:100%;padding:6px 12px;text-align:left;font-size:var(--consenti-font-size-base);color:var(--consenti-color-text);background:none;border:none;cursor:pointer}.consenti-locale-switcher__option:hover{background:var(--consenti-color-secondary)}.consenti-locale-switcher__option--active{font-weight:600;color:var(--consenti-color-primary)}.consenti-locale-switcher--modal .consenti-locale-switcher__list{right:0}`;
|
|
93
|
-
|
|
94
|
-
// src/utils/ssr.ts
|
|
95
|
-
var isClient = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
96
|
-
var safeWindow = () => isClient() ? window : null;
|
|
97
|
-
var safeNavigator = () => isClient() && typeof navigator !== "undefined" ? navigator : null;
|
|
98
|
-
|
|
99
|
-
// src/utils/broadcast.ts
|
|
100
|
-
var ConsentiChannel = class {
|
|
101
|
-
constructor() {
|
|
102
|
-
this.channel = null;
|
|
103
|
-
}
|
|
104
|
-
/** `true` when `BroadcastChannel` is available in the current environment. */
|
|
105
|
-
get isSupported() {
|
|
106
|
-
return isClient() && typeof BroadcastChannel !== "undefined";
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Opens the `BroadcastChannel` and registers a message handler.
|
|
110
|
-
* Silently no-ops if `BroadcastChannel` is unsupported.
|
|
111
|
-
*
|
|
112
|
-
* @param onMessage - Callback invoked with each received `ConsentiMessage`.
|
|
113
|
-
*/
|
|
114
|
-
connect(onMessage) {
|
|
115
|
-
if (!this.isSupported) return;
|
|
116
|
-
this.onMessageCallback = onMessage;
|
|
117
|
-
this.channel = new BroadcastChannel("consenti");
|
|
118
|
-
this.channel.onmessage = (event) => {
|
|
119
|
-
if (event.data?.type) {
|
|
120
|
-
onMessage(event.data);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
this.channel.onmessageerror = () => {
|
|
124
|
-
console.warn("[Consenti] BroadcastChannel message error \u2014 ignoring");
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Posts a message to all other tabs connected to the `'consenti'` channel.
|
|
129
|
-
* The sending tab does not receive its own message.
|
|
130
|
-
*
|
|
131
|
-
* @param message - The `ConsentiMessage` to broadcast.
|
|
132
|
-
*/
|
|
133
|
-
send(message) {
|
|
134
|
-
this.channel?.postMessage(message);
|
|
135
|
-
}
|
|
136
|
-
/** Closes the channel and removes the message callback. */
|
|
137
|
-
disconnect() {
|
|
138
|
-
this.channel?.close();
|
|
139
|
-
this.channel = null;
|
|
140
|
-
this.onMessageCallback = void 0;
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
// src/utils/receipt.ts
|
|
145
|
-
function generateReceipt(params) {
|
|
146
|
-
const receipt = {
|
|
147
|
-
version: "1.0",
|
|
148
|
-
issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
149
|
-
visitorId: params.visitorId,
|
|
150
|
-
profileId: params.profileId,
|
|
151
|
-
profileVersion: params.profileVersion,
|
|
152
|
-
locale: params.locale,
|
|
153
|
-
consent: params.consent
|
|
154
|
-
};
|
|
155
|
-
if (params.signature) receipt.signature = params.signature;
|
|
156
|
-
return receipt;
|
|
157
|
-
}
|
|
158
|
-
function downloadReceipt(receipt) {
|
|
159
|
-
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
160
|
-
const json = JSON.stringify(receipt, null, 2);
|
|
161
|
-
const blob = new Blob([json], { type: "application/json" });
|
|
162
|
-
const url = URL.createObjectURL(blob);
|
|
163
|
-
const anchor = document.createElement("a");
|
|
164
|
-
anchor.href = url;
|
|
165
|
-
anchor.download = `consenti-receipt-${receipt.issuedAt.slice(0, 10)}.json`;
|
|
166
|
-
anchor.style.display = "none";
|
|
167
|
-
document.body.appendChild(anchor);
|
|
168
|
-
anchor.click();
|
|
169
|
-
document.body.removeChild(anchor);
|
|
170
|
-
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// src/utils/cookie.ts
|
|
174
|
-
function getCookie(name) {
|
|
175
|
-
if (!isClient()) return null;
|
|
176
|
-
const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${escapeRegExp(name)}=([^;]*)`));
|
|
177
|
-
return match ? decodeURIComponent(match[1] ?? "") : null;
|
|
178
|
-
}
|
|
179
|
-
function setCookie(name, value, opts = {}) {
|
|
180
|
-
if (!isClient()) return;
|
|
181
|
-
const secure = opts.secure ?? (typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.protocol === "https:");
|
|
182
|
-
const parts = [
|
|
183
|
-
`${encodeURIComponent(name)}=${encodeURIComponent(value)}`,
|
|
184
|
-
`Path=${opts.path ?? "/"}`,
|
|
185
|
-
`SameSite=${opts.sameSite ?? "Lax"}`,
|
|
186
|
-
opts.maxAge != null ? `Max-Age=${opts.maxAge}` : "",
|
|
187
|
-
secure ? "Secure" : "",
|
|
188
|
-
opts.domain ? `Domain=${opts.domain}` : ""
|
|
189
|
-
];
|
|
190
|
-
document.cookie = parts.filter(Boolean).join("; ");
|
|
191
|
-
}
|
|
192
|
-
function deleteCookie(name, opts = {}) {
|
|
193
|
-
setCookie(name, "", { ...opts, maxAge: 0 });
|
|
194
|
-
}
|
|
195
|
-
function escapeRegExp(str) {
|
|
196
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// src/utils/storage.ts
|
|
200
|
-
var ConsentStorage = class {
|
|
201
|
-
/**
|
|
202
|
-
* @param mode - `'cookie'` (default) or `'localStorage'`. Falls back to `'cookie'` if
|
|
203
|
-
* `localStorage` is requested but unavailable in the current environment.
|
|
204
|
-
*/
|
|
205
|
-
constructor(mode) {
|
|
206
|
-
this.mode = mode;
|
|
207
|
-
if (mode === "localStorage" && isClient() && typeof localStorage === "undefined") {
|
|
208
|
-
console.warn("[Consenti] localStorage is not available, falling back to cookie storage");
|
|
209
|
-
this.mode = "cookie";
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Reads a value from storage.
|
|
214
|
-
*
|
|
215
|
-
* @param key - Cookie name or localStorage key.
|
|
216
|
-
* @returns The stored string value, or `null` if absent or SSR context.
|
|
217
|
-
*/
|
|
218
|
-
read(key) {
|
|
219
|
-
if (!isClient()) return null;
|
|
220
|
-
if (this.mode === "localStorage") {
|
|
221
|
-
return localStorage.getItem(key);
|
|
222
|
-
}
|
|
223
|
-
return getCookie(key);
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Writes a value to storage.
|
|
227
|
-
*
|
|
228
|
-
* @param key - Cookie name or localStorage key.
|
|
229
|
-
* @param value - String value to persist.
|
|
230
|
-
* @param opts - Cookie attributes (ignored in localStorage mode).
|
|
231
|
-
*/
|
|
232
|
-
write(key, value, opts = {}) {
|
|
233
|
-
if (!isClient()) return;
|
|
234
|
-
if (this.mode === "localStorage") {
|
|
235
|
-
localStorage.setItem(key, value);
|
|
236
|
-
} else {
|
|
237
|
-
setCookie(key, value, opts);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Removes a value from storage.
|
|
242
|
-
*
|
|
243
|
-
* @param key - Cookie name or localStorage key.
|
|
244
|
-
* @param opts - Cookie `path` / `domain` attributes (must match the original write call).
|
|
245
|
-
*/
|
|
246
|
-
remove(key, opts = {}) {
|
|
247
|
-
if (!isClient()) return;
|
|
248
|
-
if (this.mode === "localStorage") {
|
|
249
|
-
localStorage.removeItem(key);
|
|
250
|
-
} else {
|
|
251
|
-
deleteCookie(key, opts);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
// src/core/consent-store.ts
|
|
257
|
-
var COOKIE_NAME_PREFIX = "consenti";
|
|
258
|
-
function buildConsentCookieName(userId, profileId) {
|
|
259
|
-
return `${COOKIE_NAME_PREFIX}_${userId}_${profileId}`;
|
|
260
|
-
}
|
|
261
|
-
function buildCookieValue(consent) {
|
|
262
|
-
const epochSeconds = Math.floor(Date.now() / 1e3);
|
|
263
|
-
const pairs = Object.entries(consent).map(([id, status]) => `${id}:${status}`).join("|");
|
|
264
|
-
return `t:${epochSeconds}::${pairs}`;
|
|
265
|
-
}
|
|
266
|
-
function parseConsentCookie(value) {
|
|
267
|
-
const parts = value.split("::");
|
|
268
|
-
if (parts.length < 2) return null;
|
|
269
|
-
const tsPart = parts[0] ?? "";
|
|
270
|
-
let timestamp;
|
|
271
|
-
if (tsPart.startsWith("t:")) {
|
|
272
|
-
const epochStr = tsPart.slice(2);
|
|
273
|
-
const epoch = parseInt(epochStr, 10);
|
|
274
|
-
if (!epochStr || isNaN(epoch)) return null;
|
|
275
|
-
timestamp = new Date(epoch * 1e3).toISOString();
|
|
276
|
-
} else if (tsPart.startsWith("ConsentTimestamp:")) {
|
|
277
|
-
timestamp = tsPart.replace("ConsentTimestamp:", "");
|
|
278
|
-
if (!timestamp) return null;
|
|
279
|
-
} else {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
const consentPart = parts[1] ?? "";
|
|
283
|
-
const sigPart = parts[2];
|
|
284
|
-
const consent = {};
|
|
285
|
-
for (const pair of consentPart.split("|")) {
|
|
286
|
-
const colonIdx = pair.indexOf(":");
|
|
287
|
-
if (colonIdx === -1) return null;
|
|
288
|
-
const id = pair.slice(0, colonIdx);
|
|
289
|
-
const status = pair.slice(colonIdx + 1);
|
|
290
|
-
if (!id || status !== "granted" && status !== "denied" && status !== "objected") {
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
consent[id] = status;
|
|
294
|
-
}
|
|
295
|
-
const result = { timestamp, consent };
|
|
296
|
-
if (sigPart?.startsWith("sig:")) {
|
|
297
|
-
result.signature = sigPart.slice(4);
|
|
298
|
-
}
|
|
299
|
-
return result;
|
|
300
|
-
}
|
|
301
|
-
var ConsentStore = class _ConsentStore {
|
|
302
|
-
/**
|
|
303
|
-
* @param userId - Visitor UUID (from `consenti_uid` cookie).
|
|
304
|
-
* @param profileId - Numeric profile ID.
|
|
305
|
-
* @param storageMode - `'cookie'` (default, cross-subdomain) or `'localStorage'` (origin-scoped).
|
|
306
|
-
* @param cookieDomains - Comma-separated domain list. First entry used as `Domain` attribute.
|
|
307
|
-
*/
|
|
308
|
-
constructor(userId, profileId, storageMode, cookieDomains) {
|
|
309
|
-
this.userId = userId;
|
|
310
|
-
this.profileId = profileId;
|
|
311
|
-
this.cookieDomains = cookieDomains;
|
|
312
|
-
this.cachedConsent = null;
|
|
313
|
-
this.cachedTimestamp = null;
|
|
314
|
-
this.storage = new ConsentStorage(storageMode);
|
|
315
|
-
}
|
|
316
|
-
/** The full cookie / localStorage key for this visitor + profile combination. */
|
|
317
|
-
get cookieName() {
|
|
318
|
-
return buildConsentCookieName(this.userId, this.profileId);
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Reads and parses the stored consent record.
|
|
322
|
-
* Updates the in-memory cache on success.
|
|
323
|
-
*
|
|
324
|
-
* @returns The parsed consent or `null` if absent / malformed.
|
|
325
|
-
*/
|
|
326
|
-
read() {
|
|
327
|
-
const raw = this.storage.read(this.cookieName);
|
|
328
|
-
if (!raw) return null;
|
|
329
|
-
const parsed = parseConsentCookie(raw);
|
|
330
|
-
if (parsed) {
|
|
331
|
-
this.cachedConsent = parsed.consent;
|
|
332
|
-
this.cachedTimestamp = parsed.timestamp;
|
|
333
|
-
}
|
|
334
|
-
return parsed;
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Reads, parses, and cryptographically verifies the stored consent record.
|
|
338
|
-
*
|
|
339
|
-
* If the cookie has a `::sig:{hmac}` segment, the signature is verified against
|
|
340
|
-
* the raw value using HMAC-SHA256. A mismatch means the cookie was tampered with —
|
|
341
|
-
* the cookie is deleted and `null` is returned so the widget re-prompts for consent.
|
|
342
|
-
*
|
|
343
|
-
* If the cookie has no signature segment, it is treated as valid (backwards compatible
|
|
344
|
-
* with cookies written before `signCookies` was enabled).
|
|
345
|
-
*
|
|
346
|
-
* @param signingKey - The HMAC key (from profile API response or `core.cookieSigningKey`).
|
|
347
|
-
* @returns The parsed consent, or `null` if absent / malformed / signature invalid.
|
|
348
|
-
*/
|
|
349
|
-
async readAndVerify(signingKey) {
|
|
350
|
-
const raw = this.storage.read(this.cookieName);
|
|
351
|
-
if (!raw) return null;
|
|
352
|
-
const parts = raw.split("::");
|
|
353
|
-
if (parts.length < 2) return null;
|
|
354
|
-
const parsed = parseConsentCookie(raw);
|
|
355
|
-
if (!parsed) return null;
|
|
356
|
-
const hasSig = parts.length === 3 && (parts[2] ?? "").startsWith("sig:");
|
|
357
|
-
if (hasSig) {
|
|
358
|
-
const { verifyValue: verifyValue2 } = await Promise.resolve().then(() => (init_hmac(), hmac_exports));
|
|
359
|
-
const valueToVerify = (parts[0] ?? "") + "::" + (parts[1] ?? "");
|
|
360
|
-
const sig = (parts[2] ?? "").slice(4);
|
|
361
|
-
const valid = await verifyValue2(valueToVerify, sig, signingKey);
|
|
362
|
-
if (!valid) {
|
|
363
|
-
console.warn("[Consenti] Cookie signature mismatch \u2014 consent cleared and banner will re-appear");
|
|
364
|
-
this.delete();
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
this.cachedConsent = parsed.consent;
|
|
369
|
-
this.cachedTimestamp = parsed.timestamp;
|
|
370
|
-
return parsed;
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Writes a consent record to storage.
|
|
374
|
-
*
|
|
375
|
-
* @param consent - The consent map to persist.
|
|
376
|
-
* @param signature - Optional pre-computed HMAC hex string. Use `writeAndSign()` instead
|
|
377
|
-
* if you need signing — it guarantees the signature covers the exact
|
|
378
|
-
* value that gets written (timestamps match).
|
|
379
|
-
*/
|
|
380
|
-
write(consent, signature) {
|
|
381
|
-
let value = buildCookieValue(consent);
|
|
382
|
-
if (signature) {
|
|
383
|
-
value = `${value}::sig:${signature}`;
|
|
384
|
-
}
|
|
385
|
-
const opts = this.buildCookieOpts();
|
|
386
|
-
this.storage.write(this.cookieName, value, opts);
|
|
387
|
-
this.cachedConsent = consent;
|
|
388
|
-
this.cachedTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Builds the cookie value, signs it with HMAC-SHA256 in a single atomic step,
|
|
392
|
-
* and writes the signed value to storage.
|
|
393
|
-
*
|
|
394
|
-
* Using this instead of `write(consent, signature)` ensures the signature
|
|
395
|
-
* covers exactly the value that is written — there is no timestamp drift
|
|
396
|
-
* between building, signing, and writing.
|
|
397
|
-
*
|
|
398
|
-
* @param consent - The consent map to persist.
|
|
399
|
-
* @param signingKey - The HMAC key string.
|
|
400
|
-
* @returns The hex-encoded signature, stored in `this.lastSignature` by the caller.
|
|
401
|
-
*/
|
|
402
|
-
async writeAndSign(consent, signingKey) {
|
|
403
|
-
const { signValue: signValue2 } = await Promise.resolve().then(() => (init_hmac(), hmac_exports));
|
|
404
|
-
const rawValue = buildCookieValue(consent);
|
|
405
|
-
const sig = await signValue2(rawValue, signingKey);
|
|
406
|
-
const finalValue = `${rawValue}::sig:${sig}`;
|
|
407
|
-
const opts = this.buildCookieOpts();
|
|
408
|
-
this.storage.write(this.cookieName, finalValue, opts);
|
|
409
|
-
this.cachedConsent = consent;
|
|
410
|
-
this.cachedTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
411
|
-
return sig;
|
|
412
|
-
}
|
|
413
|
-
/** Removes the consent record from storage and clears the in-memory cache. */
|
|
414
|
-
delete() {
|
|
415
|
-
const opts = this.buildCookieOpts();
|
|
416
|
-
this.storage.remove(this.cookieName, opts);
|
|
417
|
-
this.cachedConsent = null;
|
|
418
|
-
this.cachedTimestamp = null;
|
|
419
|
-
}
|
|
420
|
-
/** Returns `true` if a valid consent record exists (uses cache when available). */
|
|
421
|
-
hasConsent() {
|
|
422
|
-
if (this.cachedConsent) return true;
|
|
423
|
-
return this.read() !== null;
|
|
424
|
-
}
|
|
425
|
-
/** Returns the stored consent map, or `null` if no consent has been given. */
|
|
426
|
-
getConsent() {
|
|
427
|
-
if (this.cachedConsent) return this.cachedConsent;
|
|
428
|
-
return this.read()?.consent ?? null;
|
|
429
|
-
}
|
|
430
|
-
/** Returns the `Date` of the last consent submission, or `false` if no consent exists. */
|
|
431
|
-
getConsentDate() {
|
|
432
|
-
if (this.cachedTimestamp) return new Date(this.cachedTimestamp);
|
|
433
|
-
const parsed = this.read();
|
|
434
|
-
if (!parsed) return false;
|
|
435
|
-
return new Date(parsed.timestamp);
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Updates the in-memory cache without writing to storage.
|
|
439
|
-
* Used by the cross-tab BroadcastChannel handler to keep other tabs in sync.
|
|
440
|
-
*/
|
|
441
|
-
setInMemory(consent) {
|
|
442
|
-
this.cachedConsent = consent;
|
|
443
|
-
this.cachedTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
444
|
-
}
|
|
445
|
-
/** Clears the in-memory cache. Used when consent is deleted from another tab. */
|
|
446
|
-
clearInMemory() {
|
|
447
|
-
this.cachedConsent = null;
|
|
448
|
-
this.cachedTimestamp = null;
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* Derives the visitor UUID from an existing consent cookie, or generates a new one
|
|
452
|
-
* in memory.
|
|
453
|
-
*
|
|
454
|
-
* No separate identifier cookie is written before consent. Storing a tracking
|
|
455
|
-
* identifier before the user has given consent violates TTDSG §25 (Germany) and
|
|
456
|
-
* equivalent ePrivacy laws in the EU. The UUID is embedded in the consent cookie
|
|
457
|
-
* name and only persisted when consent is first saved (via `write()` / `writeAndSign()`).
|
|
458
|
-
*
|
|
459
|
-
* @param profileId - The active profile ID, used to locate an existing consent cookie.
|
|
460
|
-
* @param storageMode - The configured storage mode (`'cookie'` or `'localStorage'`).
|
|
461
|
-
*/
|
|
462
|
-
static getOrCreateUserId(profileId, storageMode) {
|
|
463
|
-
if (typeof document === "undefined") return crypto.randomUUID();
|
|
464
|
-
const prefix = `${COOKIE_NAME_PREFIX}_`;
|
|
465
|
-
const suffix = `_${profileId}`;
|
|
466
|
-
const all = storageMode === "localStorage" ? _ConsentStore._localStorageKeys() : _ConsentStore._cookieNames();
|
|
467
|
-
for (const name of all) {
|
|
468
|
-
if (name.startsWith(prefix) && name.endsWith(suffix)) {
|
|
469
|
-
const inner = name.slice(prefix.length, name.length - suffix.length);
|
|
470
|
-
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(inner)) {
|
|
471
|
-
return inner;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
return crypto.randomUUID();
|
|
476
|
-
}
|
|
477
|
-
/** Returns all document.cookie names. */
|
|
478
|
-
static _cookieNames() {
|
|
479
|
-
return document.cookie.split(";").map((c) => c.split("=")[0]?.trim() ?? "");
|
|
480
|
-
}
|
|
481
|
-
/** Returns all localStorage keys (empty array when unavailable). */
|
|
482
|
-
static _localStorageKeys() {
|
|
483
|
-
if (typeof localStorage === "undefined") return [];
|
|
484
|
-
return Object.keys(localStorage);
|
|
485
|
-
}
|
|
486
|
-
buildCookieOpts() {
|
|
487
|
-
const opts = {
|
|
488
|
-
path: "/",
|
|
489
|
-
sameSite: "Lax",
|
|
490
|
-
maxAge: 365 * 24 * 60 * 60
|
|
491
|
-
};
|
|
492
|
-
if (this.cookieDomains) {
|
|
493
|
-
const domain = this.cookieDomains.split(",")[0]?.trim();
|
|
494
|
-
if (domain) opts.domain = domain;
|
|
495
|
-
}
|
|
496
|
-
return opts;
|
|
497
|
-
}
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
// src/core/event-bus.ts
|
|
501
|
-
var EventBus = class {
|
|
502
|
-
/**
|
|
503
|
-
* @param profileId - Profile ID included in all GTM pushes.
|
|
504
|
-
* @param gtmConfig - Optional GTM integration settings.
|
|
505
|
-
*/
|
|
506
|
-
constructor(profileId, gtmConfig) {
|
|
507
|
-
this.profileId = profileId;
|
|
508
|
-
this.gtmConfig = gtmConfig;
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Dispatches a `consenti:*` custom event on `window` and, if GTM is configured,
|
|
512
|
-
* pushes the event to `window.dataLayer`.
|
|
513
|
-
*
|
|
514
|
-
* Silently no-ops in SSR contexts.
|
|
515
|
-
*
|
|
516
|
-
* @param name - The event name.
|
|
517
|
-
* @param detail - Event payload attached to `event.detail` and included in the GTM push.
|
|
518
|
-
*/
|
|
519
|
-
dispatch(name, detail = {}) {
|
|
520
|
-
if (!isClient()) return;
|
|
521
|
-
const event = new CustomEvent(name, { detail, bubbles: true });
|
|
522
|
-
window.dispatchEvent(event);
|
|
523
|
-
this.pushToGTM(name, detail);
|
|
524
|
-
}
|
|
525
|
-
pushToGTM(name, detail) {
|
|
526
|
-
const gtm = this.gtmConfig;
|
|
527
|
-
if (!gtm) return;
|
|
528
|
-
const win = safeWindow();
|
|
529
|
-
if (!win) return;
|
|
530
|
-
const layerName = gtm.dataLayer ?? "dataLayer";
|
|
531
|
-
const layer = win[layerName];
|
|
532
|
-
if (!Array.isArray(layer)) return;
|
|
533
|
-
const shouldPush = !gtm.events || gtm.events.length === 0 || gtm.events.includes(name);
|
|
534
|
-
if (!shouldPush) return;
|
|
535
|
-
layer.push({
|
|
536
|
-
event: name,
|
|
537
|
-
consenti: {
|
|
538
|
-
profileId: this.profileId,
|
|
539
|
-
consent: detail.consent,
|
|
540
|
-
consentId: detail.consentId,
|
|
541
|
-
consentAction: detail.consentAction
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
if (name === "consenti:consentSubmitted" && this.hasGtag(win)) {
|
|
545
|
-
if (gtm.urlPassthrough) {
|
|
546
|
-
layer.push({ url_passthrough: true });
|
|
547
|
-
}
|
|
548
|
-
if (gtm.adsDataRedaction) {
|
|
549
|
-
const adConsentDenied = detail.consent?.["ad_storage"] !== "granted";
|
|
550
|
-
layer.push({ ads_data_redaction: adConsentDenied });
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Returns `true` when gtag.js or Google Tag Manager is detected on the page.
|
|
556
|
-
* Used to gate GCM v2 cookieless-ping pushes so they are not emitted when
|
|
557
|
-
* Google services are absent.
|
|
558
|
-
*/
|
|
559
|
-
hasGtag(win) {
|
|
560
|
-
return typeof win["gtag"] === "function" || typeof win["google_tag_manager"] !== "undefined";
|
|
561
|
-
}
|
|
562
|
-
};
|
|
563
|
-
|
|
564
|
-
// src/core/profile-resolver.ts
|
|
565
|
-
init_http();
|
|
566
|
-
|
|
567
|
-
// src/utils/locale.ts
|
|
568
|
-
function resolveLocale(translations, requested, defaultLocale) {
|
|
569
|
-
const base = translations[defaultLocale];
|
|
570
|
-
if (!base) {
|
|
571
|
-
throw new Error(`[Consenti] No translations found for defaultLocale "${defaultLocale}"`);
|
|
572
|
-
}
|
|
573
|
-
if (translations[requested]) {
|
|
574
|
-
return deepMerge(base, translations[requested]);
|
|
575
|
-
}
|
|
576
|
-
const lang = requested.split("-")[0] ?? "";
|
|
577
|
-
if (lang !== requested && translations[lang]) {
|
|
578
|
-
return deepMerge(base, translations[lang]);
|
|
579
|
-
}
|
|
580
|
-
return base;
|
|
581
|
-
}
|
|
582
|
-
function deepMerge(base, override) {
|
|
583
|
-
const result = { ...base };
|
|
584
|
-
for (const key in override) {
|
|
585
|
-
const overrideVal = override[key];
|
|
586
|
-
if (overrideVal === void 0 || overrideVal === null) continue;
|
|
587
|
-
if (typeof overrideVal === "object" && !Array.isArray(overrideVal) && typeof result[key] === "object" && result[key] !== null && !Array.isArray(result[key])) {
|
|
588
|
-
result[key] = deepMerge(result[key], overrideVal);
|
|
589
|
-
} else {
|
|
590
|
-
result[key] = overrideVal;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
return result;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// src/core/profile-resolver.ts
|
|
597
|
-
var profileRegistry = /* @__PURE__ */ new Map();
|
|
598
|
-
function registerProfile(id, config) {
|
|
599
|
-
profileRegistry.set(id, config);
|
|
600
|
-
}
|
|
601
|
-
var DEFAULT_PROFILE = {
|
|
602
|
-
id: 0,
|
|
603
|
-
version: 1,
|
|
604
|
-
defaultLocale: "en",
|
|
605
|
-
cookies: [
|
|
606
|
-
{ id: "functionality_storage", mandatory: true },
|
|
607
|
-
{
|
|
608
|
-
id: "analytics_storage",
|
|
609
|
-
listenGpc: true,
|
|
610
|
-
expiry: 365
|
|
611
|
-
},
|
|
612
|
-
{
|
|
613
|
-
id: "ad_storage",
|
|
614
|
-
listenGpc: true,
|
|
615
|
-
expiry: 365
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
id: "ad_user_data",
|
|
619
|
-
listenGpc: true,
|
|
620
|
-
expiry: 365
|
|
621
|
-
},
|
|
622
|
-
{
|
|
623
|
-
id: "ad_personalization",
|
|
624
|
-
listenGpc: true,
|
|
625
|
-
expiry: 365
|
|
626
|
-
}
|
|
627
|
-
],
|
|
628
|
-
mainBanner: {
|
|
629
|
-
position: "bottom",
|
|
630
|
-
heading: "We value your privacy",
|
|
631
|
-
htmlText: "We use cookies to enhance your browsing experience, serve personalised ads or content, and analyse our traffic. By clicking <strong>Accept All</strong> you consent to our use of cookies. You may change your preferences at any time.",
|
|
632
|
-
buttons: [
|
|
633
|
-
{ text: "Accept All", cookies: "*", style: "primary", action: "custom" },
|
|
634
|
-
{ text: "Reject All", cookies: "!", style: "primary", action: "custom" },
|
|
635
|
-
{ text: "Manage Preferences", style: "secondary", action: "manage" }
|
|
636
|
-
]
|
|
637
|
-
},
|
|
638
|
-
preferenceModal: {
|
|
639
|
-
heading: "Cookie Preferences",
|
|
640
|
-
subheading: "Choose which cookies you allow us to use.",
|
|
641
|
-
htmlText: "We use different types of cookies to optimise your experience. You can choose to enable or disable each category below. Necessary cookies cannot be disabled as they are required for core site functionality.",
|
|
642
|
-
showClose: true,
|
|
643
|
-
overlayOpacity: 50,
|
|
644
|
-
categories: [
|
|
645
|
-
{
|
|
646
|
-
id: "cat-necessary",
|
|
647
|
-
heading: "Strictly Necessary",
|
|
648
|
-
htmlText: "These cookies are essential for the website to function correctly. They include authentication, security, and accessibility features. They cannot be disabled.",
|
|
649
|
-
mandatory: true,
|
|
650
|
-
cookies: ["functionality_storage"]
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
id: "cat-analytics",
|
|
654
|
-
heading: "Analytics",
|
|
655
|
-
htmlText: "These cookies help us understand how visitors interact with our website by collecting and reporting information anonymously. This allows us to improve the site over time. (e.g. Google Analytics)",
|
|
656
|
-
cookies: ["analytics_storage"]
|
|
657
|
-
},
|
|
658
|
-
{
|
|
659
|
-
id: "cat-advertising",
|
|
660
|
-
heading: "Advertising",
|
|
661
|
-
htmlText: "These cookies are used to deliver advertisements more relevant to you and your interests. They are also used to limit the number of times you see an ad and to help measure the effectiveness of advertising campaigns. (e.g. Google Ads, Meta Pixel)",
|
|
662
|
-
cookies: ["ad_storage", "ad_user_data", "ad_personalization"]
|
|
663
|
-
}
|
|
664
|
-
],
|
|
665
|
-
buttons: [
|
|
666
|
-
{ text: "Accept All", cookies: "*", style: "primary", action: "custom" },
|
|
667
|
-
{ text: "Save Preferences", style: "primary", action: "submit" },
|
|
668
|
-
{ text: "Reject All", cookies: "!", style: "primary", action: "custom" }
|
|
669
|
-
]
|
|
670
|
-
}
|
|
671
|
-
};
|
|
672
|
-
async function resolveProfile(config) {
|
|
673
|
-
const locale = config.core.locale ?? "en";
|
|
674
|
-
const profileId = config.core.profileId ?? 0;
|
|
675
|
-
if (config.api?.enabled) {
|
|
676
|
-
try {
|
|
677
|
-
const base = config.api.baseUrl ?? (typeof window !== "undefined" ? window.location.origin : "");
|
|
678
|
-
const url = `${base}/consenti/api/v1/profiles/${profileId}/${encodeURIComponent(locale)}`;
|
|
679
|
-
const apiProfile = await httpRequest(url, {}, config.api.authToken);
|
|
680
|
-
return {
|
|
681
|
-
id: profileId,
|
|
682
|
-
version: apiProfile.version,
|
|
683
|
-
defaultLocale: apiProfile.defaultLocale,
|
|
684
|
-
locales: apiProfile.locales,
|
|
685
|
-
cookies: apiProfile.cookies,
|
|
686
|
-
mainBanner: apiProfile.mainBanner,
|
|
687
|
-
preferenceModal: apiProfile.preferenceModal,
|
|
688
|
-
...apiProfile.gpcBanner != null ? { gpcBanner: apiProfile.gpcBanner } : {}
|
|
689
|
-
};
|
|
690
|
-
} catch {
|
|
691
|
-
console.warn("[Consenti] API profile fetch failed, falling back to local profile");
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
if (profileId > 0) {
|
|
695
|
-
const local = profileRegistry.get(profileId);
|
|
696
|
-
if (local) {
|
|
697
|
-
const resolved = resolveLocale(local.translations ?? {}, locale, local.defaultLocale);
|
|
698
|
-
return {
|
|
699
|
-
id: profileId,
|
|
700
|
-
version: 1,
|
|
701
|
-
defaultLocale: local.defaultLocale,
|
|
702
|
-
locales: Object.keys(local.translations ?? {}),
|
|
703
|
-
cookies: local.cookies ?? [],
|
|
704
|
-
mainBanner: resolved.mainBanner,
|
|
705
|
-
...resolved.gpcBanner ? { gpcBanner: resolved.gpcBanner } : {},
|
|
706
|
-
preferenceModal: resolved.preferenceModal,
|
|
707
|
-
...local.darkMode !== void 0 ? { darkMode: local.darkMode } : {}
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
throw new Error(
|
|
711
|
-
`[Consenti] Profile ${profileId} not found. Register it with ConsentiProfile or enable the API.`
|
|
712
|
-
);
|
|
713
|
-
}
|
|
714
|
-
return DEFAULT_PROFILE;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// src/core/gpc.ts
|
|
718
|
-
function detectGPC() {
|
|
719
|
-
const nav = safeNavigator();
|
|
720
|
-
if (!nav) return false;
|
|
721
|
-
return "globalPrivacyControl" in nav && nav.globalPrivacyControl === true;
|
|
722
|
-
}
|
|
723
|
-
function applyGPCToConsent(cookies, currentConsent, mode) {
|
|
724
|
-
if (!mode || !detectGPC()) return { ...currentConsent };
|
|
725
|
-
const result = { ...currentConsent };
|
|
726
|
-
for (const cookie of cookies) {
|
|
727
|
-
if (cookie.mandatory) continue;
|
|
728
|
-
if (cookie.listenGpc) {
|
|
729
|
-
result[cookie.id] = cookie.type === "legitimate_interest" ? "objected" : "denied";
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
for (const cookie of cookies) {
|
|
733
|
-
if (cookie.mandatory) result[cookie.id] = "granted";
|
|
734
|
-
}
|
|
735
|
-
return result;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// src/ui/buttons.ts
|
|
739
|
-
function buildButton(btn, handlers) {
|
|
740
|
-
const el = document.createElement("button");
|
|
741
|
-
el.type = "button";
|
|
742
|
-
el.className = `consenti-btn consenti-btn--${btn.style}`;
|
|
743
|
-
el.textContent = btn.text;
|
|
744
|
-
el.addEventListener("click", () => {
|
|
745
|
-
switch (btn.action) {
|
|
746
|
-
case "custom": {
|
|
747
|
-
const cookies = btn.cookies;
|
|
748
|
-
if (cookies === "*") {
|
|
749
|
-
handlers.onGrantAll();
|
|
750
|
-
} else if (cookies === "!") {
|
|
751
|
-
handlers.onDenyAll();
|
|
752
|
-
} else if (Array.isArray(cookies) && cookies.length > 0) {
|
|
753
|
-
handlers.onGrantSpecific(cookies);
|
|
754
|
-
}
|
|
755
|
-
break;
|
|
756
|
-
}
|
|
757
|
-
case "submit":
|
|
758
|
-
handlers.onSubmit();
|
|
759
|
-
break;
|
|
760
|
-
case "manage":
|
|
761
|
-
handlers.onManage();
|
|
762
|
-
break;
|
|
763
|
-
case "close":
|
|
764
|
-
handlers.onClose();
|
|
765
|
-
break;
|
|
766
|
-
}
|
|
767
|
-
});
|
|
768
|
-
return el;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
// src/ui/overlay.ts
|
|
772
|
-
function createOverlay(opacity, onClick) {
|
|
773
|
-
const el = document.createElement("div");
|
|
774
|
-
el.className = "consenti-overlay";
|
|
775
|
-
el.style.opacity = String(opacity / 100);
|
|
776
|
-
el.setAttribute("aria-hidden", "true");
|
|
777
|
-
if (onClick) {
|
|
778
|
-
el.addEventListener("click", onClick);
|
|
779
|
-
}
|
|
780
|
-
return el;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
// src/ui/banner.ts
|
|
784
|
-
var Banner = class {
|
|
785
|
-
constructor() {
|
|
786
|
-
this.el = null;
|
|
787
|
-
this.overlayEl = null;
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Constructs the banner DOM from the given config and returns the root element.
|
|
791
|
-
* The element is not yet inserted into the document — the caller appends it to
|
|
792
|
-
* the mount root via `Renderer.mount()`.
|
|
793
|
-
*
|
|
794
|
-
* @param config - Banner layout and content config from the resolved profile.
|
|
795
|
-
* @param handlers - Click handlers wired to each button.
|
|
796
|
-
* @param privacyPolicyUrl - Optional URL appended as a "Privacy Policy" link after the body text.
|
|
797
|
-
* @param locales - All locale codes available on the profile (for the locale switcher).
|
|
798
|
-
* @param activeLocale - The currently active locale code.
|
|
799
|
-
* @param onLocaleSwitch - Callback invoked when the user selects a different locale.
|
|
800
|
-
* @returns The constructed banner `<div>` element.
|
|
801
|
-
*/
|
|
802
|
-
build(config, handlers, privacyPolicyUrl, locales, activeLocale, onLocaleSwitch) {
|
|
803
|
-
const banner = document.createElement("div");
|
|
804
|
-
banner.id = "consenti-banner";
|
|
805
|
-
banner.className = `consenti-banner consenti-banner--${config.position}`;
|
|
806
|
-
banner.setAttribute("role", "region");
|
|
807
|
-
banner.setAttribute("aria-label", "Cookie consent");
|
|
808
|
-
banner.setAttribute("aria-live", "polite");
|
|
809
|
-
const textContainer = document.createElement("div");
|
|
810
|
-
textContainer.className = `consenti-banner__text-container`;
|
|
811
|
-
const linksContainer = document.createElement("div");
|
|
812
|
-
linksContainer.className = "consenti-banner__links";
|
|
813
|
-
if (config.heading) {
|
|
814
|
-
const headingTag = config.headingTag ?? "h2";
|
|
815
|
-
const heading = document.createElement(headingTag);
|
|
816
|
-
heading.id = "consenti-banner-heading";
|
|
817
|
-
heading.className = "consenti-banner__heading";
|
|
818
|
-
heading.textContent = config.heading;
|
|
819
|
-
textContainer.appendChild(heading);
|
|
820
|
-
}
|
|
821
|
-
const text = document.createElement("div");
|
|
822
|
-
text.className = "consenti-banner__text";
|
|
823
|
-
text.innerHTML = config.htmlText;
|
|
824
|
-
if (privacyPolicyUrl) {
|
|
825
|
-
const link = document.createElement("a");
|
|
826
|
-
link.href = privacyPolicyUrl;
|
|
827
|
-
link.className = "consenti-banner__link consenti-banner__link--privacy consenti-btn consenti-btn--text";
|
|
828
|
-
link.textContent = "Privacy Policy";
|
|
829
|
-
link.setAttribute("target", "_blank");
|
|
830
|
-
link.setAttribute("rel", "noopener noreferrer");
|
|
831
|
-
linksContainer.appendChild(link);
|
|
832
|
-
}
|
|
833
|
-
textContainer.appendChild(text);
|
|
834
|
-
const linkButtons = config.buttons.filter((b) => b.action === "link");
|
|
835
|
-
if (linkButtons.length > 0) {
|
|
836
|
-
for (const btn of linkButtons) {
|
|
837
|
-
if (!btn.url) continue;
|
|
838
|
-
const anchor = document.createElement("a");
|
|
839
|
-
anchor.href = btn.url;
|
|
840
|
-
anchor.className = `consenti-banner__link consenti-btn consenti-btn--${btn.style ?? "text"}`;
|
|
841
|
-
anchor.textContent = btn.text;
|
|
842
|
-
anchor.setAttribute("target", "_blank");
|
|
843
|
-
anchor.setAttribute("rel", "noopener noreferrer");
|
|
844
|
-
linksContainer.appendChild(anchor);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
if (linkButtons.length > 0 || privacyPolicyUrl) {
|
|
848
|
-
textContainer.appendChild(linksContainer);
|
|
849
|
-
}
|
|
850
|
-
banner.appendChild(textContainer);
|
|
851
|
-
const actionButtons = config.buttons.filter((b) => b.action !== "link");
|
|
852
|
-
if (actionButtons.length > 0) {
|
|
853
|
-
const btns = document.createElement("div");
|
|
854
|
-
btns.className = "consenti-banner__buttons";
|
|
855
|
-
for (const btn of actionButtons) {
|
|
856
|
-
btns.appendChild(buildButton(btn, handlers));
|
|
857
|
-
}
|
|
858
|
-
banner.appendChild(btns);
|
|
859
|
-
}
|
|
860
|
-
const hasClose = config.showClose;
|
|
861
|
-
const hasLocaleSwitcher = config.showLocaleSwitcher && locales && locales.length > 1;
|
|
862
|
-
if (hasClose || hasLocaleSwitcher) {
|
|
863
|
-
const controls = document.createElement("div");
|
|
864
|
-
controls.className = "consenti-banner__controls";
|
|
865
|
-
if (hasLocaleSwitcher && locales && onLocaleSwitch) {
|
|
866
|
-
controls.appendChild(buildLocaleSwitcher(locales, activeLocale, onLocaleSwitch));
|
|
867
|
-
}
|
|
868
|
-
if (hasClose) {
|
|
869
|
-
const close = document.createElement("button");
|
|
870
|
-
close.type = "button";
|
|
871
|
-
close.className = "consenti-banner__close consenti-btn consenti-btn--close";
|
|
872
|
-
close.setAttribute("aria-label", "Close cookie banner");
|
|
873
|
-
close.textContent = "\xD7";
|
|
874
|
-
close.addEventListener("click", handlers.onClose);
|
|
875
|
-
controls.appendChild(close);
|
|
876
|
-
}
|
|
877
|
-
banner.appendChild(controls);
|
|
878
|
-
}
|
|
879
|
-
if (config.overlayOpacity && config.overlayOpacity > 0) {
|
|
880
|
-
this.overlayEl = createOverlay(config.overlayOpacity);
|
|
881
|
-
}
|
|
882
|
-
this.el = banner;
|
|
883
|
-
return banner;
|
|
884
|
-
}
|
|
885
|
-
/** Returns the overlay element (if `overlayOpacity > 0`), or `null`. */
|
|
886
|
-
getOverlay() {
|
|
887
|
-
return this.overlayEl;
|
|
888
|
-
}
|
|
889
|
-
/** Makes the banner and its overlay visible after a `hide()` call. */
|
|
890
|
-
show() {
|
|
891
|
-
if (this.el) this.el.style.display = "";
|
|
892
|
-
if (this.overlayEl) this.overlayEl.style.display = "";
|
|
893
|
-
}
|
|
894
|
-
/** Hides the banner and its overlay without removing them from the DOM. */
|
|
895
|
-
hide() {
|
|
896
|
-
if (this.el) this.el.style.display = "none";
|
|
897
|
-
if (this.overlayEl) this.overlayEl.style.display = "none";
|
|
898
|
-
}
|
|
899
|
-
/** Removes the banner and overlay from the DOM entirely. */
|
|
900
|
-
remove() {
|
|
901
|
-
this.el?.remove();
|
|
902
|
-
this.overlayEl?.remove();
|
|
903
|
-
this.el = null;
|
|
904
|
-
this.overlayEl = null;
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
function buildLocaleSwitcher(locales, activeLocale, onSwitch) {
|
|
908
|
-
const wrapper = document.createElement("div");
|
|
909
|
-
wrapper.className = "consenti-locale-switcher";
|
|
910
|
-
const btn = document.createElement("button");
|
|
911
|
-
btn.type = "button";
|
|
912
|
-
btn.className = "consenti-locale-switcher__btn consenti-btn consenti-btn--close";
|
|
913
|
-
btn.setAttribute("aria-label", "Switch language");
|
|
914
|
-
btn.setAttribute("aria-haspopup", "listbox");
|
|
915
|
-
btn.textContent = "\u{1F310}";
|
|
916
|
-
const list = document.createElement("ul");
|
|
917
|
-
list.className = "consenti-locale-switcher__list";
|
|
918
|
-
list.setAttribute("role", "listbox");
|
|
919
|
-
list.setAttribute("aria-label", "Select language");
|
|
920
|
-
list.hidden = true;
|
|
921
|
-
for (const locale of locales) {
|
|
922
|
-
const item = document.createElement("li");
|
|
923
|
-
item.setAttribute("role", "option");
|
|
924
|
-
item.setAttribute("aria-selected", String(locale === activeLocale));
|
|
925
|
-
const localeBtn = document.createElement("button");
|
|
926
|
-
localeBtn.type = "button";
|
|
927
|
-
localeBtn.className = `consenti-locale-switcher__option${locale === activeLocale ? " consenti-locale-switcher__option--active" : ""}`;
|
|
928
|
-
localeBtn.textContent = locale;
|
|
929
|
-
localeBtn.addEventListener("click", (e) => {
|
|
930
|
-
e.stopPropagation();
|
|
931
|
-
list.hidden = true;
|
|
932
|
-
if (locale !== activeLocale) onSwitch(locale);
|
|
933
|
-
});
|
|
934
|
-
item.appendChild(localeBtn);
|
|
935
|
-
list.appendChild(item);
|
|
936
|
-
}
|
|
937
|
-
btn.addEventListener("click", (e) => {
|
|
938
|
-
e.stopPropagation();
|
|
939
|
-
list.hidden = !list.hidden;
|
|
940
|
-
});
|
|
941
|
-
document.addEventListener("click", () => {
|
|
942
|
-
list.hidden = true;
|
|
943
|
-
}, { capture: true, once: false });
|
|
944
|
-
wrapper.appendChild(btn);
|
|
945
|
-
wrapper.appendChild(list);
|
|
946
|
-
return wrapper;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
// src/ui/focus-trap.ts
|
|
950
|
-
var FOCUSABLE_SELECTORS = [
|
|
951
|
-
"a[href]",
|
|
952
|
-
"button:not([disabled])",
|
|
953
|
-
"input:not([disabled])",
|
|
954
|
-
"select:not([disabled])",
|
|
955
|
-
"textarea:not([disabled])",
|
|
956
|
-
'[tabindex]:not([tabindex="-1"])',
|
|
957
|
-
'[contenteditable="true"]'
|
|
958
|
-
].join(", ");
|
|
959
|
-
function trapFocus(container) {
|
|
960
|
-
const getFocusable = () => Array.from(container.querySelectorAll(FOCUSABLE_SELECTORS)).filter(
|
|
961
|
-
(el) => !el.closest('[aria-hidden="true"]')
|
|
962
|
-
);
|
|
963
|
-
const handleKeydown = (e) => {
|
|
964
|
-
if (e.key !== "Tab") return;
|
|
965
|
-
const els = getFocusable();
|
|
966
|
-
if (els.length === 0) return;
|
|
967
|
-
const first = els[0];
|
|
968
|
-
const last = els[els.length - 1];
|
|
969
|
-
if (e.shiftKey) {
|
|
970
|
-
if (document.activeElement === first || document.activeElement === container) {
|
|
971
|
-
e.preventDefault();
|
|
972
|
-
last.focus();
|
|
973
|
-
}
|
|
974
|
-
} else {
|
|
975
|
-
if (document.activeElement === last) {
|
|
976
|
-
e.preventDefault();
|
|
977
|
-
first.focus();
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
};
|
|
981
|
-
const handleEscape = (e) => {
|
|
982
|
-
if (e.key === "Escape") {
|
|
983
|
-
container.dispatchEvent(new CustomEvent("consenti:closeRequest", { bubbles: true }));
|
|
984
|
-
}
|
|
985
|
-
};
|
|
986
|
-
document.addEventListener("keydown", handleKeydown);
|
|
987
|
-
document.addEventListener("keydown", handleEscape);
|
|
988
|
-
getFocusable()[0]?.focus();
|
|
989
|
-
return () => {
|
|
990
|
-
document.removeEventListener("keydown", handleKeydown);
|
|
991
|
-
document.removeEventListener("keydown", handleEscape);
|
|
992
|
-
};
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
// src/ui/modal.ts
|
|
996
|
-
var Modal = class {
|
|
997
|
-
constructor() {
|
|
998
|
-
this.el = null;
|
|
999
|
-
this.triggerEl = null;
|
|
1000
|
-
this.trapCleanup = null;
|
|
1001
|
-
/** Map of category ID → toggle button element, used to read state on submit. */
|
|
1002
|
-
this.toggleMap = /* @__PURE__ */ new Map();
|
|
1003
|
-
this.receiptCheckbox = null;
|
|
1004
|
-
/** Live toggle state — updated on each click so `getToggleConsent()` reads the latest. */
|
|
1005
|
-
this.toggleState = /* @__PURE__ */ new Map();
|
|
1006
|
-
/** When `true`, the modal wrapper is passthrough (overlayOpacity === 0). */
|
|
1007
|
-
this.passthrough = false;
|
|
1008
|
-
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Constructs the modal DOM from the given config.
|
|
1011
|
-
* The modal is not inserted into the document until `open()` is called.
|
|
1012
|
-
*
|
|
1013
|
-
* @param config - Modal layout and content config from the resolved profile.
|
|
1014
|
-
* @param initialConsent - Current stored consent, used to pre-set toggle states.
|
|
1015
|
-
* @param handlers - Click handlers wired to each button.
|
|
1016
|
-
* @param allowReceipt - When `true`, renders the consent receipt download checkbox.
|
|
1017
|
-
* @param dpdpaConfig - DPDPA grievance notice config.
|
|
1018
|
-
* @param locales - All available locale codes (for locale switcher).
|
|
1019
|
-
* @param activeLocale - The currently active locale code.
|
|
1020
|
-
* @param onLocaleSwitch - Callback invoked when the user selects a different locale.
|
|
1021
|
-
*/
|
|
1022
|
-
build(config, initialConsent, handlers, allowReceipt, dpdpaConfig, locales, activeLocale, onLocaleSwitch) {
|
|
1023
|
-
const position = config.position ?? "center";
|
|
1024
|
-
const wrapper = document.createElement("div");
|
|
1025
|
-
wrapper.id = "consenti-modal";
|
|
1026
|
-
wrapper.className = `consenti-modal consenti-modal--${position}`;
|
|
1027
|
-
wrapper.setAttribute("role", "dialog");
|
|
1028
|
-
wrapper.setAttribute("aria-modal", "true");
|
|
1029
|
-
const overlayOpacity = config.overlayOpacity ?? 50;
|
|
1030
|
-
this.passthrough = overlayOpacity === 0;
|
|
1031
|
-
if (overlayOpacity > 0) {
|
|
1032
|
-
const overlayClickHandler = config.persistent ? void 0 : () => handlers.onClose();
|
|
1033
|
-
const overlay = createOverlay(overlayOpacity, overlayClickHandler);
|
|
1034
|
-
overlay.className = "consenti-modal__overlay";
|
|
1035
|
-
wrapper.appendChild(overlay);
|
|
1036
|
-
} else {
|
|
1037
|
-
wrapper.classList.add("consenti-modal--passthrough");
|
|
1038
|
-
}
|
|
1039
|
-
const container = document.createElement("div");
|
|
1040
|
-
container.className = "consenti-modal__container";
|
|
1041
|
-
const header = document.createElement("div");
|
|
1042
|
-
header.className = "consenti-modal__header";
|
|
1043
|
-
if (config.heading) {
|
|
1044
|
-
const headingTag = config.headingTag ?? "h2";
|
|
1045
|
-
const heading = document.createElement(headingTag);
|
|
1046
|
-
heading.id = "consenti-modal-heading";
|
|
1047
|
-
heading.className = "consenti-modal__heading";
|
|
1048
|
-
heading.textContent = config.heading;
|
|
1049
|
-
header.appendChild(heading);
|
|
1050
|
-
wrapper.setAttribute("aria-labelledby", "consenti-modal-heading");
|
|
1051
|
-
}
|
|
1052
|
-
const hasClose = config.showClose !== false;
|
|
1053
|
-
const hasLocaleSwitcher = config.showLocaleSwitcher && locales && locales.length > 1;
|
|
1054
|
-
if (hasLocaleSwitcher || hasClose) {
|
|
1055
|
-
const headerControls = document.createElement("div");
|
|
1056
|
-
headerControls.className = "consenti-modal__header-controls";
|
|
1057
|
-
if (hasLocaleSwitcher && locales && onLocaleSwitch) {
|
|
1058
|
-
headerControls.appendChild(buildModalLocaleSwitcher(locales, activeLocale, onLocaleSwitch));
|
|
1059
|
-
}
|
|
1060
|
-
if (hasClose) {
|
|
1061
|
-
const close = document.createElement("button");
|
|
1062
|
-
close.type = "button";
|
|
1063
|
-
close.className = "consenti-modal__close consenti-btn consenti-btn--close";
|
|
1064
|
-
close.setAttribute("aria-label", "Close preference modal");
|
|
1065
|
-
close.textContent = "\xD7";
|
|
1066
|
-
close.addEventListener("click", handlers.onClose);
|
|
1067
|
-
headerControls.appendChild(close);
|
|
1068
|
-
}
|
|
1069
|
-
header.appendChild(headerControls);
|
|
1070
|
-
}
|
|
1071
|
-
container.appendChild(header);
|
|
1072
|
-
if (config.subheading) {
|
|
1073
|
-
const sub = document.createElement("p");
|
|
1074
|
-
sub.className = "consenti-modal__subheading";
|
|
1075
|
-
sub.textContent = config.subheading;
|
|
1076
|
-
container.appendChild(sub);
|
|
1077
|
-
}
|
|
1078
|
-
if (config.htmlText) {
|
|
1079
|
-
const desc = document.createElement("div");
|
|
1080
|
-
desc.className = "consenti-modal__text";
|
|
1081
|
-
desc.innerHTML = config.htmlText;
|
|
1082
|
-
container.appendChild(desc);
|
|
1083
|
-
}
|
|
1084
|
-
const linkButtons = config.buttons.filter((b) => b.action === "link");
|
|
1085
|
-
if (linkButtons.length > 0) {
|
|
1086
|
-
const linksContainer = document.createElement("div");
|
|
1087
|
-
linksContainer.className = "consenti-modal__links";
|
|
1088
|
-
for (const btn of linkButtons) {
|
|
1089
|
-
if (!btn.url) continue;
|
|
1090
|
-
const anchor = document.createElement("a");
|
|
1091
|
-
anchor.href = btn.url;
|
|
1092
|
-
anchor.className = `consenti-modal__link consenti-btn consenti-btn--${btn.style ?? "text"}`;
|
|
1093
|
-
anchor.textContent = btn.text;
|
|
1094
|
-
anchor.setAttribute("target", "_blank");
|
|
1095
|
-
anchor.setAttribute("rel", "noopener noreferrer");
|
|
1096
|
-
linksContainer.appendChild(anchor);
|
|
1097
|
-
}
|
|
1098
|
-
container.appendChild(linksContainer);
|
|
1099
|
-
}
|
|
1100
|
-
const body = document.createElement("div");
|
|
1101
|
-
body.className = "consenti-modal__body";
|
|
1102
|
-
const categories = document.createElement("div");
|
|
1103
|
-
categories.className = "consenti-modal__categories";
|
|
1104
|
-
for (const cat of config.categories) {
|
|
1105
|
-
const catEl = this.buildCategory(cat, initialConsent);
|
|
1106
|
-
categories.appendChild(catEl);
|
|
1107
|
-
}
|
|
1108
|
-
body.appendChild(categories);
|
|
1109
|
-
container.appendChild(body);
|
|
1110
|
-
if (allowReceipt) {
|
|
1111
|
-
container.appendChild(this.buildReceiptOption());
|
|
1112
|
-
}
|
|
1113
|
-
if (dpdpaConfig) {
|
|
1114
|
-
const notice = document.createElement("div");
|
|
1115
|
-
notice.className = "consenti-modal__dpdpa-notice";
|
|
1116
|
-
notice.innerHTML = [
|
|
1117
|
-
`<strong>Data Fiduciary:</strong> ${dpdpaConfig.dataFiduciary}.`,
|
|
1118
|
-
dpdpaConfig.purposeDescription ? ` <strong>Purpose:</strong> ${dpdpaConfig.purposeDescription}.` : "",
|
|
1119
|
-
` You may withdraw consent at any time or contact our Grievance Officer at`,
|
|
1120
|
-
` <a href="mailto:${dpdpaConfig.grievanceEmail}">${dpdpaConfig.grievanceEmail}</a>.`
|
|
1121
|
-
].join("");
|
|
1122
|
-
container.appendChild(notice);
|
|
1123
|
-
}
|
|
1124
|
-
const btns = document.createElement("div");
|
|
1125
|
-
btns.className = "consenti-modal__buttons";
|
|
1126
|
-
for (const btn of config.buttons.filter((b) => b.action !== "link")) {
|
|
1127
|
-
btns.appendChild(buildButton(btn, handlers));
|
|
1128
|
-
}
|
|
1129
|
-
container.appendChild(btns);
|
|
1130
|
-
wrapper.appendChild(container);
|
|
1131
|
-
wrapper.addEventListener("consenti:closeRequest", () => handlers.onClose());
|
|
1132
|
-
this.el = wrapper;
|
|
1133
|
-
}
|
|
1134
|
-
buildCategory(cat, initialConsent) {
|
|
1135
|
-
const isLI = cat.type === "legitimate_interest";
|
|
1136
|
-
const isMandatory = cat.mandatory === true;
|
|
1137
|
-
let defaultOn;
|
|
1138
|
-
if (isMandatory) {
|
|
1139
|
-
defaultOn = true;
|
|
1140
|
-
} else if (isLI) {
|
|
1141
|
-
defaultOn = initialConsent[cat.cookies[0] ?? ""] !== "objected";
|
|
1142
|
-
} else {
|
|
1143
|
-
defaultOn = initialConsent[cat.cookies[0] ?? ""] === "granted";
|
|
1144
|
-
}
|
|
1145
|
-
this.toggleState.set(cat.id, defaultOn);
|
|
1146
|
-
const wrapper = document.createElement("div");
|
|
1147
|
-
wrapper.className = `consenti-category${isMandatory ? " consenti-category--mandatory" : ""}`;
|
|
1148
|
-
const header = document.createElement("div");
|
|
1149
|
-
header.className = "consenti-category__header";
|
|
1150
|
-
const headingTag = cat.headingTag ?? "h3";
|
|
1151
|
-
const heading = document.createElement(headingTag);
|
|
1152
|
-
heading.id = `consenti-cat-${cat.id}-heading`;
|
|
1153
|
-
heading.className = "consenti-category__heading";
|
|
1154
|
-
heading.textContent = cat.heading;
|
|
1155
|
-
header.appendChild(heading);
|
|
1156
|
-
const toggle = document.createElement("button");
|
|
1157
|
-
toggle.type = "button";
|
|
1158
|
-
toggle.className = `consenti-category__toggle${isMandatory ? " consenti-category__toggle--mandatory" : ""}`;
|
|
1159
|
-
toggle.setAttribute("role", "switch");
|
|
1160
|
-
toggle.setAttribute("aria-checked", String(defaultOn));
|
|
1161
|
-
toggle.setAttribute("aria-labelledby", `consenti-cat-${cat.id}-heading`);
|
|
1162
|
-
if (isMandatory) toggle.setAttribute("aria-disabled", "true");
|
|
1163
|
-
const knob = document.createElement("span");
|
|
1164
|
-
knob.className = "consenti-category__toggle-knob";
|
|
1165
|
-
knob.setAttribute("aria-hidden", "true");
|
|
1166
|
-
toggle.appendChild(knob);
|
|
1167
|
-
if (!isMandatory) {
|
|
1168
|
-
toggle.addEventListener("click", () => {
|
|
1169
|
-
const current = this.toggleState.get(cat.id) ?? false;
|
|
1170
|
-
const next = !current;
|
|
1171
|
-
this.toggleState.set(cat.id, next);
|
|
1172
|
-
toggle.setAttribute("aria-checked", String(next));
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
this.toggleMap.set(cat.id, toggle);
|
|
1176
|
-
header.appendChild(toggle);
|
|
1177
|
-
wrapper.appendChild(header);
|
|
1178
|
-
const text = document.createElement("div");
|
|
1179
|
-
text.className = "consenti-category__text";
|
|
1180
|
-
text.innerHTML = cat.htmlText;
|
|
1181
|
-
wrapper.appendChild(text);
|
|
1182
|
-
if (isLI && cat.legitimateInterest?.description) {
|
|
1183
|
-
const li = document.createElement("p");
|
|
1184
|
-
li.className = "consenti-category__li-desc";
|
|
1185
|
-
li.textContent = cat.legitimateInterest.description;
|
|
1186
|
-
wrapper.appendChild(li);
|
|
1187
|
-
}
|
|
1188
|
-
return wrapper;
|
|
1189
|
-
}
|
|
1190
|
-
buildReceiptOption() {
|
|
1191
|
-
const wrapper = document.createElement("div");
|
|
1192
|
-
wrapper.className = "consenti-modal__receipt-option";
|
|
1193
|
-
const label = document.createElement("label");
|
|
1194
|
-
label.className = "consenti-modal__receipt-label";
|
|
1195
|
-
const checkbox = document.createElement("input");
|
|
1196
|
-
checkbox.type = "checkbox";
|
|
1197
|
-
checkbox.className = "consenti-modal__receipt-checkbox";
|
|
1198
|
-
checkbox.id = "consenti-receipt-checkbox";
|
|
1199
|
-
checkbox.setAttribute("aria-describedby", "consenti-receipt-desc");
|
|
1200
|
-
this.receiptCheckbox = checkbox;
|
|
1201
|
-
label.appendChild(checkbox);
|
|
1202
|
-
label.append(" Get a copy of my consent choices (JSON)");
|
|
1203
|
-
wrapper.appendChild(label);
|
|
1204
|
-
const desc = document.createElement("p");
|
|
1205
|
-
desc.id = "consenti-receipt-desc";
|
|
1206
|
-
desc.className = "consenti-modal__receipt-desc";
|
|
1207
|
-
desc.textContent = "A JSON file will be downloaded to your device when you save your preferences.";
|
|
1208
|
-
wrapper.appendChild(desc);
|
|
1209
|
-
return wrapper;
|
|
1210
|
-
}
|
|
1211
|
-
/**
|
|
1212
|
-
* Appends the modal to `document.body` and activates the focus trap.
|
|
1213
|
-
* The receipt checkbox (if present) is reset to unchecked.
|
|
1214
|
-
*
|
|
1215
|
-
* @param triggerEl - The element that opened the modal. Focus returns here on `close()`.
|
|
1216
|
-
*/
|
|
1217
|
-
open(triggerEl) {
|
|
1218
|
-
if (!this.el) return;
|
|
1219
|
-
this.triggerEl = triggerEl ?? document.activeElement;
|
|
1220
|
-
if (this.receiptCheckbox) this.receiptCheckbox.checked = false;
|
|
1221
|
-
document.body.appendChild(this.el);
|
|
1222
|
-
if (!this.passthrough) {
|
|
1223
|
-
this.trapCleanup = trapFocus(this.el);
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
/**
|
|
1227
|
-
* Removes the modal from `document.body`, deactivates the focus trap,
|
|
1228
|
-
* and returns focus to `triggerEl`.
|
|
1229
|
-
*/
|
|
1230
|
-
close() {
|
|
1231
|
-
this.trapCleanup?.();
|
|
1232
|
-
this.trapCleanup = null;
|
|
1233
|
-
this.el?.remove();
|
|
1234
|
-
this.triggerEl?.focus();
|
|
1235
|
-
this.triggerEl = null;
|
|
1236
|
-
}
|
|
1237
|
-
/** Returns `true` if the modal is currently mounted in the document. */
|
|
1238
|
-
isOpen() {
|
|
1239
|
-
return this.el?.isConnected === true;
|
|
1240
|
-
}
|
|
1241
|
-
/** Returns `true` if the receipt download checkbox is checked at the time of calling. */
|
|
1242
|
-
isReceiptRequested() {
|
|
1243
|
-
return this.receiptCheckbox?.checked ?? false;
|
|
1244
|
-
}
|
|
1245
|
-
/**
|
|
1246
|
-
* Reads the current toggle state map and converts it to a `ConsentValue`.
|
|
1247
|
-
*
|
|
1248
|
-
* Called by the submit handler to build the consent object before writing to storage.
|
|
1249
|
-
*
|
|
1250
|
-
* @param categories - The category list from the resolved profile (provides cookie IDs and type).
|
|
1251
|
-
*/
|
|
1252
|
-
getToggleConsent(categories) {
|
|
1253
|
-
const consent = {};
|
|
1254
|
-
for (const cat of categories) {
|
|
1255
|
-
const isLI = cat.type === "legitimate_interest";
|
|
1256
|
-
const isMandatory = cat.mandatory === true;
|
|
1257
|
-
const on = this.toggleState.get(cat.id) ?? false;
|
|
1258
|
-
for (const cookieId of cat.cookies) {
|
|
1259
|
-
if (isMandatory) {
|
|
1260
|
-
consent[cookieId] = "granted";
|
|
1261
|
-
} else if (isLI) {
|
|
1262
|
-
consent[cookieId] = on ? "granted" : "objected";
|
|
1263
|
-
} else {
|
|
1264
|
-
consent[cookieId] = on ? "granted" : "denied";
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
return consent;
|
|
1269
|
-
}
|
|
1270
|
-
/** Removes the modal element from the DOM and clears all internal state. */
|
|
1271
|
-
destroy() {
|
|
1272
|
-
this.trapCleanup?.();
|
|
1273
|
-
this.el?.remove();
|
|
1274
|
-
this.el = null;
|
|
1275
|
-
this.toggleMap.clear();
|
|
1276
|
-
this.toggleState.clear();
|
|
1277
|
-
this.receiptCheckbox = null;
|
|
1278
|
-
}
|
|
1279
|
-
};
|
|
1280
|
-
function buildModalLocaleSwitcher(locales, activeLocale, onSwitch) {
|
|
1281
|
-
const wrapper = document.createElement("div");
|
|
1282
|
-
wrapper.className = "consenti-locale-switcher consenti-locale-switcher--modal";
|
|
1283
|
-
const btn = document.createElement("button");
|
|
1284
|
-
btn.type = "button";
|
|
1285
|
-
btn.className = "consenti-locale-switcher__btn consenti-btn consenti-btn--close";
|
|
1286
|
-
btn.setAttribute("aria-label", "Switch language");
|
|
1287
|
-
btn.setAttribute("aria-haspopup", "listbox");
|
|
1288
|
-
btn.textContent = "\u{1F310}";
|
|
1289
|
-
const list = document.createElement("ul");
|
|
1290
|
-
list.className = "consenti-locale-switcher__list";
|
|
1291
|
-
list.setAttribute("role", "listbox");
|
|
1292
|
-
list.setAttribute("aria-label", "Select language");
|
|
1293
|
-
list.hidden = true;
|
|
1294
|
-
for (const locale of locales) {
|
|
1295
|
-
const item = document.createElement("li");
|
|
1296
|
-
item.setAttribute("role", "option");
|
|
1297
|
-
item.setAttribute("aria-selected", String(locale === activeLocale));
|
|
1298
|
-
const localeBtn = document.createElement("button");
|
|
1299
|
-
localeBtn.type = "button";
|
|
1300
|
-
localeBtn.className = `consenti-locale-switcher__option${locale === activeLocale ? " consenti-locale-switcher__option--active" : ""}`;
|
|
1301
|
-
localeBtn.textContent = locale;
|
|
1302
|
-
localeBtn.addEventListener("click", (e) => {
|
|
1303
|
-
e.stopPropagation();
|
|
1304
|
-
list.hidden = true;
|
|
1305
|
-
if (locale !== activeLocale) onSwitch(locale);
|
|
1306
|
-
});
|
|
1307
|
-
item.appendChild(localeBtn);
|
|
1308
|
-
list.appendChild(item);
|
|
1309
|
-
}
|
|
1310
|
-
btn.addEventListener("click", (e) => {
|
|
1311
|
-
e.stopPropagation();
|
|
1312
|
-
list.hidden = !list.hidden;
|
|
1313
|
-
});
|
|
1314
|
-
document.addEventListener("click", () => {
|
|
1315
|
-
list.hidden = true;
|
|
1316
|
-
}, { capture: true, once: false });
|
|
1317
|
-
wrapper.appendChild(btn);
|
|
1318
|
-
wrapper.appendChild(list);
|
|
1319
|
-
return wrapper;
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
// src/ui/renderer.ts
|
|
1323
|
-
var ROOT_ID = "consenti-root";
|
|
1324
|
-
var Renderer = class {
|
|
1325
|
-
constructor() {
|
|
1326
|
-
this.root = null;
|
|
1327
|
-
this.styleEl = null;
|
|
1328
|
-
}
|
|
1329
|
-
/**
|
|
1330
|
-
* Returns the mount-point element, creating `#consenti-root` if needed.
|
|
1331
|
-
*
|
|
1332
|
-
* When `rootEl` is supplied:
|
|
1333
|
-
* - `string` → resolved via `document.querySelector`. Throws if no match.
|
|
1334
|
-
* - `HTMLElement` → used directly. Throws if not attached to the document.
|
|
1335
|
-
* On subsequent calls the previously stored root is returned immediately.
|
|
1336
|
-
*
|
|
1337
|
-
* @throws `Error` if called in SSR or if a supplied `rootEl` cannot be resolved.
|
|
1338
|
-
*/
|
|
1339
|
-
mount(rootEl) {
|
|
1340
|
-
if (!isClient()) throw new Error("[Consenti] Renderer.mount() called in SSR context");
|
|
1341
|
-
if (this.root) return this.root;
|
|
1342
|
-
if (rootEl !== void 0) {
|
|
1343
|
-
if (typeof rootEl === "string") {
|
|
1344
|
-
const found = document.querySelector(rootEl);
|
|
1345
|
-
if (!found) throw new Error(`[Consenti] rootEl selector "${rootEl}" did not match any element.`);
|
|
1346
|
-
this.root = found;
|
|
1347
|
-
} else {
|
|
1348
|
-
if (!document.contains(rootEl)) throw new Error("[Consenti] rootEl element is not attached to the document.");
|
|
1349
|
-
this.root = rootEl;
|
|
1350
|
-
}
|
|
1351
|
-
return this.root;
|
|
1352
|
-
}
|
|
1353
|
-
let root = document.getElementById(ROOT_ID);
|
|
1354
|
-
if (!root) {
|
|
1355
|
-
root = document.createElement("div");
|
|
1356
|
-
root.id = ROOT_ID;
|
|
1357
|
-
document.body.appendChild(root);
|
|
1358
|
-
}
|
|
1359
|
-
this.root = root;
|
|
1360
|
-
return root;
|
|
1361
|
-
}
|
|
1362
|
-
/**
|
|
1363
|
-
* Injects a `<style id="consenti-styles">` tag into `<head>` with the given CSS string.
|
|
1364
|
-
* No-ops if the style element already exists (idempotent).
|
|
1365
|
-
*
|
|
1366
|
-
* @param css - The CSS content to inject.
|
|
1367
|
-
*/
|
|
1368
|
-
injectStyles(css) {
|
|
1369
|
-
if (!isClient()) return;
|
|
1370
|
-
if (this.styleEl) return;
|
|
1371
|
-
const style = document.createElement("style");
|
|
1372
|
-
style.id = "consenti-styles";
|
|
1373
|
-
style.textContent = css;
|
|
1374
|
-
document.head.appendChild(style);
|
|
1375
|
-
this.styleEl = style;
|
|
1376
|
-
}
|
|
1377
|
-
/** Removes `#consenti-root` and the injected `<style>` tag from the document. */
|
|
1378
|
-
unmount() {
|
|
1379
|
-
this.root?.remove();
|
|
1380
|
-
this.styleEl?.remove();
|
|
1381
|
-
this.root = null;
|
|
1382
|
-
this.styleEl = null;
|
|
1383
|
-
}
|
|
1384
|
-
/**
|
|
1385
|
-
* Announces a message to screen readers via a visually-hidden `aria-live="polite"` region.
|
|
1386
|
-
*
|
|
1387
|
-
* The region is created on first call and reused. The message is cleared then
|
|
1388
|
-
* re-set via `requestAnimationFrame` to guarantee the change is detected by
|
|
1389
|
-
* AT even if the same string is announced twice in a row.
|
|
1390
|
-
*
|
|
1391
|
-
* @param message - The message to announce (plain text, not HTML).
|
|
1392
|
-
*/
|
|
1393
|
-
announceToScreenReader(message) {
|
|
1394
|
-
if (!isClient()) return;
|
|
1395
|
-
let announcer = document.getElementById("consenti-announcer");
|
|
1396
|
-
if (!announcer) {
|
|
1397
|
-
announcer = document.createElement("div");
|
|
1398
|
-
announcer.id = "consenti-announcer";
|
|
1399
|
-
announcer.setAttribute("role", "status");
|
|
1400
|
-
announcer.setAttribute("aria-live", "polite");
|
|
1401
|
-
announcer.setAttribute("aria-atomic", "true");
|
|
1402
|
-
announcer.style.cssText = "position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;";
|
|
1403
|
-
document.body.appendChild(announcer);
|
|
1404
|
-
}
|
|
1405
|
-
announcer.textContent = "";
|
|
1406
|
-
requestAnimationFrame(() => {
|
|
1407
|
-
if (announcer) announcer.textContent = message;
|
|
1408
|
-
});
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
|
|
1412
|
-
// src/core/consenti-setup.ts
|
|
1413
|
-
var ConsentiSetup = class {
|
|
1414
|
-
/**
|
|
1415
|
-
* Creates and initialises the consent widget.
|
|
1416
|
-
*
|
|
1417
|
-
* Construction is synchronous; the async `init()` is launched in the background.
|
|
1418
|
-
* Use `await widget.ready` or `widget.onReady(cb)` to run code after init completes.
|
|
1419
|
-
*
|
|
1420
|
-
* @param config - Widget configuration. See `ConsentiConfig` for all options.
|
|
1421
|
-
*/
|
|
1422
|
-
constructor(config) {
|
|
1423
|
-
this.config = config;
|
|
1424
|
-
this.initialized = false;
|
|
1425
|
-
this.initializing = false;
|
|
1426
|
-
this.profile = null;
|
|
1427
|
-
this.consentStore = null;
|
|
1428
|
-
this.eventBus = null;
|
|
1429
|
-
this.banner = null;
|
|
1430
|
-
this.modal = null;
|
|
1431
|
-
this.renderer = null;
|
|
1432
|
-
this.broadcastChannel = new ConsentiChannel();
|
|
1433
|
-
this.plugins = [];
|
|
1434
|
-
/** Tracks which banner variant is currently visible, or null when hidden. */
|
|
1435
|
-
this._bannerVariant = null;
|
|
1436
|
-
this.readyPromise = new Promise((resolve) => {
|
|
1437
|
-
this.readyResolve = resolve;
|
|
1438
|
-
});
|
|
1439
|
-
if (!isClient()) return;
|
|
1440
|
-
if (config.api?.enabled && config.core.storage === "localStorage") {
|
|
1441
|
-
console.warn(
|
|
1442
|
-
"[Consenti] localStorage storage mode cannot be used with API mode (API sets cookies via Set-Cookie header). Falling back to cookie storage."
|
|
1443
|
-
);
|
|
1444
|
-
config.core.storage = "cookie";
|
|
1445
|
-
}
|
|
1446
|
-
if (config.autoInit !== false) {
|
|
1447
|
-
this.init().catch((err) => console.warn("[Consenti] Init error:", err));
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
profileId() {
|
|
1451
|
-
return this.config.core.profileId ?? 0;
|
|
1452
|
-
}
|
|
1453
|
-
/**
|
|
1454
|
-
* Starts widget initialisation. Called automatically unless `autoInit: false` is set.
|
|
1455
|
-
* Can be called explicitly after construction when `autoInit: false`, or after `destroy()`
|
|
1456
|
-
* to re-initialise the same instance.
|
|
1457
|
-
*/
|
|
1458
|
-
async init() {
|
|
1459
|
-
if (!isClient()) return;
|
|
1460
|
-
if (this.initializing) return;
|
|
1461
|
-
this.initializing = true;
|
|
1462
|
-
this.initialized = false;
|
|
1463
|
-
this.readyPromise = new Promise((resolve) => {
|
|
1464
|
-
this.readyResolve = resolve;
|
|
1465
|
-
});
|
|
1466
|
-
try {
|
|
1467
|
-
const storageMode = this.config.core.storage ?? "cookie";
|
|
1468
|
-
const userId = this.config.core.userId ?? ConsentStore.getOrCreateUserId(this.profileId(), storageMode);
|
|
1469
|
-
this.profile = await resolveProfile(this.config);
|
|
1470
|
-
if (this.config.profileOverride) {
|
|
1471
|
-
this.profile = { ...this.profile, ...this.config.profileOverride };
|
|
1472
|
-
}
|
|
1473
|
-
this.eventBus = new EventBus(this.profileId(), this.config.utils?.gtm);
|
|
1474
|
-
this.consentStore = new ConsentStore(
|
|
1475
|
-
userId,
|
|
1476
|
-
this.profileId(),
|
|
1477
|
-
storageMode,
|
|
1478
|
-
this.config.core.cookieDomains
|
|
1479
|
-
);
|
|
1480
|
-
this.renderer = new Renderer();
|
|
1481
|
-
if (!this.config.core.disableCssTemplate && CONSENTI_CSS) {
|
|
1482
|
-
this.renderer.injectStyles(CONSENTI_CSS);
|
|
1483
|
-
}
|
|
1484
|
-
this.banner = new Banner();
|
|
1485
|
-
this.modal = new Modal();
|
|
1486
|
-
this.applyTheme();
|
|
1487
|
-
this.applyDarkMode();
|
|
1488
|
-
this.broadcastChannel.connect((msg) => this.handleBroadcastMessage(msg));
|
|
1489
|
-
await this.runPlugins();
|
|
1490
|
-
const signingKey = this.profile.cookieSigningKey ?? this.config.core.cookieSigningKey;
|
|
1491
|
-
const existing = this.config.core.signCookies && signingKey ? await this.consentStore.readAndVerify(signingKey) : this.consentStore.read();
|
|
1492
|
-
const hasExisting = existing !== null;
|
|
1493
|
-
this.eventBus.dispatch("consenti:bannerInitialized", {
|
|
1494
|
-
profileId: this.profileId(),
|
|
1495
|
-
hasExistingConsent: hasExisting
|
|
1496
|
-
});
|
|
1497
|
-
const gpcMode = this.config.core.autoHonorGPC ?? false;
|
|
1498
|
-
if (gpcMode && detectGPC()) {
|
|
1499
|
-
const gpcConsent = applyGPCToConsent(this.profile.cookies, {}, gpcMode);
|
|
1500
|
-
if (gpcMode === "strict") {
|
|
1501
|
-
await this.submitConsent(gpcConsent, true);
|
|
1502
|
-
this.initialized = true;
|
|
1503
|
-
this.readyResolve();
|
|
1504
|
-
return;
|
|
1505
|
-
}
|
|
1506
|
-
if (!hasExisting) {
|
|
1507
|
-
const gpcSigningKey = this.profile.cookieSigningKey ?? this.config.core.cookieSigningKey;
|
|
1508
|
-
if (this.config.core.signCookies && gpcSigningKey && this.consentStore) {
|
|
1509
|
-
this.lastSignature = await this.consentStore.writeAndSign(gpcConsent, gpcSigningKey);
|
|
1510
|
-
} else {
|
|
1511
|
-
this.consentStore?.write(gpcConsent);
|
|
1512
|
-
}
|
|
1513
|
-
this.broadcastChannel.send({
|
|
1514
|
-
type: "consentUpdated",
|
|
1515
|
-
consent: gpcConsent,
|
|
1516
|
-
profileId: this.profileId()
|
|
1517
|
-
});
|
|
1518
|
-
this.eventBus?.dispatch("consenti:consentSubmitted", {
|
|
1519
|
-
consent: gpcConsent,
|
|
1520
|
-
gpcDetected: true,
|
|
1521
|
-
consentId: crypto.randomUUID(),
|
|
1522
|
-
consentAction: this.deriveAction(gpcConsent, false),
|
|
1523
|
-
pageUrl: window.location.href
|
|
1524
|
-
});
|
|
1525
|
-
this.showBanner(true);
|
|
1526
|
-
this.initialized = true;
|
|
1527
|
-
this.readyResolve();
|
|
1528
|
-
return;
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
const regulation = this.config.core.regulation ?? "gdpr";
|
|
1532
|
-
if (regulation === "ccpa" && !hasExisting) {
|
|
1533
|
-
const defaultConsent = {};
|
|
1534
|
-
for (const cookie of this.profile.cookies) {
|
|
1535
|
-
defaultConsent[cookie.id] = "granted";
|
|
1536
|
-
}
|
|
1537
|
-
const ccpaSigKey = this.profile.cookieSigningKey ?? this.config.core.cookieSigningKey;
|
|
1538
|
-
if (this.config.core.signCookies && ccpaSigKey) {
|
|
1539
|
-
await this.consentStore.writeAndSign(defaultConsent, ccpaSigKey);
|
|
1540
|
-
} else {
|
|
1541
|
-
this.consentStore.write(defaultConsent);
|
|
1542
|
-
}
|
|
1543
|
-
this.initialized = true;
|
|
1544
|
-
this.readyResolve();
|
|
1545
|
-
return;
|
|
1546
|
-
}
|
|
1547
|
-
if (regulation === "cpra" && !hasExisting) {
|
|
1548
|
-
const gpcActive = this.config.core.autoHonorGPC && detectGPC();
|
|
1549
|
-
const defaultConsent = {};
|
|
1550
|
-
for (const cookie of this.profile.cookies) {
|
|
1551
|
-
if (cookie.mandatory) {
|
|
1552
|
-
defaultConsent[cookie.id] = "granted";
|
|
1553
|
-
continue;
|
|
1554
|
-
}
|
|
1555
|
-
if (cookie.cpraCategory === "sensitive") {
|
|
1556
|
-
defaultConsent[cookie.id] = "denied";
|
|
1557
|
-
} else if (gpcActive && (cookie.cpraCategory === "sale" || cookie.cpraCategory === "sharing")) {
|
|
1558
|
-
defaultConsent[cookie.id] = "denied";
|
|
1559
|
-
} else {
|
|
1560
|
-
defaultConsent[cookie.id] = "granted";
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
const sigKey = this.profile.cookieSigningKey ?? this.config.core.cookieSigningKey;
|
|
1564
|
-
if (this.config.core.signCookies && sigKey) {
|
|
1565
|
-
await this.consentStore.writeAndSign(defaultConsent, sigKey);
|
|
1566
|
-
} else {
|
|
1567
|
-
this.consentStore.write(defaultConsent);
|
|
1568
|
-
}
|
|
1569
|
-
this.initialized = true;
|
|
1570
|
-
this.readyResolve();
|
|
1571
|
-
return;
|
|
1572
|
-
}
|
|
1573
|
-
if (!hasExisting) {
|
|
1574
|
-
this.showBanner();
|
|
1575
|
-
}
|
|
1576
|
-
this.initialized = true;
|
|
1577
|
-
this.readyResolve();
|
|
1578
|
-
} finally {
|
|
1579
|
-
this.initializing = false;
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
/** Applies the `consenti-root--dark` class based on config or profile flag. */
|
|
1583
|
-
applyDarkMode() {
|
|
1584
|
-
if (!this.renderer) return;
|
|
1585
|
-
const isDark = this.config.darkMode ?? this.profile?.darkMode ?? false;
|
|
1586
|
-
const root = this.renderer.mount(this.config.rootEl);
|
|
1587
|
-
if (isDark) {
|
|
1588
|
-
root.classList.add("consenti-root--dark");
|
|
1589
|
-
} else {
|
|
1590
|
-
root.classList.remove("consenti-root--dark");
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
/**
|
|
1594
|
-
* Injects CSS custom property overrides supplied via `core.theme` into the
|
|
1595
|
-
* Consenti root element so they cascade down to all widget elements.
|
|
1596
|
-
*/
|
|
1597
|
-
applyTheme() {
|
|
1598
|
-
const theme = this.config.core.theme;
|
|
1599
|
-
if (!theme || !this.renderer) return;
|
|
1600
|
-
const map = {
|
|
1601
|
-
"--consenti-color-bg": theme.bgColor,
|
|
1602
|
-
"--consenti-color-text": theme.textColor,
|
|
1603
|
-
"--consenti-color-primary": theme.primaryColor,
|
|
1604
|
-
"--consenti-color-primary-text": theme.primaryTextColor,
|
|
1605
|
-
"--consenti-color-secondary": theme.secondaryColor,
|
|
1606
|
-
"--consenti-color-secondary-text": theme.secondaryTextColor,
|
|
1607
|
-
"--consenti-color-border": theme.borderColor,
|
|
1608
|
-
"--consenti-font-family": theme.fontFamily,
|
|
1609
|
-
"--consenti-font-size-base": theme.fontSizeBase,
|
|
1610
|
-
"--consenti-font-size-heading": theme.fontSizeHeading,
|
|
1611
|
-
"--consenti-border-radius": theme.borderRadius,
|
|
1612
|
-
"--consenti-border-radius-btn": theme.buttonBorderRadius,
|
|
1613
|
-
"--consenti-toggle-bg-on": theme.toggleBgOn,
|
|
1614
|
-
"--consenti-toggle-bg-off": theme.toggleBgOff,
|
|
1615
|
-
"--consenti-color-accent": theme.accentColor,
|
|
1616
|
-
"--consenti-color-accent-text": theme.accentTextColor
|
|
1617
|
-
};
|
|
1618
|
-
const root = this.renderer.mount(this.config.rootEl);
|
|
1619
|
-
for (const [prop, value] of Object.entries(map)) {
|
|
1620
|
-
if (value !== void 0) root.style.setProperty(prop, value);
|
|
1621
|
-
}
|
|
1622
|
-
if (theme.fontSizeMultiplier) {
|
|
1623
|
-
const mult = parseFloat(theme.fontSizeMultiplier);
|
|
1624
|
-
if (!isNaN(mult)) {
|
|
1625
|
-
const baseSize = parseFloat(getComputedStyle(root).getPropertyValue("--consenti-font-size-base") || "14");
|
|
1626
|
-
const headingSize = parseFloat(getComputedStyle(root).getPropertyValue("--consenti-font-size-heading") || "16");
|
|
1627
|
-
root.style.setProperty("--consenti-font-size-base", `${Math.round(baseSize * mult)}px`);
|
|
1628
|
-
root.style.setProperty("--consenti-font-size-heading", `${Math.round(headingSize * mult)}px`);
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
async runPlugins() {
|
|
1633
|
-
this.plugins = this.config.plugins ?? [];
|
|
1634
|
-
for (const plugin of this.plugins) {
|
|
1635
|
-
try {
|
|
1636
|
-
await plugin.initialize(this);
|
|
1637
|
-
} catch (err) {
|
|
1638
|
-
console.warn("[Consenti] Plugin initialize error:", err);
|
|
1639
|
-
}
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
/**
|
|
1643
|
-
* Invokes an optional plugin hook on all registered plugins.
|
|
1644
|
-
* Async hooks are awaited; errors are caught and logged so a broken plugin
|
|
1645
|
-
* never interferes with the consent flow.
|
|
1646
|
-
*
|
|
1647
|
-
* @param invoke - Function that calls the desired hook method on a single plugin.
|
|
1648
|
-
*/
|
|
1649
|
-
async callPluginHook(invoke) {
|
|
1650
|
-
for (const plugin of this.plugins) {
|
|
1651
|
-
try {
|
|
1652
|
-
await invoke(plugin, this);
|
|
1653
|
-
} catch (err) {
|
|
1654
|
-
console.warn("[Consenti] Plugin hook failed:", err);
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
buildHandlers(context) {
|
|
1659
|
-
return {
|
|
1660
|
-
onGrantAll: () => {
|
|
1661
|
-
const consent = {};
|
|
1662
|
-
for (const cookie of this.profile?.cookies ?? []) {
|
|
1663
|
-
consent[cookie.id] = "granted";
|
|
1664
|
-
}
|
|
1665
|
-
void this.submitConsent(consent);
|
|
1666
|
-
if (context === "banner") {
|
|
1667
|
-
this.banner?.hide();
|
|
1668
|
-
this._bannerVariant = null;
|
|
1669
|
-
}
|
|
1670
|
-
},
|
|
1671
|
-
onDenyAll: () => {
|
|
1672
|
-
const consent = {};
|
|
1673
|
-
for (const cookie of this.profile?.cookies ?? []) {
|
|
1674
|
-
consent[cookie.id] = cookie.mandatory ? "granted" : "denied";
|
|
1675
|
-
}
|
|
1676
|
-
void this.submitConsent(consent);
|
|
1677
|
-
if (context === "banner") {
|
|
1678
|
-
this.banner?.hide();
|
|
1679
|
-
this._bannerVariant = null;
|
|
1680
|
-
}
|
|
1681
|
-
},
|
|
1682
|
-
onSubmit: () => {
|
|
1683
|
-
if (context === "modal" && this.modal && this.profile) {
|
|
1684
|
-
const consent = this.modal.getToggleConsent(this.profile.preferenceModal.categories);
|
|
1685
|
-
void this.submitConsent(consent);
|
|
1686
|
-
this.hideModal();
|
|
1687
|
-
} else {
|
|
1688
|
-
const consent = {};
|
|
1689
|
-
for (const cookie of this.profile?.cookies ?? []) {
|
|
1690
|
-
if (cookie.mandatory) consent[cookie.id] = "granted";
|
|
1691
|
-
}
|
|
1692
|
-
void this.submitConsent(consent);
|
|
1693
|
-
if (context === "banner") {
|
|
1694
|
-
this.banner?.hide();
|
|
1695
|
-
this._bannerVariant = null;
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
},
|
|
1699
|
-
onManage: () => {
|
|
1700
|
-
this.showModal();
|
|
1701
|
-
},
|
|
1702
|
-
onClose: () => {
|
|
1703
|
-
if (context === "modal") {
|
|
1704
|
-
this.hideModal();
|
|
1705
|
-
} else {
|
|
1706
|
-
this.banner?.hide();
|
|
1707
|
-
this._bannerVariant = null;
|
|
1708
|
-
this.broadcastChannel.send({ type: "bannerClosed" });
|
|
1709
|
-
this.eventBus?.dispatch("consenti:bannerVisibility", { show: false, action: true });
|
|
1710
|
-
void this.callPluginHook((p) => p.onBannerHide?.());
|
|
1711
|
-
}
|
|
1712
|
-
},
|
|
1713
|
-
onGrantSpecific: (cookieIds) => {
|
|
1714
|
-
const consent = {};
|
|
1715
|
-
for (const cookie of this.profile?.cookies ?? []) {
|
|
1716
|
-
if (cookie.mandatory || cookieIds.includes(cookie.id)) {
|
|
1717
|
-
consent[cookie.id] = "granted";
|
|
1718
|
-
} else {
|
|
1719
|
-
consent[cookie.id] = "denied";
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
void this.submitConsent(consent);
|
|
1723
|
-
if (context === "banner") this.hideBanner();
|
|
1724
|
-
}
|
|
1725
|
-
};
|
|
1726
|
-
}
|
|
1727
|
-
/**
|
|
1728
|
-
* Classifies a consent submission as `accept_all`, `reject_all`, `custom`, or `update`.
|
|
1729
|
-
* Used to enrich events and API payloads with intent metadata.
|
|
1730
|
-
*/
|
|
1731
|
-
deriveAction(fullConsent, hadExistingConsent) {
|
|
1732
|
-
if (hadExistingConsent) return "update";
|
|
1733
|
-
const nonMandatory = this.profile?.cookies.filter((c) => !c.mandatory) ?? [];
|
|
1734
|
-
if (nonMandatory.length === 0) return "custom";
|
|
1735
|
-
const allGranted = nonMandatory.every((c) => fullConsent[c.id] === "granted");
|
|
1736
|
-
const allDenied = nonMandatory.every(
|
|
1737
|
-
(c) => fullConsent[c.id] === "denied" || fullConsent[c.id] === "objected"
|
|
1738
|
-
);
|
|
1739
|
-
if (allGranted) return "accept_all";
|
|
1740
|
-
if (allDenied) return "reject_all";
|
|
1741
|
-
return "custom";
|
|
1742
|
-
}
|
|
1743
|
-
handleBroadcastMessage(msg) {
|
|
1744
|
-
switch (msg.type) {
|
|
1745
|
-
case "consentUpdated":
|
|
1746
|
-
if (msg.profileId !== this.profileId()) return;
|
|
1747
|
-
this.consentStore?.setInMemory(msg.consent);
|
|
1748
|
-
this.banner?.hide();
|
|
1749
|
-
if (this.modal?.isOpen()) this.modal.close();
|
|
1750
|
-
this.eventBus?.dispatch("consenti:consentSubmitted", {
|
|
1751
|
-
consent: msg.consent,
|
|
1752
|
-
fromBroadcast: true
|
|
1753
|
-
});
|
|
1754
|
-
break;
|
|
1755
|
-
case "bannerClosed":
|
|
1756
|
-
this.banner?.hide();
|
|
1757
|
-
this._bannerVariant = null;
|
|
1758
|
-
break;
|
|
1759
|
-
case "consentDeleted":
|
|
1760
|
-
this.consentStore?.clearInMemory();
|
|
1761
|
-
break;
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
1765
|
-
/**
|
|
1766
|
-
* Returns `true` if the visitor has saved consent for the active profile.
|
|
1767
|
-
* Always returns `false` during SSR.
|
|
1768
|
-
*/
|
|
1769
|
-
hasConsent() {
|
|
1770
|
-
if (!isClient()) return false;
|
|
1771
|
-
return this.consentStore?.hasConsent() ?? false;
|
|
1772
|
-
}
|
|
1773
|
-
/**
|
|
1774
|
-
* Returns the stored consent map, or `null` if no consent has been saved.
|
|
1775
|
-
* Always returns `null` during SSR.
|
|
1776
|
-
*/
|
|
1777
|
-
getConsent() {
|
|
1778
|
-
if (!isClient()) return null;
|
|
1779
|
-
return this.consentStore?.getConsent() ?? null;
|
|
1780
|
-
}
|
|
1781
|
-
/**
|
|
1782
|
-
* Returns the `Date` when consent was last saved, or `false` if no consent exists.
|
|
1783
|
-
* Always returns `false` during SSR.
|
|
1784
|
-
*/
|
|
1785
|
-
getConsentDate() {
|
|
1786
|
-
if (!isClient()) return false;
|
|
1787
|
-
return this.consentStore?.getConsentDate() ?? false;
|
|
1788
|
-
}
|
|
1789
|
-
/**
|
|
1790
|
-
* Returns the consent map in Google Consent Mode v2 format, ready to pass to
|
|
1791
|
-
* `gtag('consent', 'update', ...)`. Returns `null` if no consent has been saved.
|
|
1792
|
-
*
|
|
1793
|
-
* Maps Consenti cookie IDs to the seven Google Consent Mode v2 parameters.
|
|
1794
|
-
* Cookies whose IDs exactly match a GCM v2 key are forwarded directly.
|
|
1795
|
-
* Non-GCM cookies are ignored by this method (they appear in `getConsent()` only).
|
|
1796
|
-
*/
|
|
1797
|
-
getGTMConsent() {
|
|
1798
|
-
const consent = this.getConsent();
|
|
1799
|
-
if (!consent) return null;
|
|
1800
|
-
const gcmKeys = [
|
|
1801
|
-
"ad_storage",
|
|
1802
|
-
"analytics_storage",
|
|
1803
|
-
"ad_user_data",
|
|
1804
|
-
"ad_personalization",
|
|
1805
|
-
"functionality_storage",
|
|
1806
|
-
"personalization_storage",
|
|
1807
|
-
"security_storage"
|
|
1808
|
-
];
|
|
1809
|
-
const result = {};
|
|
1810
|
-
for (const key of gcmKeys) {
|
|
1811
|
-
const raw = consent[key];
|
|
1812
|
-
if (raw === "granted") {
|
|
1813
|
-
result[key] = "granted";
|
|
1814
|
-
} else if (raw === "denied" || raw === "objected") {
|
|
1815
|
-
result[key] = "denied";
|
|
1816
|
-
} else {
|
|
1817
|
-
const safeDefault = key === "functionality_storage" || key === "security_storage" ? "granted" : "denied";
|
|
1818
|
-
result[key] = safeDefault;
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1821
|
-
return result;
|
|
1822
|
-
}
|
|
1823
|
-
/**
|
|
1824
|
-
* Records and persists the user's consent choices.
|
|
1825
|
-
*
|
|
1826
|
-
* Mandatory cookies are always forced to `'granted'` regardless of what is passed.
|
|
1827
|
-
* Non-mandatory cookies not present in `consent` default to `'denied'`.
|
|
1828
|
-
*
|
|
1829
|
-
* @param consent - Partial or full map of cookie ID → status.
|
|
1830
|
-
* @param gpcDerived - Internal flag set to `true` when called from the GPC strict path.
|
|
1831
|
-
*/
|
|
1832
|
-
async submitConsent(consent, gpcDerived = false) {
|
|
1833
|
-
if (!isClient() || !this.profile || !this.consentStore) return;
|
|
1834
|
-
const regulation = this.config.core.regulation ?? "gdpr";
|
|
1835
|
-
const hadExistingConsent = this.consentStore.hasConsent();
|
|
1836
|
-
const consentId = crypto.randomUUID();
|
|
1837
|
-
const pageUrl = window.location.href;
|
|
1838
|
-
const fullConsent = {};
|
|
1839
|
-
for (const cookie of this.profile.cookies) {
|
|
1840
|
-
if (cookie.mandatory) {
|
|
1841
|
-
fullConsent[cookie.id] = "granted";
|
|
1842
|
-
} else if (regulation === "cpra") {
|
|
1843
|
-
const fallback = cookie.cpraCategory === "sensitive" ? "denied" : "granted";
|
|
1844
|
-
fullConsent[cookie.id] = consent[cookie.id] ?? fallback;
|
|
1845
|
-
} else {
|
|
1846
|
-
fullConsent[cookie.id] = consent[cookie.id] ?? (regulation === "ccpa" ? "granted" : "denied");
|
|
1847
|
-
}
|
|
1848
|
-
}
|
|
1849
|
-
const consentAction = this.deriveAction(fullConsent, hadExistingConsent);
|
|
1850
|
-
this.eventBus?.dispatch("consenti:consentBeingSubmitted", { consent: fullConsent, consentId });
|
|
1851
|
-
let apiResponse;
|
|
1852
|
-
if (this.config.api?.enabled) {
|
|
1853
|
-
try {
|
|
1854
|
-
const base = this.config.api.baseUrl ?? window.location.origin;
|
|
1855
|
-
const { httpRequest: httpRequest2 } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
1856
|
-
apiResponse = await httpRequest2(
|
|
1857
|
-
`${base}/consenti/api/v1/consent`,
|
|
1858
|
-
{
|
|
1859
|
-
method: "POST",
|
|
1860
|
-
body: JSON.stringify({
|
|
1861
|
-
profileId: this.profileId(),
|
|
1862
|
-
consent: fullConsent,
|
|
1863
|
-
locale: this.config.core.locale ?? "en",
|
|
1864
|
-
gpcDetected: gpcDerived || detectGPC(),
|
|
1865
|
-
consentId,
|
|
1866
|
-
action: consentAction,
|
|
1867
|
-
pageUrl
|
|
1868
|
-
})
|
|
1869
|
-
},
|
|
1870
|
-
this.config.api.authToken
|
|
1871
|
-
);
|
|
1872
|
-
} catch (err) {
|
|
1873
|
-
console.warn("[Consenti] API consent submission failed:", err);
|
|
1874
|
-
}
|
|
1875
|
-
}
|
|
1876
|
-
const signingKey = this.profile.cookieSigningKey ?? this.config.core.cookieSigningKey;
|
|
1877
|
-
if (this.config.core.signCookies && signingKey) {
|
|
1878
|
-
this.lastSignature = await this.consentStore.writeAndSign(fullConsent, signingKey);
|
|
1879
|
-
} else {
|
|
1880
|
-
this.consentStore.write(fullConsent);
|
|
1881
|
-
}
|
|
1882
|
-
const receiptRequested = this.modal?.isReceiptRequested() ?? false;
|
|
1883
|
-
if (receiptRequested && this.config.core.allowReceipt) {
|
|
1884
|
-
const nameParts = this.consentStore.cookieName.split("_");
|
|
1885
|
-
const visitorId = nameParts.slice(1, -1).join("_");
|
|
1886
|
-
const receiptParams = {
|
|
1887
|
-
visitorId,
|
|
1888
|
-
profileId: this.profileId(),
|
|
1889
|
-
profileVersion: this.profile.version,
|
|
1890
|
-
locale: this.config.core.locale ?? "en",
|
|
1891
|
-
consent: fullConsent,
|
|
1892
|
-
...this.lastSignature ? { signature: this.lastSignature } : {}
|
|
1893
|
-
};
|
|
1894
|
-
const receipt = generateReceipt(receiptParams);
|
|
1895
|
-
downloadReceipt(receipt);
|
|
1896
|
-
}
|
|
1897
|
-
this.broadcastChannel.send({
|
|
1898
|
-
type: "consentUpdated",
|
|
1899
|
-
consent: fullConsent,
|
|
1900
|
-
profileId: this.profileId()
|
|
1901
|
-
});
|
|
1902
|
-
this.eventBus?.dispatch("consenti:consentSubmitted", {
|
|
1903
|
-
consent: fullConsent,
|
|
1904
|
-
apiResponse,
|
|
1905
|
-
gpcDetected: gpcDerived,
|
|
1906
|
-
consentId,
|
|
1907
|
-
consentAction,
|
|
1908
|
-
pageUrl
|
|
1909
|
-
});
|
|
1910
|
-
await this.callPluginHook((p) => p.onConsentSubmit?.(fullConsent));
|
|
1911
|
-
this.renderer?.announceToScreenReader("Your cookie preferences have been saved.");
|
|
1912
|
-
this.hideBanner();
|
|
1913
|
-
if (this.modal?.isOpen()) this.hideModal();
|
|
1914
|
-
}
|
|
1915
|
-
/**
|
|
1916
|
-
* Returns the currently visible banner variant, or `false` if no banner is shown.
|
|
1917
|
-
* Useful for programmatically checking state before calling `showBanner` / `hideBanner`.
|
|
1918
|
-
*/
|
|
1919
|
-
bannerVisibility() {
|
|
1920
|
-
return this._bannerVariant ?? false;
|
|
1921
|
-
}
|
|
1922
|
-
/**
|
|
1923
|
-
* Returns `'preference'` when the preference modal is open, or `false` when closed.
|
|
1924
|
-
*/
|
|
1925
|
-
modalVisibility() {
|
|
1926
|
-
return this.modal?.isOpen() ? "preference" : false;
|
|
1927
|
-
}
|
|
1928
|
-
/**
|
|
1929
|
-
* Mounts and shows the consent banner.
|
|
1930
|
-
*
|
|
1931
|
-
* No-ops if the requested variant is already visible. If a different variant is
|
|
1932
|
-
* currently shown (e.g. switching from main to GPC), the existing banner is replaced.
|
|
1933
|
-
*
|
|
1934
|
-
* @param useGpcVariant - When `true` and the profile has a `gpcBanner`, that variant
|
|
1935
|
-
* is shown instead of `mainBanner`. Used by the GPC flow.
|
|
1936
|
-
*/
|
|
1937
|
-
showBanner(useGpcVariant = false) {
|
|
1938
|
-
if (!isClient() || !this.profile || !this.banner || !this.renderer) return;
|
|
1939
|
-
const variant = useGpcVariant && this.profile.gpcBanner ? "gpc" : "main";
|
|
1940
|
-
if (this._bannerVariant === variant) return;
|
|
1941
|
-
const bannerConfig = variant === "gpc" ? this.profile.gpcBanner : this.profile.mainBanner;
|
|
1942
|
-
const root = this.renderer.mount(this.config.rootEl);
|
|
1943
|
-
const handlers = this.buildHandlers("banner");
|
|
1944
|
-
this.banner.remove();
|
|
1945
|
-
const locales = this.profile.locales;
|
|
1946
|
-
const activeLocale = this.config.core.locale ?? "en";
|
|
1947
|
-
const bannerEl = this.banner.build(
|
|
1948
|
-
bannerConfig,
|
|
1949
|
-
handlers,
|
|
1950
|
-
this.config.core.privacyPolicyUrl,
|
|
1951
|
-
locales,
|
|
1952
|
-
activeLocale,
|
|
1953
|
-
(locale) => this.switchLocale(locale)
|
|
1954
|
-
);
|
|
1955
|
-
root.appendChild(bannerEl);
|
|
1956
|
-
const overlay = this.banner.getOverlay();
|
|
1957
|
-
if (overlay) root.appendChild(overlay);
|
|
1958
|
-
this._bannerVariant = variant;
|
|
1959
|
-
this.eventBus?.dispatch("consenti:bannerVisibility", { show: true, action: false });
|
|
1960
|
-
void this.callPluginHook((p) => p.onBannerShow?.());
|
|
1961
|
-
}
|
|
1962
|
-
/** Hides the banner and notifies other tabs via BroadcastChannel. No-op if already hidden. */
|
|
1963
|
-
hideBanner() {
|
|
1964
|
-
if (this._bannerVariant === null) return;
|
|
1965
|
-
this.banner?.hide();
|
|
1966
|
-
this._bannerVariant = null;
|
|
1967
|
-
this.broadcastChannel.send({ type: "bannerClosed" });
|
|
1968
|
-
this.eventBus?.dispatch("consenti:bannerVisibility", { show: false, action: true });
|
|
1969
|
-
this.renderer?.announceToScreenReader("Cookie banner dismissed.");
|
|
1970
|
-
void this.callPluginHook((p) => p.onBannerHide?.());
|
|
1971
|
-
}
|
|
1972
|
-
/**
|
|
1973
|
-
* Opens the preference modal and hides the banner while the modal is open.
|
|
1974
|
-
* No-ops if the modal is already open.
|
|
1975
|
-
* If the modal is closed without saving consent, the banner is re-shown automatically
|
|
1976
|
-
* (see `hideModal()`). Only one banner or modal is visible at a time.
|
|
1977
|
-
*
|
|
1978
|
-
* @param triggerEl - The element that triggered the modal open. Focus returns here on close.
|
|
1979
|
-
*/
|
|
1980
|
-
showModal(triggerEl) {
|
|
1981
|
-
if (!isClient() || !this.profile || !this.modal) return;
|
|
1982
|
-
if (this.modal.isOpen()) return;
|
|
1983
|
-
const handlers = this.buildHandlers("modal");
|
|
1984
|
-
const existing = this.consentStore?.getConsent() ?? {};
|
|
1985
|
-
const regulation = this.config.core.regulation ?? "gdpr";
|
|
1986
|
-
const dpdpaCfg = regulation === "dpdpa" ? this.profile.dpdpa : void 0;
|
|
1987
|
-
const locales = this.profile.locales;
|
|
1988
|
-
const activeLocale = this.config.core.locale ?? "en";
|
|
1989
|
-
this.modal.build(
|
|
1990
|
-
this.profile.preferenceModal,
|
|
1991
|
-
existing,
|
|
1992
|
-
handlers,
|
|
1993
|
-
this.config.core.allowReceipt ?? false,
|
|
1994
|
-
dpdpaCfg,
|
|
1995
|
-
locales,
|
|
1996
|
-
activeLocale,
|
|
1997
|
-
(locale) => {
|
|
1998
|
-
this.hideModal();
|
|
1999
|
-
this.switchLocale(locale);
|
|
2000
|
-
}
|
|
2001
|
-
);
|
|
2002
|
-
this.banner?.hide();
|
|
2003
|
-
this.modal.open(triggerEl);
|
|
2004
|
-
const isDark = this.config.darkMode ?? this.profile?.darkMode ?? false;
|
|
2005
|
-
document.getElementById("consenti-modal")?.classList.toggle("consenti-root--dark", isDark);
|
|
2006
|
-
this.eventBus?.dispatch("consenti:modalVisibility", { show: true, action: true });
|
|
2007
|
-
void this.callPluginHook((p) => p.onModalShow?.());
|
|
2008
|
-
}
|
|
2009
|
-
/**
|
|
2010
|
-
* Closes the preference modal and returns focus to the element that opened it.
|
|
2011
|
-
* No-ops if the modal is already closed.
|
|
2012
|
-
* If the user has not yet given consent, the banner is re-shown automatically.
|
|
2013
|
-
*/
|
|
2014
|
-
hideModal() {
|
|
2015
|
-
if (!this.modal?.isOpen()) return;
|
|
2016
|
-
this.modal.close();
|
|
2017
|
-
this.eventBus?.dispatch("consenti:modalVisibility", { show: false, action: true });
|
|
2018
|
-
void this.callPluginHook((p) => p.onModalHide?.());
|
|
2019
|
-
if (!this.consentStore?.hasConsent() && this._bannerVariant !== null) {
|
|
2020
|
-
this.banner?.show();
|
|
2021
|
-
} else if (!this.consentStore?.hasConsent()) {
|
|
2022
|
-
this.showBanner();
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
/**
|
|
2026
|
-
* Registers a callback to run once the widget has finished initialising.
|
|
2027
|
-
* If the widget is already initialised, the callback is invoked synchronously.
|
|
2028
|
-
*
|
|
2029
|
-
* @param callback - Function to call when the widget is ready.
|
|
2030
|
-
*/
|
|
2031
|
-
onReady(callback) {
|
|
2032
|
-
if (this.initialized) {
|
|
2033
|
-
callback();
|
|
2034
|
-
} else {
|
|
2035
|
-
void this.readyPromise.then(callback);
|
|
2036
|
-
}
|
|
2037
|
-
}
|
|
2038
|
-
/**
|
|
2039
|
-
* A `Promise` that resolves once the widget has finished initialising.
|
|
2040
|
-
* Equivalent to wrapping `onReady()` in a `Promise`.
|
|
2041
|
-
*
|
|
2042
|
-
* @example
|
|
2043
|
-
* ```ts
|
|
2044
|
-
* await widget.ready
|
|
2045
|
-
* console.log('Widget ready')
|
|
2046
|
-
* ```
|
|
2047
|
-
*/
|
|
2048
|
-
get ready() {
|
|
2049
|
-
return this.readyPromise;
|
|
2050
|
-
}
|
|
2051
|
-
/**
|
|
2052
|
-
* Deletes the stored consent record and notifies other tabs.
|
|
2053
|
-
* The banner will reappear on the next page load (or immediately if the
|
|
2054
|
-
* receiving tab calls `showBanner()` in response to `consentDeleted`).
|
|
2055
|
-
*/
|
|
2056
|
-
async deleteConsent() {
|
|
2057
|
-
if (!isClient() || !this.consentStore) return;
|
|
2058
|
-
if (this.config.api?.enabled) {
|
|
2059
|
-
try {
|
|
2060
|
-
const base = this.config.api.baseUrl ?? window.location.origin;
|
|
2061
|
-
const visitorId = this.consentStore.cookieName;
|
|
2062
|
-
const { httpRequest: httpRequest2 } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
2063
|
-
await httpRequest2(
|
|
2064
|
-
`${base}/consenti/api/v1/consent/${visitorId}`,
|
|
2065
|
-
{ method: "DELETE" },
|
|
2066
|
-
this.config.api?.authToken
|
|
2067
|
-
);
|
|
2068
|
-
} catch (err) {
|
|
2069
|
-
console.warn("[Consenti] API consent deletion failed:", err);
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
this.consentStore.delete();
|
|
2073
|
-
this.broadcastChannel.send({ type: "consentDeleted" });
|
|
2074
|
-
}
|
|
2075
|
-
/**
|
|
2076
|
-
* Removes existing consent and immediately re-shows the consent banner so the user
|
|
2077
|
-
* can review and update their preferences.
|
|
2078
|
-
*
|
|
2079
|
-
* Equivalent to calling `deleteConsent()` followed by `showBanner()`, but in a single
|
|
2080
|
-
* method so callers do not need to coordinate the async deletion with the banner display.
|
|
2081
|
-
*
|
|
2082
|
-
* Use this to power "Review my consent" links in footers or privacy dashboards.
|
|
2083
|
-
*/
|
|
2084
|
-
async reConsent() {
|
|
2085
|
-
await this.deleteConsent();
|
|
2086
|
-
this.showBanner();
|
|
2087
|
-
}
|
|
2088
|
-
/**
|
|
2089
|
-
* Returns the fully resolved profile for the current session, or `null` during the
|
|
2090
|
-
* async init phase (before the profile has been fetched/resolved).
|
|
2091
|
-
*
|
|
2092
|
-
* Plugins can use this to read cookie definitions, banner config, modal categories,
|
|
2093
|
-
* and the profile version without accessing internal state.
|
|
2094
|
-
*/
|
|
2095
|
-
getProfile() {
|
|
2096
|
-
return this.profile;
|
|
2097
|
-
}
|
|
2098
|
-
/**
|
|
2099
|
-
* Returns the `#consenti-root` container element that wraps all widget DOM,
|
|
2100
|
-
* or `null` before the widget has mounted or after `destroy()`.
|
|
2101
|
-
*
|
|
2102
|
-
* Plugins can use this to append custom elements, apply extra CSS variables,
|
|
2103
|
-
* or observe mutations within the widget container.
|
|
2104
|
-
*/
|
|
2105
|
-
getRootElement() {
|
|
2106
|
-
if (!isClient()) return null;
|
|
2107
|
-
if (this.config.rootEl) {
|
|
2108
|
-
if (typeof this.config.rootEl === "string") {
|
|
2109
|
-
return document.querySelector(this.config.rootEl);
|
|
2110
|
-
}
|
|
2111
|
-
return this.config.rootEl;
|
|
2112
|
-
}
|
|
2113
|
-
return document.getElementById("consenti-root");
|
|
2114
|
-
}
|
|
2115
|
-
/**
|
|
2116
|
-
* Returns the `#consenti-banner` element when it is present in the DOM, or `null`.
|
|
2117
|
-
* The element may be hidden (`display: none`) — check `bannerVisibility()` for visibility state.
|
|
2118
|
-
*
|
|
2119
|
-
* Useful for adding extra content, custom event listeners, or mutation observers on the banner.
|
|
2120
|
-
*/
|
|
2121
|
-
getBannerElement() {
|
|
2122
|
-
if (!isClient()) return null;
|
|
2123
|
-
return document.getElementById("consenti-banner");
|
|
2124
|
-
}
|
|
2125
|
-
/**
|
|
2126
|
-
* Returns the `#consenti-modal` element when the modal has been built, or `null`.
|
|
2127
|
-
* The element is built on first `showModal()` call and reused on subsequent opens.
|
|
2128
|
-
*
|
|
2129
|
-
* Useful for injecting extra content into the modal or listening to modal-specific events.
|
|
2130
|
-
*/
|
|
2131
|
-
getModalElement() {
|
|
2132
|
-
if (!isClient()) return null;
|
|
2133
|
-
return document.getElementById("consenti-modal");
|
|
2134
|
-
}
|
|
2135
|
-
/**
|
|
2136
|
-
* Switches the active locale, re-resolves the profile, and re-renders the widget.
|
|
2137
|
-
* Called by the locale switcher UI when the user selects a different language.
|
|
2138
|
-
*
|
|
2139
|
-
* @param locale - BCP 47 locale code to switch to (e.g. `'fr'`, `'de-AT'`).
|
|
2140
|
-
*/
|
|
2141
|
-
switchLocale(locale) {
|
|
2142
|
-
if (!isClient()) return;
|
|
2143
|
-
this.config.core.locale = locale;
|
|
2144
|
-
this.banner?.remove();
|
|
2145
|
-
if (this.modal?.isOpen()) this.modal.close();
|
|
2146
|
-
this._bannerVariant = null;
|
|
2147
|
-
this.profile = null;
|
|
2148
|
-
this.initialized = false;
|
|
2149
|
-
this.readyPromise = new Promise((resolve) => {
|
|
2150
|
-
this.readyResolve = resolve;
|
|
2151
|
-
});
|
|
2152
|
-
this.init().catch((err) => console.warn("[Consenti] Locale switch error:", err));
|
|
2153
|
-
}
|
|
2154
|
-
/**
|
|
2155
|
-
* Destroys the widget — removes all DOM elements, disconnects the BroadcastChannel,
|
|
2156
|
-
* and calls `destroy()` on all registered plugins.
|
|
2157
|
-
*
|
|
2158
|
-
* After `destroy()`, the instance should not be used again.
|
|
2159
|
-
*/
|
|
2160
|
-
destroy() {
|
|
2161
|
-
for (const plugin of this.plugins) {
|
|
2162
|
-
try {
|
|
2163
|
-
plugin.destroy();
|
|
2164
|
-
} catch {
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
this.modal?.destroy();
|
|
2168
|
-
this.renderer?.unmount();
|
|
2169
|
-
this.broadcastChannel.disconnect();
|
|
2170
|
-
this.banner = null;
|
|
2171
|
-
this.modal = null;
|
|
2172
|
-
this.renderer = null;
|
|
2173
|
-
this.consentStore = null;
|
|
2174
|
-
this.eventBus = null;
|
|
2175
|
-
this.initialized = false;
|
|
2176
|
-
}
|
|
2177
|
-
};
|
|
2178
|
-
|
|
2179
|
-
// src/plugins/plugin.base.ts
|
|
2180
|
-
var ConsentiPlugin = class {
|
|
2181
|
-
};
|
|
2182
|
-
|
|
2183
|
-
// src/profile/consenti-profile.ts
|
|
2184
|
-
var nextLocalId = 1e3;
|
|
2185
|
-
var ConsentiProfile = class {
|
|
2186
|
-
/**
|
|
2187
|
-
* @param config - Full profile configuration including cookies, locales, and UI text.
|
|
2188
|
-
*/
|
|
2189
|
-
constructor(config) {
|
|
2190
|
-
this.config = config;
|
|
2191
|
-
this.id = nextLocalId++;
|
|
2192
|
-
registerProfile(this.id, config);
|
|
2193
|
-
}
|
|
2194
|
-
/** Returns the auto-assigned numeric profile ID. Pass this to `core.profileId`. */
|
|
2195
|
-
getId() {
|
|
2196
|
-
return this.id;
|
|
2197
|
-
}
|
|
2198
|
-
/** Returns the raw `ProfileConfig` passed to the constructor. */
|
|
2199
|
-
toJSON() {
|
|
2200
|
-
return this.config;
|
|
2201
|
-
}
|
|
2202
|
-
};
|
|
2203
|
-
|
|
2204
|
-
// src/utils/consent-script.ts
|
|
2205
|
-
var ConsentScript = class {
|
|
2206
|
-
constructor(options) {
|
|
2207
|
-
this.options = options;
|
|
2208
|
-
this.scriptEl = null;
|
|
2209
|
-
this.handler = () => this.evaluate();
|
|
2210
|
-
if (!isClient()) return;
|
|
2211
|
-
window.addEventListener("consenti:consentSubmitted", this.handler);
|
|
2212
|
-
this.evaluate();
|
|
2213
|
-
}
|
|
2214
|
-
evaluate() {
|
|
2215
|
-
const consent = this.options.widget.getConsent();
|
|
2216
|
-
const granted = consent?.[this.options.cookieId] === "granted";
|
|
2217
|
-
if (granted && !this.scriptEl) {
|
|
2218
|
-
this.inject();
|
|
2219
|
-
} else if (!granted && this.scriptEl) {
|
|
2220
|
-
this.revoke();
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
inject() {
|
|
2224
|
-
const script = document.createElement("script");
|
|
2225
|
-
if (this.options.src) script.src = this.options.src;
|
|
2226
|
-
if (this.options.innerHTML) script.innerHTML = this.options.innerHTML;
|
|
2227
|
-
for (const [key, value] of Object.entries(this.options.attributes ?? {})) {
|
|
2228
|
-
script.setAttribute(key, value);
|
|
2229
|
-
}
|
|
2230
|
-
document.head.appendChild(script);
|
|
2231
|
-
this.scriptEl = script;
|
|
2232
|
-
this.options.onLoad?.();
|
|
2233
|
-
}
|
|
2234
|
-
revoke() {
|
|
2235
|
-
this.scriptEl?.remove();
|
|
2236
|
-
this.scriptEl = null;
|
|
2237
|
-
this.options.onRevoke?.();
|
|
2238
|
-
}
|
|
2239
|
-
/**
|
|
2240
|
-
* Removes the event listener and the injected `<script>` element (if present).
|
|
2241
|
-
* Call this when the widget is destroyed or the script is no longer needed.
|
|
2242
|
-
*/
|
|
2243
|
-
destroy() {
|
|
2244
|
-
if (!isClient()) return;
|
|
2245
|
-
window.removeEventListener("consenti:consentSubmitted", this.handler);
|
|
2246
|
-
this.revoke();
|
|
2247
|
-
}
|
|
2248
|
-
};
|
|
2249
|
-
|
|
2250
|
-
// src/utils/cookie-trigger.ts
|
|
2251
|
-
var CookieTrigger = class {
|
|
2252
|
-
constructor(options) {
|
|
2253
|
-
const action = options.action ?? "modal";
|
|
2254
|
-
this.clickHandler = () => {
|
|
2255
|
-
if (action === "modal") options.widget.showModal();
|
|
2256
|
-
else options.widget.showBanner();
|
|
2257
|
-
};
|
|
2258
|
-
if (!options.el) {
|
|
2259
|
-
const btn = document.createElement("button");
|
|
2260
|
-
btn.type = "button";
|
|
2261
|
-
btn.className = "consenti-btn consenti-btn--text consenti-cookie-trigger";
|
|
2262
|
-
btn.textContent = options.label ?? "Cookie Settings";
|
|
2263
|
-
btn.setAttribute("aria-label", options.label ?? "Open cookie settings");
|
|
2264
|
-
this.el = btn;
|
|
2265
|
-
this.created = true;
|
|
2266
|
-
} else if (typeof options.el === "string") {
|
|
2267
|
-
if (!isClient()) {
|
|
2268
|
-
this.el = document.createElement("span");
|
|
2269
|
-
this.created = false;
|
|
2270
|
-
return;
|
|
2271
|
-
}
|
|
2272
|
-
const found = document.querySelector(options.el);
|
|
2273
|
-
if (!found) {
|
|
2274
|
-
throw new Error(
|
|
2275
|
-
`[Consenti] CookieTrigger: element not found for selector "${options.el}"`
|
|
2276
|
-
);
|
|
2277
|
-
}
|
|
2278
|
-
this.el = found;
|
|
2279
|
-
this.created = false;
|
|
2280
|
-
} else {
|
|
2281
|
-
this.el = options.el;
|
|
2282
|
-
this.created = false;
|
|
2283
|
-
}
|
|
2284
|
-
this.el.addEventListener("click", this.clickHandler);
|
|
2285
|
-
}
|
|
2286
|
-
/**
|
|
2287
|
-
* Returns the trigger element.
|
|
2288
|
-
* When no `el` was provided, append the returned element to the desired location
|
|
2289
|
-
* in the DOM after construction.
|
|
2290
|
-
*/
|
|
2291
|
-
getElement() {
|
|
2292
|
-
return this.el;
|
|
2293
|
-
}
|
|
2294
|
-
/**
|
|
2295
|
-
* Removes the click handler and, if this instance auto-created the button,
|
|
2296
|
-
* removes it from the DOM.
|
|
2297
|
-
*/
|
|
2298
|
-
destroy() {
|
|
2299
|
-
this.el.removeEventListener("click", this.clickHandler);
|
|
2300
|
-
if (this.created) this.el.remove();
|
|
2301
|
-
}
|
|
2302
|
-
};
|
|
2303
|
-
return __toCommonJS(src_exports);
|
|
2304
|
-
})();
|
|
1
|
+
"use strict";var Consenti=(()=>{var Ee=Object.defineProperty;var Xn=Object.getOwnPropertyDescriptor;var eo=Object.getOwnPropertyNames;var to=Object.prototype.hasOwnProperty;var f=(n,e)=>()=>(n&&(e=n(n=0)),e);var Z=(n,e)=>{for(var t in e)Ee(n,t,{get:e[t],enumerable:!0})},no=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of eo(e))!to.call(n,i)&&i!==t&&Ee(n,i,{get:()=>e[i],enumerable:!(o=Xn(e,i))||o.enumerable});return n};var oo=n=>no(Ee({},"__esModule",{value:!0}),n);var X,Se=f(()=>{"use strict";X={complianceGroup:"opt-in",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!0},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"}},translations:{en:{mainBanner:{position:"bottom",heading:"We value your privacy",htmlText:"We use cookies and similar technologies to enhance your browsing experience, analyse site traffic, and show you personalised content. Non-essential cookies require your consent under the GDPR and ePrivacy Directive.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"submit",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"Global Privacy Control detected",htmlText:"Your browser is sending a Global Privacy Control signal. We have applied your preference and will not set non-essential cookies unless you change your settings below.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"confirm-settings":{text:"Confirm Settings",style:"secondary",action:"submit",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Preferences",subheading:"Manage your consent settings for each category below.",htmlText:"You can choose which cookie categories you allow. Your choices apply to this site only. Essential cookies cannot be disabled as they are required for the site to function correctly.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"submit",cookies:"!"},"save-preferences":{text:"Save My Preferences",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"These cookies are required for the website to function and cannot be disabled. They are usually set in response to actions you take, such as setting your privacy preferences, logging in, or filling in forms.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"These cookies enable enhanced functionality and personalisation. They may be set by us or by third-party providers whose services we have added to our pages. If you do not allow these cookies, some or all of these features may not function properly.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"These cookies allow us to count visits and traffic sources so we can measure and improve site performance. They help us understand which pages are most and least popular. All information collected is aggregated and therefore anonymous.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing",htmlText:"These cookies may be set through our site by advertising partners to build a profile of your interests and show you relevant adverts on other sites. They do not store personal information directly but identify your browser and device uniquely.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var ee,Ie=f(()=>{"use strict";ee={complianceGroup:"opt-out",gpcMode:"honor",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!0},personalization_storage:{purpose:"preferences",listenGpc:!0},analytics_storage:{purpose:"analytics",listenGpc:!0},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"}},translations:{en:{mainBanner:{position:"bottom",heading:"We use cookies",htmlText:"We and our partners use cookies and similar tracking technologies to improve your experience, analyse site usage, and show relevant advertising. You may opt out of the sale or sharing of your personal data at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"do-not-sell-share":{text:"Do Not Sell or Share My Personal Information",style:"secondary",action:"submit",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"Your opt-out has been applied",htmlText:"Your browser sent a Global Privacy Control signal. We have automatically opted you out of the sale and sharing of your personal data as required by applicable US state privacy laws.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"confirm-opt-out":{text:"Confirm Opt-Out",style:"secondary",action:"submit",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Cookie Preferences",subheading:"Manage your data preferences. You may opt out of non-essential uses at any time.",htmlText:"Under applicable US state privacy laws, you have the right to opt out of the sale and sharing of your personal data. Toggle the categories below to exercise your rights.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"opt-out-all":{text:"Opt Out of All",style:"secondary",action:"submit",cookies:"!"},"save-choices":{text:"Save My Choices",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"These cookies are required for the website to operate and cannot be disabled. They do not involve the sale or sharing of personal data.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"These cookies improve the functionality of the site. Disabling them may affect how the site operates. You may opt out at any time.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Analytics cookies help us understand how visitors interact with the site. Opting out prevents your data from being included in usage statistics.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Sale / Sharing of Personal Data",htmlText:"These cookies involve the sale or sharing of your personal data with advertising partners for targeted advertising. You have the right to opt out of this under applicable US state privacy laws.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var te,Me=f(()=>{"use strict";te={complianceGroup:"opt-out-strict",gpcMode:"honor",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!0},personalization_storage:{purpose:"preferences",listenGpc:!0},analytics_storage:{purpose:"analytics",listenGpc:!0,cpraCategory:"sharing"},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"},sensitive_info_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sensitive"}},translations:{en:{mainBanner:{position:"bottom",heading:"Your California Privacy Rights",htmlText:"Under the California Privacy Rights Act (CPRA), you have the right to opt out of the sale, sharing, and use of sensitive personal information. We use cookies and tracking technologies that may involve the sale or sharing of your data with third parties.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"opt-out-sale-sharing-sensitive":{text:"Opt Out of Sale, Sharing & Sensitive Use",style:"secondary",action:"submit",cookies:"!"},manage:{text:"Manage",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"GPC opt-out applied automatically",htmlText:"Your browser sent a Global Privacy Control signal. Under the CPRA, we are required to honor this as a Do Not Sell or Share My Personal Information request. Your opt-out has been applied automatically.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"confirm-opt-out":{text:"Confirm Opt-Out",style:"secondary",action:"submit",cookies:"!"},"review-choices":{text:"Review Choices",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Rights Center",subheading:"Manage your CPRA rights: opt out of sale, sharing, and limit the use of sensitive personal information.",htmlText:"As a California resident, you have the right under CPRA to opt out of the sale and sharing of your personal information, including for cross-context behavioral advertising, and to limit the use of your sensitive personal information. Toggle each category below to exercise your rights.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"opt-out-sale-sharing-sensitive":{text:"Opt Out of Sale, Sharing & Sensitive Use",style:"secondary",action:"submit",cookies:"!"},"save-choices":{text:"Save My Choices",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Essential to deliver the service. These cookies are not sold or shared and cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional & Personalisation",htmlText:"Improve site functionality and remember your preferences. May involve sharing of browsing data.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics (Sharing)",htmlText:'Measure site performance. Analytics data may be shared with third-party providers, which constitutes "sharing" under CPRA.',legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Sale & Sharing of Personal Data",htmlText:"Advertising and retargeting cookies that involve the sale or sharing of your personal data with third-party advertisers for cross-context behavioural advertising.",legalBasis:"consent",cookies:["ad_storage"]},sensitive:{heading:"Sensitive Personal Information",htmlText:"Some technologies may use sensitive personal information as defined by CPRA (e.g. precise geolocation, health data). You have the right to limit such use.",legalBasis:"consent",cookies:["sensitive_info_storage"]}}}}}}});var ne,De=f(()=>{"use strict";ne={complianceGroup:"opt-in-dpdpa",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"Data Protection Notice",htmlText:"We are the Data Fiduciary under India's Digital Personal Data Protection Act (DPDPA). Your explicit consent is required before we process your personal data using non-essential cookies. You may withdraw consent at any time without affecting prior processing.",buttons:{"consent-all":{text:"I Consent",style:"primary",action:"submit",cookies:"*"},"deny-all":{text:"I Do Not Consent",style:"secondary",action:"submit",cookies:"!"},"review-choices":{text:"Review Choices",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Consent Preferences",subheading:"Review the purposes for which we process your personal data and provide or withdraw consent for each.",htmlText:"Under the Digital Personal Data Protection Act (DPDPA) 2023, you have the right to give, manage, and withdraw consent for personal data processing. Legitimate interest is not a valid legal basis under the DPDPA \u2014 all data processing requires your explicit consent.",buttons:{"consent-all":{text:"Give Consent to All",style:"primary",action:"submit",cookies:"*"},"withdraw-all":{text:"Withdraw All Consent",style:"secondary",action:"submit",cookies:"!"},"save-choices":{text:"Save Choices",style:"secondary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required to deliver the core service. No personal data is shared and consent is not required for these.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Enable enhanced features and personalisation. Your explicit consent is required under the DPDPA before we process data for these purposes.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand how you interact with the site. Your consent is required before any analytics data is collected.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing & Advertising",htmlText:"Allow personalised advertising based on your browsing activity. Requires your explicit consent under the DPDPA.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var oe,Le=f(()=>{"use strict";oe={complianceGroup:"opt-in-china",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"Personal Information Processing Notice",htmlText:"In accordance with China's Personal Information Protection Law (PIPL), Data Security Law (DSL), and Cybersecurity Law (CSL), we process personal information only for specified, explicit, and legitimate purposes with minimum data collection. Your consent is required for non-essential cookies.",buttons:{"agree-all":{text:"Agree to All",style:"primary",action:"submit",cookies:"*"},"reject-non-necessary":{text:"Reject Non-Necessary",style:"secondary",action:"submit",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Personal Information Processing Settings",subheading:"Review the purpose and scope of each category of personal information processing.",htmlText:"Under the PIPL, you have the right to know, decide, and restrict the processing of your personal information. Processing is limited to the stated purposes. Cross-border transfers of your data, if any, are handled in accordance with Chapter III of the PIPL, including security assessments or standard contracts where applicable.",buttons:{"agree-all":{text:"Agree to All",style:"primary",action:"submit",cookies:"*"},"disagree-all":{text:"Disagree to All",style:"secondary",action:"submit",cookies:"!"},"confirm-settings":{text:"Confirm Settings",style:"primary",action:"submit"}},categories:{necessary:{heading:"Necessary for Service",htmlText:"Required to deliver the core service and ensure network security under the CSL. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functionality & Personalisation",htmlText:"Enable enhanced features. Personal information is processed only for the stated purposes and retained for no longer than necessary.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Statistical Analysis",htmlText:"Collect and analyse usage data to improve the service. Data is processed within China unless cross-border transfer requirements are satisfied.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Targeted Advertising",htmlText:"Personalise advertisements based on your interactions. Requires explicit consent under PIPL. You may withdraw consent and object to personalised advertising at any time.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var ie,ze=f(()=>{"use strict";ie={complianceGroup:"opt-in-brazil",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"We value your privacy",htmlText:"In accordance with Brazil's Lei Geral de Prote\xE7\xE3o de Dados (LGPD), we process personal data only with a valid legal basis. Non-essential cookies require your prior consent. You may withdraw consent at any time. Legitimate interest applies where noted.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"submit",cookies:"!"},manage:{text:"Manage",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Preferences",subheading:"Review and manage your data processing preferences under the LGPD.",htmlText:"You have rights under the LGPD including: access, correction, deletion, portability, and withdrawal of consent. Categories based on legitimate interest are indicated below \u2014 you may object to these at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"submit",cookies:"!"},"save-preferences":{text:"Save My Preferences",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Essential for the service to function. Legal basis: fulfillment of a contract or legal obligation. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Enhance site functionality and remember your settings. Legal basis: legitimate interest (LGPD Art. 7, X). You may object to this processing at any time.",legalBasis:"legitimate_interest",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand how visitors use the site so we can improve it. Legal basis: your consent.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing & Advertising",htmlText:"Personalise ads and measure campaign effectiveness. Legal basis: your consent. You may withdraw consent at any time without affecting the lawfulness of prior processing.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var ae,Re=f(()=>{"use strict";ae={complianceGroup:"general-privacy-consent",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"We use cookies",htmlText:"We use cookies to improve your browsing experience, analyse site traffic, and show you relevant content. By continuing to use this site, you accept our use of cookies. You can manage your preferences at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"reject-marketing":{text:"Reject Marketing",style:"secondary",action:"submit",cookies:["security_storage","functionality_storage","personalization_storage","analytics_storage"]},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Cookie Settings",subheading:"We document the legal basis for each category of cookie we use.",htmlText:"A privacy notice or consent framework applies in your jurisdiction. While a strict cookie consent banner may not be legally required, we document our legal basis for processing to follow privacy best practices.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"submit",cookies:"*"},"necessary-only":{text:"Necessary Only",style:"secondary",action:"submit",cookies:"!"},"save-preferences":{text:"Save My Settings",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required to deliver the service. No optional data processing takes place. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Improve how the site works and remember your preferences. Legal basis: legitimate interest.",legalBasis:"legitimate_interest",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand usage patterns to improve the site. Legal basis: legitimate interest. Data is aggregated and anonymised where possible.",legalBasis:"legitimate_interest",cookies:["analytics_storage"]},marketing:{heading:"Marketing",htmlText:"Personalise advertising and measure campaign reach. Legal basis: your consent. You may withdraw consent at any time.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var re,Be=f(()=>{"use strict";re={complianceGroup:"notice-only",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"This site uses essential cookies only",htmlText:"We use strictly necessary cookies to ensure this website functions correctly. No tracking, advertising, or analytics cookies are used. No specific cookie consent law applies in your jurisdiction.",buttons:{ok:{text:"OK",style:"primary",action:"close"}}},preferenceModal:{position:"right",heading:"Cookie Information",subheading:"We only use cookies that are strictly necessary for this site to work.",htmlText:"This site does not use optional cookies. The only cookie set is required to maintain basic security and session integrity. You cannot disable it without affecting site functionality.",buttons:{close:{text:"Close",style:"primary",action:"close"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required for the site to function. These cookies do not track you and cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]}}}}}}});var it,at=f(()=>{"use strict";it={mainBanner:{heading:"Wir sch\xE4tzen Ihre Privatsph\xE4re",htmlText:"Wir verwenden Cookies, um Ihre Browser-Erfahrung zu verbessern, personalisierte Inhalte oder Anzeigen bereitzustellen und unseren Datenverkehr zu analysieren. Mit dem Klicken auf <strong>Alle akzeptieren</strong> stimmen Sie der Verwendung von Cookies zu. Sie k\xF6nnen Ihre Einstellungen jederzeit \xE4ndern.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","manage-preferences":"Einstellungen verwalten"}},gpcBanner:{heading:"Datenschutzpr\xE4ferenz erkannt",htmlText:"Ihr Browser hat ein Global Privacy Control (GPC) Signal gesendet. Wir haben Ihre Datenschutzpr\xE4ferenz ber\xFCcksichtigt.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-settings":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie aus, welche Cookies Sie erlauben.",htmlText:"Wir verwenden verschiedene Cookie-Typen. Sie k\xF6nnen die einzelnen Kategorien aktivieren oder deaktivieren. Notwendige Cookies k\xF6nnen nicht deaktiviert werden.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"Diese Cookies sind f\xFCr das Funktionieren der Website unbedingt erforderlich und k\xF6nnen nicht deaktiviert werden."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen wie gespeicherte Pr\xE4ferenzen und Personalisierung."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen und Pr\xE4ferenzen f\xFCr zuk\xFCnftige Besuche."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns zu verstehen, wie Besucher mit unserer Website interagieren."},"cat-marketing":{heading:"Marketing",htmlText:"Werden verwendet, um Ihnen relevante Werbung anzuzeigen."}}}}});var rt,st=f(()=>{"use strict";rt={mainBanner:{heading:"Valoramos su privacidad",htmlText:"Utilizamos cookies para mejorar su experiencia de navegaci\xF3n, mostrar anuncios o contenido personalizados y analizar nuestro tr\xE1fico. Al hacer clic en <strong>Aceptar todo</strong>, consiente el uso de cookies. Puede cambiar sus preferencias en cualquier momento.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","manage-preferences":"Gestionar preferencias"}},gpcBanner:{heading:"Preferencia de privacidad reconocida",htmlText:"Su navegador ha enviado una se\xF1al Global Privacy Control (GPC). Hemos aplicado su preferencia de privacidad.",buttons:{"accept-all":"Revisar preferencias","confirm-settings":"Continuar"}},preferenceModal:{heading:"Preferencias de privacidad",subheading:"Elija qu\xE9 cookies desea permitir.",htmlText:"Utilizamos distintos tipos de cookies. Puede activar o desactivar cada categor\xEDa. Las cookies necesarias no pueden desactivarse.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Estas cookies son imprescindibles para el funcionamiento del sitio web y no pueden desactivarse."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas como preferencias guardadas y personalizaci\xF3n."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal y preferencias para visitas futuras."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender c\xF3mo los visitantes interact\xFAan con nuestro sitio web."},"cat-marketing":{heading:"Marketing",htmlText:"Se utilizan para mostrarle publicidad relevante."}}}}});var ct,lt=f(()=>{"use strict";ct={mainBanner:{heading:"Nous respectons votre vie priv\xE9e",htmlText:"Nous utilisons des cookies pour am\xE9liorer votre exp\xE9rience de navigation, afficher des publicit\xE9s ou du contenu personnalis\xE9s et analyser notre trafic. En cliquant sur <strong>Tout accepter</strong>, vous consentez \xE0 l'utilisation des cookies. Vous pouvez modifier vos pr\xE9f\xE9rences \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"Pr\xE9f\xE9rence de confidentialit\xE9 reconnue",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control (GPC). Nous avons appliqu\xE9 votre pr\xE9f\xE9rence de confidentialit\xE9.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-settings":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez les cookies que vous souhaitez autoriser.",htmlText:"Nous utilisons diff\xE9rents types de cookies. Vous pouvez activer ou d\xE9sactiver chaque cat\xE9gorie. Les cookies n\xE9cessaires ne peuvent pas \xEAtre d\xE9sactiv\xE9s.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Ces cookies sont indispensables au fonctionnement du site web et ne peuvent pas \xEAtre d\xE9sactiv\xE9s."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es comme les pr\xE9f\xE9rences enregistr\xE9es et la personnalisation."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels et pr\xE9f\xE9rences pour les visites futures."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre comment les visiteurs interagissent avec notre site web."},"cat-marketing":{heading:"Marketing",htmlText:"Sont utilis\xE9s pour vous afficher des publicit\xE9s pertinentes."}}}}});var pt,dt=f(()=>{"use strict";pt={mainBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u3092\u5927\u5207\u306B\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30D6\u30E9\u30A6\u30B8\u30F3\u30B0\u4F53\u9A13\u306E\u5411\u4E0A\u3001\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u30FB\u30B3\u30F3\u30C6\u30F3\u30C4\u306E\u8868\u793A\u3001\u30C8\u30E9\u30D5\u30A3\u30C3\u30AF\u5206\u6790\u306E\u305F\u3081\u306BCookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002<strong>\u3059\u3079\u3066\u540C\u610F</strong>\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3053\u3068\u3067\u3001Cookie\u306E\u4F7F\u7528\u306B\u540C\u610F\u3057\u305F\u3053\u3068\u306B\u306A\u308A\u307E\u3059\u3002\u8A2D\u5B9A\u306F\u3044\u3064\u3067\u3082\u5909\u66F4\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\uFF08GPC\uFF09\u30B7\u30B0\u30CA\u30EB\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u304A\u5BA2\u69D8\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u3092\u9069\u7528\u3057\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-settings":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"\u8A31\u53EF\u3059\u308BCookie\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",htmlText:"\u3055\u307E\u3056\u307E\u306A\u7A2E\u985E\u306ECookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u5404\u30AB\u30C6\u30B4\u30EA\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u5FC5\u9808Cookie\u306F\u7121\u52B9\u306B\u3067\u304D\u307E\u305B\u3093\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u3053\u308C\u3089\u306ECookie\u306F\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u6A5F\u80FD\u306B\u4E0D\u53EF\u6B20\u3067\u3042\u308A\u3001\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u4FDD\u5B58\u3055\u308C\u305F\u8A2D\u5B9A\u3084\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\u306A\u3069\u306E\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u5C06\u6765\u306E\u8A2A\u554F\u306E\u305F\u3081\u306B\u500B\u4EBA\u8A2D\u5B9A\u3084\u597D\u307F\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u8A2A\u554F\u8005\u304C\u3069\u306E\u3088\u3046\u306B\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u3092\u5229\u7528\u3057\u3066\u3044\u308B\u304B\u3092\u7406\u89E3\u3059\u308B\u306E\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u95A2\u9023\u3059\u308B\u5E83\u544A\u3092\u8868\u793A\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002"}}}}});var ut,mt=f(()=>{"use strict";ut={mainBanner:{heading:"Wir verwenden Cookies",htmlText:"Wir verwenden Cookies, um unsere Dienste zu verbessern. Sie k\xF6nnen dem Verkauf oder der Weitergabe Ihrer pers\xF6nlichen Daten jederzeit widersprechen.",buttons:{"accept-all":"Alle akzeptieren","do-not-sell-share":"Nicht verkaufen oder weitergeben","manage-preferences":"Einstellungen verwalten"}},gpcBanner:{heading:"GPC erkannt \u2013 Opt-out angewendet",htmlText:"Ihr Browser hat ein Global Privacy Control Signal gesendet. Wir haben Sie vom Verkauf und der Weitergabe Ihrer Daten abgemeldet.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-opt-out":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie Ihre Datenschutzoptionen.",buttons:{"accept-all":"Alle akzeptieren","opt-out-all":"Nicht verkaufen oder weitergeben","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"Diese Cookies sind f\xFCr das Funktionieren der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen und Personalisierung."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre Einstellungen f\xFCr zuk\xFCnftige Besuche."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns zu verstehen, wie Besucher unsere Website nutzen."},"cat-marketing":{heading:"Werbung / Verkauf",htmlText:"Erm\xF6glichen gezielte Werbung. Sie k\xF6nnen dem Verkauf Ihrer Daten widersprechen."}}}}});var gt,ft=f(()=>{"use strict";gt={mainBanner:{heading:"Utilizamos cookies",htmlText:"Utilizamos cookies para mejorar nuestros servicios. Puede oponerse a la venta o al intercambio de sus datos personales en cualquier momento.",buttons:{"accept-all":"Aceptar todo","do-not-sell-share":"No vender ni compartir","manage-preferences":"Gestionar preferencias"}},gpcBanner:{heading:"GPC detectado \u2013 exclusi\xF3n aplicada",htmlText:"Su navegador ha enviado una se\xF1al Global Privacy Control. Le hemos excluido de la venta y el intercambio de sus datos.",buttons:{"accept-all":"Revisar preferencias","confirm-opt-out":"Continuar"}},preferenceModal:{heading:"Preferencias de privacidad",subheading:"Elija sus opciones de privacidad.",buttons:{"accept-all":"Aceptar todo","opt-out-all":"No vender ni compartir","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio web."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas y personalizaci\xF3n."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n para visitas futuras."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender c\xF3mo los visitantes utilizan nuestro sitio."},"cat-marketing":{heading:"Publicidad / Venta",htmlText:"Permiten publicidad dirigida. Puede oponerse a la venta de sus datos."}}}}});var ht,yt=f(()=>{"use strict";ht={mainBanner:{heading:"Nous utilisons des cookies",htmlText:"Nous utilisons des cookies pour am\xE9liorer nos services. Vous pouvez vous opposer \xE0 la vente ou au partage de vos donn\xE9es personnelles \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","do-not-sell-share":"Ne pas vendre ni partager","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"GPC d\xE9tect\xE9 \u2013 exclusion appliqu\xE9e",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control. Nous avons appliqu\xE9 votre demande de ne pas vendre ni partager vos donn\xE9es.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-opt-out":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez vos options de confidentialit\xE9.",buttons:{"accept-all":"Tout accepter","opt-out-all":"Ne pas vendre ni partager","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site web."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es et la personnalisation."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres pour les visites futures."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre comment les visiteurs utilisent notre site."},"cat-marketing":{heading:"Publicit\xE9 / Vente",htmlText:"Permettent la publicit\xE9 cibl\xE9e. Vous pouvez vous opposer \xE0 la vente de vos donn\xE9es."}}}}});var vt,bt=f(()=>{"use strict";vt={mainBanner:{heading:"Cookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30FC\u30D3\u30B9\u5411\u4E0A\u306E\u305F\u3081\u306BCookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u3084\u5171\u6709\u306B\u306F\u3044\u3064\u3067\u3082\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","do-not-sell-share":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"GPC\u691C\u51FA \u2013 \u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u9069\u7528\u6E08\u307F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u30B7\u30B0\u30CA\u30EB\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u304A\u3088\u3073\u5171\u6709\u304B\u3089\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-opt-out":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-all":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u6A5F\u80FD\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3068\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u5C06\u6765\u306E\u8A2A\u554F\u306E\u305F\u3081\u306B\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u8A2A\u554F\u8005\u306E\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u3092\u628A\u63E1\u3059\u308B\u306E\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002"},"cat-marketing":{heading:"\u5E83\u544A\u30FB\u8CA9\u58F2",htmlText:"\u30BF\u30FC\u30B2\u30C3\u30C8\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u306B\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002"}}}}});var Ct,kt=f(()=>{"use strict";Ct={mainBanner:{heading:"Datenschutzrechte in Kalifornien",htmlText:"Gem\xE4\xDF dem California Privacy Rights Act (CPRA) haben Sie das Recht, dem Verkauf, der Weitergabe und der Verwendung Ihrer pers\xF6nlichen Daten zu widersprechen.",buttons:{"accept-all":"Alle akzeptieren","opt-out-sale-sharing-sensitive":"Meine Daten nicht verkaufen oder teilen",manage:"Einstellungen verwalten"}},gpcBanner:{heading:"GPC erkannt \u2013 CPRA-Opt-out angewendet",htmlText:"Ihr Global Privacy Control Signal wurde erkannt. Ihr Recht auf Opt-out gem\xE4\xDF CPRA wurde automatisch angewendet.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-opt-out":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen (CPRA)",subheading:"Verwalten Sie Ihre Datenschutzrechte.",buttons:{"accept-all":"Alle akzeptieren","opt-out-sale-sharing-sensitive":"Meine Daten nicht verkaufen oder teilen","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen."},"cat-marketing":{heading:"Verkauf / Weitergabe (CPRA)",htmlText:"Verkauf und Weitergabe pers\xF6nlicher Daten gem\xE4\xDF CPRA. Sie k\xF6nnen widersprechen."}}}}});var Pt,_t=f(()=>{"use strict";Pt={mainBanner:{heading:"Derechos de privacidad en California",htmlText:"De acuerdo con la Ley de Derechos de Privacidad de California (CPRA), tiene derecho a oponerse a la venta, el intercambio y el uso de sus datos personales.",buttons:{"accept-all":"Aceptar todo","opt-out-sale-sharing-sensitive":"No vender ni compartir mis datos",manage:"Gestionar preferencias"}},gpcBanner:{heading:"GPC detectado \u2013 exclusi\xF3n CPRA aplicada",htmlText:"Se ha detectado su se\xF1al Global Privacy Control. Su derecho de exclusi\xF3n seg\xFAn la CPRA se ha aplicado autom\xE1ticamente.",buttons:{"accept-all":"Revisar preferencias","confirm-opt-out":"Continuar"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (CPRA)",subheading:"Administre sus derechos de privacidad.",buttons:{"accept-all":"Aceptar todo","opt-out-sale-sharing-sensitive":"No vender ni compartir mis datos","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio."},"cat-marketing":{heading:"Venta / Intercambio (CPRA)",htmlText:"Venta e intercambio de datos personales seg\xFAn la CPRA. Puede oponerse."}}}}});var xt,wt=f(()=>{"use strict";xt={mainBanner:{heading:"Droits \xE0 la vie priv\xE9e en Californie",htmlText:"Conform\xE9ment au California Privacy Rights Act (CPRA), vous avez le droit de vous opposer \xE0 la vente, au partage et \xE0 l'utilisation de vos donn\xE9es personnelles.",buttons:{"accept-all":"Tout accepter","opt-out-sale-sharing-sensitive":"Ne pas vendre ni partager mes donn\xE9es",manage:"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"GPC d\xE9tect\xE9 \u2013 exclusion CPRA appliqu\xE9e",htmlText:"Votre signal Global Privacy Control a \xE9t\xE9 d\xE9tect\xE9. Votre droit d'exclusion selon la CPRA a \xE9t\xE9 appliqu\xE9 automatiquement.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-opt-out":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (CPRA)",subheading:"G\xE9rez vos droits \xE0 la vie priv\xE9e.",buttons:{"accept-all":"Tout accepter","opt-out-sale-sharing-sensitive":"Ne pas vendre ni partager mes donn\xE9es","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site."},"cat-marketing":{heading:"Vente / Partage (CPRA)",htmlText:"Vente et partage de donn\xE9es personnelles selon la CPRA. Vous pouvez vous y opposer."}}}}});var At,Tt=f(()=>{"use strict";At={mainBanner:{heading:"\u30AB\u30EA\u30D5\u30A9\u30EB\u30CB\u30A2\u5DDE\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29",htmlText:"\u30AB\u30EA\u30D5\u30A9\u30EB\u30CB\u30A2\u30FB\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29\u6CD5\uFF08CPRA\uFF09\u306B\u57FA\u3065\u304D\u3001\u304A\u5BA2\u69D8\u306B\u306F\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u30FB\u5171\u6709\u30FB\u5229\u7528\u306B\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u6A29\u5229\u304C\u3042\u308A\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-sale-sharing-sensitive":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044",manage:"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"GPC\u691C\u51FA \u2013 CPRA\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u9069\u7528\u6E08\u307F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u30B7\u30B0\u30CA\u30EB\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002CPRA\u306B\u57FA\u3065\u304F\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u6A29\u304C\u81EA\u52D5\u7684\u306B\u9069\u7528\u3055\u308C\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-opt-out":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08CPRA\uFF09",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29\u3092\u7BA1\u7406\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-sale-sharing-sensitive":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002"},"cat-marketing":{heading:"\u8CA9\u58F2\u30FB\u5171\u6709\uFF08CPRA\uFF09",htmlText:"CPRA\u306B\u57FA\u3065\u304F\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u304A\u3088\u3073\u5171\u6709\u3002\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002"}}}}});var Et,Gt=f(()=>{"use strict";Et={mainBanner:{heading:"Datenschutzhinweis",htmlText:"Wir sind der f\xFCr die Datenverarbeitung Verantwortliche gem\xE4\xDF dem Digitalen Personaldatenschutzgesetz (DPDPA) Indiens. Ihre Einwilligung ist erforderlich, bevor wir Ihre personenbezogenen Daten verarbeiten.",buttons:{"consent-all":"Ich stimme zu","deny-all":"Ich stimme nicht zu","review-choices":"Auswahl \xFCberpr\xFCfen"}},preferenceModal:{heading:"Datenschutzeinstellungen (DPDPA)",subheading:"Bitte w\xE4hlen Sie aus, in welche Verarbeitungen Sie einwilligen.",buttons:{"consent-all":"Ich stimme zu","withdraw-all":"Ich stimme nicht zu","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich. Keine Einwilligung erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Ihre Einwilligung ist gem\xE4\xDF DPDPA erforderlich."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen. Einwilligung gem\xE4\xDF DPDPA erforderlich."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Einwilligung gem\xE4\xDF DPDPA erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Einwilligung gem\xE4\xDF DPDPA erforderlich."}}}}});var St,It=f(()=>{"use strict";St={mainBanner:{heading:"Aviso de protecci\xF3n de datos",htmlText:"Somos el Fiduciario de Datos seg\xFAn la Ley de Protecci\xF3n de Datos Digitales Personales (DPDPA) de India. Su consentimiento es necesario antes de que procesemos sus datos personales.",buttons:{"consent-all":"Doy mi consentimiento","deny-all":"No doy mi consentimiento","review-choices":"Revisar opciones"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (DPDPA)",subheading:"Elija en qu\xE9 procesamientos desea dar su consentimiento.",buttons:{"consent-all":"Doy mi consentimiento","withdraw-all":"No doy mi consentimiento","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio. No requieren consentimiento."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Su consentimiento es requerido seg\xFAn la DPDPA."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal. Se requiere consentimiento seg\xFAn la DPDPA."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio. Se requiere consentimiento seg\xFAn la DPDPA."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere consentimiento seg\xFAn la DPDPA."}}}}});var Mt,Dt=f(()=>{"use strict";Mt={mainBanner:{heading:"Avis de protection des donn\xE9es",htmlText:"Nous sommes le Fiduciaire de donn\xE9es au sens de la loi indienne sur la protection des donn\xE9es personnelles num\xE9riques (DPDPA). Votre consentement est requis avant que nous traitions vos donn\xE9es personnelles.",buttons:{"consent-all":"Je consens","deny-all":"Je ne consens pas","review-choices":"Examiner les choix"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (DPDPA)",subheading:"Choisissez les traitements auxquels vous consentez.",buttons:{"consent-all":"Je consens","withdraw-all":"Je ne consens pas","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site. Aucun consentement requis."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Votre consentement est requis selon la DPDPA."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels. Consentement requis selon la DPDPA."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Consentement requis selon la DPDPA."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Consentement requis selon la DPDPA."}}}}});var Lt,zt=f(()=>{"use strict";Lt={mainBanner:{heading:"\u30C7\u30FC\u30BF\u4FDD\u8B77\u306B\u95A2\u3059\u308B\u304A\u77E5\u3089\u305B",htmlText:"\u5F53\u793E\u306F\u30A4\u30F3\u30C9\u306E\u30C7\u30B8\u30BF\u30EB\u500B\u4EBA\u30C7\u30FC\u30BF\u4FDD\u8B77\u6CD5\uFF08DPDPA\uFF09\u306B\u57FA\u3065\u304F\u30C7\u30FC\u30BF\u53D7\u8A17\u8005\u3067\u3059\u3002\u304A\u5BA2\u69D8\u306E\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u51E6\u7406\u3059\u308B\u524D\u306B\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002",buttons:{"consent-all":"\u540C\u610F\u3059\u308B","deny-all":"\u540C\u610F\u3057\u306A\u3044","review-choices":"\u9078\u629E\u3092\u78BA\u8A8D"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08DPDPA\uFF09",subheading:"\u540C\u610F\u3059\u308B\u51E6\u7406\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"consent-all":"\u540C\u610F\u3059\u308B","withdraw-all":"\u540C\u610F\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002\u540C\u610F\u306F\u4E0D\u8981\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var Rt,Bt=f(()=>{"use strict";Rt={mainBanner:{heading:"Hinweis zur Verarbeitung personenbezogener Daten",htmlText:"Gem\xE4\xDF dem Gesetz zum Schutz personenbezogener Daten (PIPL) m\xFCssen wir Sie vor der Verarbeitung Ihrer Daten informieren. Wir verarbeiten Daten nur zu den angegebenen Zwecken auf Grundlage Ihrer Einwilligung.",buttons:{"agree-all":"Zustimmen","reject-non-necessary":"Ablehnen","manage-preferences":"Einstellungen"}},preferenceModal:{heading:"Datenschutzeinstellungen (PIPL)",subheading:"Bitte w\xE4hlen Sie, welcher Datenverarbeitung Sie zustimmen.",buttons:{"agree-all":"Zustimmen","disagree-all":"Ablehnen","confirm-settings":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich. Zweck: Sicherheit und grundlegende Funktionalit\xE4t."},"cat-functional":{heading:"Funktional",htmlText:"Zweck: Verbesserung der Benutzererfahrung. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Zweck: Speicherung personalisierter Einstellungen. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-analytics":{heading:"Analyse",htmlText:"Zweck: Statistiken zur Website-Nutzung. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Zweck: Personalisierte Werbung. Einwilligung gem\xE4\xDF PIPL erforderlich."}}}}});var Nt,Ot=f(()=>{"use strict";Nt={mainBanner:{heading:"Aviso de tratamiento de informaci\xF3n personal",htmlText:"De conformidad con la Ley de Protecci\xF3n de Informaci\xF3n Personal (PIPL), debemos informarle antes de tratar sus datos. Solo procesamos datos con fines espec\xEDficos y con su consentimiento.",buttons:{"agree-all":"Aceptar","reject-non-necessary":"Rechazar","manage-preferences":"Configuraci\xF3n"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (PIPL)",subheading:"Elija qu\xE9 tratamientos de datos acepta.",buttons:{"agree-all":"Aceptar","disagree-all":"Rechazar","confirm-settings":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el sitio. Finalidad: seguridad y funcionalidad b\xE1sica."},"cat-functional":{heading:"Funcionales",htmlText:"Finalidad: mejorar la experiencia del usuario. Se requiere consentimiento seg\xFAn la PIPL."},"cat-preferences":{heading:"Preferencias",htmlText:"Finalidad: guardar configuraci\xF3n personalizada. Se requiere consentimiento seg\xFAn la PIPL."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Finalidad: estad\xEDsticas de uso del sitio. Se requiere consentimiento seg\xFAn la PIPL."},"cat-marketing":{heading:"Marketing",htmlText:"Finalidad: publicidad personalizada. Se requiere consentimiento seg\xFAn la PIPL."}}}}});var Vt,jt=f(()=>{"use strict";Vt={mainBanner:{heading:"Avis de traitement des informations personnelles",htmlText:"Conform\xE9ment \xE0 la loi sur la protection des informations personnelles (PIPL), nous devons vous informer avant tout traitement. Nous traitons les donn\xE9es \xE0 des fins sp\xE9cifiques uniquement, avec votre consentement.",buttons:{"agree-all":"Accepter","reject-non-necessary":"Refuser","manage-preferences":"Param\xE8tres"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (PIPL)",subheading:"Choisissez les traitements de donn\xE9es que vous acceptez.",buttons:{"agree-all":"Accepter","disagree-all":"Refuser","confirm-settings":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au site. Finalit\xE9 : s\xE9curit\xE9 et fonctionnalit\xE9 de base."},"cat-functional":{heading:"Fonctionnels",htmlText:"Finalit\xE9 : am\xE9liorer l'exp\xE9rience utilisateur. Consentement requis selon la PIPL."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Finalit\xE9 : sauvegarder les param\xE8tres personnalis\xE9s. Consentement requis selon la PIPL."},"cat-analytics":{heading:"Analytiques",htmlText:"Finalit\xE9 : statistiques d'utilisation du site. Consentement requis selon la PIPL."},"cat-marketing":{heading:"Marketing",htmlText:"Finalit\xE9 : publicit\xE9 personnalis\xE9e. Consentement requis selon la PIPL."}}}}});var Ht,Ft=f(()=>{"use strict";Ht={mainBanner:{heading:"\u500B\u4EBA\u60C5\u5831\u51E6\u7406\u306B\u95A2\u3059\u308B\u304A\u77E5\u3089\u305B",htmlText:"\u500B\u4EBA\u60C5\u5831\u4FDD\u8B77\u6CD5\uFF08PIPL\uFF09\u306B\u57FA\u3065\u304D\u3001\u30C7\u30FC\u30BF\u51E6\u7406\u306E\u524D\u306B\u304A\u77E5\u3089\u305B\u3059\u308B\u7FA9\u52D9\u304C\u3042\u308A\u307E\u3059\u3002\u304A\u5BA2\u69D8\u306E\u540C\u610F\u3092\u5F97\u305F\u7279\u5B9A\u306E\u76EE\u7684\u306B\u306E\u307F\u30C7\u30FC\u30BF\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002",buttons:{"agree-all":"\u540C\u610F\u3059\u308B","reject-non-necessary":"\u62D2\u5426\u3059\u308B","manage-preferences":"\u8A2D\u5B9A"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08PIPL\uFF09",subheading:"\u540C\u610F\u3059\u308B\u30C7\u30FC\u30BF\u51E6\u7406\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"agree-all":"\u540C\u610F\u3059\u308B","disagree-all":"\u62D2\u5426\u3059\u308B","confirm-settings":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002\u76EE\u7684\uFF1A\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u3068\u57FA\u672C\u6A5F\u80FD\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u76EE\u7684\uFF1A\u30E6\u30FC\u30B6\u30FC\u4F53\u9A13\u306E\u5411\u4E0A\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u76EE\u7684\uFF1A\u500B\u4EBA\u8A2D\u5B9A\u306E\u4FDD\u5B58\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u76EE\u7684\uFF1A\u30B5\u30A4\u30C8\u5229\u7528\u7D71\u8A08\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u76EE\u7684\uFF1A\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var Ut,qt=f(()=>{"use strict";Ut={mainBanner:{heading:"Wir sch\xE4tzen Ihre Privatsph\xE4re",htmlText:"Gem\xE4\xDF dem brasilianischen Datenschutzgesetz (LGPD) verarbeiten wir Ihre personenbezogenen Daten auf Grundlage Ihrer Einwilligung oder unseres berechtigten Interesses, sofern anwendbar. Sie k\xF6nnen Ihre Wahl jederzeit \xE4ndern.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen",manage:"Verwalten"}},preferenceModal:{heading:"Datenschutzeinstellungen (LGPD)",subheading:"W\xE4hlen Sie Ihre Datenschutzoptionen.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Rechtsgrundlage: berechtigtes Interesse (LGPD Art. 10)."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre Einstellungen. Rechtsgrundlage: berechtigtes Interesse (LGPD Art. 10)."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Einwilligung gem\xE4\xDF LGPD erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Einwilligung gem\xE4\xDF LGPD erforderlich."}}}}});var Wt,Kt=f(()=>{"use strict";Wt={mainBanner:{heading:"Valoramos su privacidad",htmlText:"De acuerdo con la Ley General de Protecci\xF3n de Datos (LGPD) de Brasil, tratamos sus datos personales con su consentimiento o con base en inter\xE9s leg\xEDtimo cuando corresponda. Puede cambiar sus preferencias en cualquier momento.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo",manage:"Gestionar"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (LGPD)",subheading:"Elija sus opciones de privacidad.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Base legal: inter\xE9s leg\xEDtimo (LGPD Art. 10)."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n. Base legal: inter\xE9s leg\xEDtimo (LGPD Art. 10)."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a comprender el uso del sitio. Se requiere consentimiento seg\xFAn la LGPD."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere consentimiento seg\xFAn la LGPD."}}}}});var $t,Yt=f(()=>{"use strict";$t={mainBanner:{heading:"Nous respectons votre vie priv\xE9e",htmlText:"Conform\xE9ment \xE0 la loi br\xE9silienne sur la protection des donn\xE9es (LGPD), nous traitons vos donn\xE9es personnelles sur la base de votre consentement ou d'un int\xE9r\xEAt l\xE9gitime, selon le cas. Vous pouvez modifier vos pr\xE9f\xE9rences \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser",manage:"G\xE9rer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (LGPD)",subheading:"Choisissez vos options de confidentialit\xE9.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime (LGPD Art. 10)."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime (LGPD Art. 10)."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Consentement requis selon la LGPD."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Consentement requis selon la LGPD."}}}}});var Jt,Zt=f(()=>{"use strict";Jt={mainBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u3092\u5927\u5207\u306B\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30D6\u30E9\u30B8\u30EB\u306E\u4E00\u822C\u30C7\u30FC\u30BF\u4FDD\u8B77\u6CD5\uFF08LGPD\uFF09\u306B\u57FA\u3065\u304D\u3001\u304A\u5BA2\u69D8\u306E\u540C\u610F\u307E\u305F\u306F\u6B63\u5F53\u306A\u5229\u76CA\u3092\u6839\u62E0\u3068\u3057\u3066\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u51E6\u7406\u3057\u307E\u3059\u3002\u8A2D\u5B9A\u306F\u3044\u3064\u3067\u3082\u5909\u66F4\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426",manage:"\u7BA1\u7406\u3059\u308B"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08LGPD\uFF09",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\uFF08LGPD\u7B2C10\u6761\uFF09\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\uFF08LGPD\u7B2C10\u6761\uFF09\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002LGPD\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002LGPD\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var Qt,Xt=f(()=>{"use strict";Qt={mainBanner:{heading:"Wir verwenden Cookies",htmlText:"Wir verwenden Cookies und \xE4hnliche Technologien, um unsere Dienste bereitzustellen und zu verbessern. F\xFCr Marketing-Cookies ist Ihre Einwilligung erforderlich. Andere Cookies basieren auf unserem berechtigten Interesse.",buttons:{"accept-all":"Alle akzeptieren","reject-marketing":"Marketing ablehnen","manage-preferences":"Einstellungen verwalten"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie Ihre Cookie-Pr\xE4ferenzen.",buttons:{"accept-all":"Alle akzeptieren","necessary-only":"Marketing ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Rechtsgrundlage: berechtigtes Interesse."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen. Rechtsgrundlage: berechtigtes Interesse."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Rechtsgrundlage: berechtigtes Interesse."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Ihre Einwilligung ist erforderlich."}}}}});var en,tn=f(()=>{"use strict";en={mainBanner:{heading:"Usamos cookies",htmlText:"Utilizamos cookies y tecnolog\xEDas similares para ofrecer y mejorar nuestros servicios. Las cookies de marketing requieren su consentimiento. Las dem\xE1s se basan en inter\xE9s leg\xEDtimo.",buttons:{"accept-all":"Aceptar todo","reject-marketing":"Rechazar marketing","manage-preferences":"Gestionar preferencias"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad",subheading:"Elija sus preferencias de cookies.",buttons:{"accept-all":"Aceptar todo","necessary-only":"Rechazar marketing","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Base legal: inter\xE9s leg\xEDtimo."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal. Base legal: inter\xE9s leg\xEDtimo."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio. Base legal: inter\xE9s leg\xEDtimo."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere su consentimiento."}}}}});var nn,on=f(()=>{"use strict";nn={mainBanner:{heading:"Nous utilisons des cookies",htmlText:"Nous utilisons des cookies et des technologies similaires pour fournir et am\xE9liorer nos services. Les cookies marketing n\xE9cessitent votre consentement. Les autres reposent sur notre int\xE9r\xEAt l\xE9gitime.",buttons:{"accept-all":"Tout accepter","reject-marketing":"Refuser le marketing","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez vos pr\xE9f\xE9rences en mati\xE8re de cookies.",buttons:{"accept-all":"Tout accepter","necessary-only":"Refuser le marketing","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Votre consentement est requis."}}}}});var an,rn=f(()=>{"use strict";an={mainBanner:{heading:"Cookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30FC\u30D3\u30B9\u306E\u63D0\u4F9B\u30FB\u6539\u5584\u306E\u305F\u3081\u306BCookie\u304A\u3088\u3073\u985E\u4F3C\u6280\u8853\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0Cookie\u306B\u306F\u304A\u5BA2\u69D8\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002\u305D\u306E\u4ED6\u306F\u6B63\u5F53\u306A\u5229\u76CA\u3092\u6839\u62E0\u3068\u3057\u3066\u3044\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-marketing":"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3092\u62D2\u5426","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"Cookie\u306E\u8A2D\u5B9A\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","necessary-only":"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3092\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002\u304A\u5BA2\u69D8\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var sn,cn=f(()=>{"use strict";sn={mainBanner:{heading:"Diese Website verwendet nur notwendige Cookies",htmlText:"Wir verwenden ausschlie\xDFlich technisch notwendige Cookies, die f\xFCr den Betrieb der Website erforderlich sind. Es werden keine Marketing- oder Analyse-Cookies eingesetzt.",buttons:{ok:"OK"}},preferenceModal:{heading:"Cookie-Informationen",buttons:{close:"Schlie\xDFen"},categories:{"cat-necessary":{heading:"Notwendige Cookies",htmlText:"Technisch notwendige Cookies, die f\xFCr den ordnungsgem\xE4\xDFen Betrieb der Website erforderlich sind. Sie k\xF6nnen nicht deaktiviert werden."}}}}});var ln,pn=f(()=>{"use strict";ln={mainBanner:{heading:"Este sitio solo usa cookies esenciales",htmlText:"\xDAnicamente utilizamos cookies t\xE9cnicamente necesarias para el funcionamiento del sitio. No utilizamos cookies de marketing ni anal\xEDticas.",buttons:{ok:"Aceptar"}},preferenceModal:{heading:"Informaci\xF3n sobre cookies",buttons:{close:"Cerrar"},categories:{"cat-necessary":{heading:"Cookies necesarias",htmlText:"Cookies t\xE9cnicamente necesarias para el correcto funcionamiento del sitio. No pueden desactivarse."}}}}});var dn,un=f(()=>{"use strict";dn={mainBanner:{heading:"Ce site utilise uniquement des cookies essentiels",htmlText:"Nous n'utilisons que des cookies techniquement n\xE9cessaires au bon fonctionnement du site. Aucun cookie de marketing ou d'analyse n'est utilis\xE9.",buttons:{ok:"OK"}},preferenceModal:{heading:"Informations sur les cookies",buttons:{close:"Fermer"},categories:{"cat-necessary":{heading:"Cookies n\xE9cessaires",htmlText:"Cookies techniquement n\xE9cessaires au bon fonctionnement du site. Ils ne peuvent pas \xEAtre d\xE9sactiv\xE9s."}}}}});var mn,gn=f(()=>{"use strict";mn={mainBanner:{heading:"\u5F53\u30B5\u30A4\u30C8\u306F\u5FC5\u9808Cookie\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30A4\u30C8\u306E\u6B63\u5E38\u306A\u52D5\u4F5C\u306B\u5FC5\u8981\u306A\u6280\u8853\u7684Cookie\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3084\u5206\u6790\u306ECookie\u306F\u4F7F\u7528\u3057\u3066\u3044\u307E\u305B\u3093\u3002",buttons:{ok:"OK"}},preferenceModal:{heading:"Cookie\u306B\u95A2\u3059\u308B\u60C5\u5831",buttons:{close:"\u9589\u3058\u308B"},categories:{"cat-necessary":{heading:"\u5FC5\u9808Cookie",htmlText:"\u30B5\u30A4\u30C8\u306E\u6B63\u5E38\u306A\u52D5\u4F5C\u306B\u5FC5\u8981\u306A\u6280\u8853\u7684Cookie\u3067\u3059\u3002\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"}}}}});var fn={};Z(fn,{DEFAULT_PROFILES:()=>Oe,GENERAL_PRIVACY_CONSENT_EN_PROFILE:()=>ae,NOTICE_ONLY_EN_PROFILE:()=>re,OPT_IN_BRAZIL_EN_PROFILE:()=>ie,OPT_IN_CHINA_EN_PROFILE:()=>oe,OPT_IN_DPDPA_EN_PROFILE:()=>ne,OPT_IN_EN_PROFILE:()=>X,OPT_OUT_EN_PROFILE:()=>ee,OPT_OUT_STRICT_EN_PROFILE:()=>te,resolveLocaleTranslation:()=>co});function Ne(n,e){let t={};for(let[o,i]of Object.entries(n))t[o]=e[o]!==void 0?{...i,text:e[o]}:i;return t}function co(n,e){let o=Oe[n]?.translations.en;if(!o)return;if(e==="en")return o;let i=so[n]?.[e];if(!i)return;let a={};for(let[r,c]of Object.entries(o.preferenceModal.categories)){let s=i.preferenceModal.categories[`cat-${r}`];a[r]=s?{...c,heading:s.heading,htmlText:s.htmlText}:c}return{mainBanner:{...o.mainBanner,heading:i.mainBanner.heading,htmlText:i.mainBanner.htmlText,buttons:Ne(o.mainBanner.buttons,i.mainBanner.buttons)},...o.gpcBanner?{gpcBanner:i.gpcBanner?{...o.gpcBanner,heading:i.gpcBanner.heading,htmlText:i.gpcBanner.htmlText,buttons:Ne(o.gpcBanner.buttons,i.gpcBanner.buttons)}:o.gpcBanner}:{},preferenceModal:{...o.preferenceModal,heading:i.preferenceModal.heading,...i.preferenceModal.subheading?{subheading:i.preferenceModal.subheading}:{},...i.preferenceModal.htmlText?{htmlText:i.preferenceModal.htmlText}:{},buttons:Ne(o.preferenceModal.buttons,i.preferenceModal.buttons),categories:a}}}var Oe,so,Ve=f(()=>{"use strict";Se();Ie();Me();De();Le();ze();Re();Be();at();st();lt();dt();mt();ft();yt();bt();kt();_t();wt();Tt();Gt();It();Dt();zt();Bt();Ot();jt();Ft();qt();Kt();Yt();Zt();Xt();tn();on();rn();cn();pn();un();gn();Se();Ie();Me();De();Le();ze();Re();Be();Oe={"opt-in":X,"opt-out":ee,"opt-out-strict":te,"opt-in-dpdpa":ne,"opt-in-china":oe,"opt-in-brazil":ie,"general-privacy-consent":ae,"notice-only":re},so={"opt-in":{de:it,es:rt,fr:ct,ja:pt},"opt-out":{de:ut,es:gt,fr:ht,ja:vt},"opt-out-strict":{de:Ct,es:Pt,fr:xt,ja:At},"opt-in-dpdpa":{de:Et,es:St,fr:Mt,ja:Lt},"opt-in-china":{de:Rt,es:Nt,fr:Vt,ja:Ht},"opt-in-brazil":{de:Ut,es:Wt,fr:$t,ja:Jt},"general-privacy-consent":{de:Qt,es:en,fr:nn,ja:an},"notice-only":{de:sn,es:ln,fr:dn,ja:mn}}});var We={};Z(We,{signValue:()=>Sn,verifyValue:()=>vo});async function yo(n){let e=new TextEncoder().encode(n);return crypto.subtle.importKey("raw",e,{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async function Sn(n,e){let t=await yo(e),o=new TextEncoder().encode(n),i=await crypto.subtle.sign("HMAC",t,o);return Array.from(new Uint8Array(i)).map(a=>a.toString(16).padStart(2,"0")).join("")}async function vo(n,e,t){return await Sn(n,t)===e}var Ke=f(()=>{"use strict"});var Ye={};Z(Ye,{httpRequest:()=>ge});async function ge(n,e={},t){let o={"Content-Type":"application/json",...e.headers};t&&(o.Authorization=`Bearer ${t}`);let i=await fetch(n,{...e,headers:o,credentials:e.credentials??"include"});if(!i.ok)throw new Error(`[Consenti] HTTP ${i.status} ${i.statusText} \u2014 ${n}`);return i.json()}var fe=f(()=>{"use strict"});var qo={};Z(qo,{BannerTrigger:()=>Te,CategoryAction:()=>Ae,CategoryScript:()=>O,ConsentAction:()=>we,ConsentScript:()=>N,ConsentiPlugin:()=>_e,ConsentiProfile:()=>xe,ConsentiSetup:()=>Pe,scanConsentScripts:()=>ce});function H(n){let e=new Map;for(let t of Object.values(n))for(let o of t.cookies)e.set(o,t);return e}function Ge(n,e){return e.get(n)?.legalBasis??"consent"}function G(n,e){return Ge(n,e)==="mandatory"}var R={version:"2026-07",countries:{AT:{name:"Austria",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Austria (GDPR)",locales:["de-AT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vienna"]},BE:{name:"Belgium",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Belgium (GDPR)",locales:["nl-BE","fr-BE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Brussels"]},BG:{name:"Bulgaria",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Bulgaria (GDPR)",locales:["bg-BG"],compliance:["gdpr","eprivacy"],timezones:["Europe/Sofia"]},HR:{name:"Croatia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Croatia (GDPR)",locales:["hr-HR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Zagreb"]},CY:{name:"Cyprus",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Cyprus (GDPR)",locales:["el-CY"],compliance:["gdpr","eprivacy"],timezones:["Asia/Nicosia"]},CZ:{name:"Czechia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Czechia (GDPR)",locales:["cs-CZ"],compliance:["gdpr","eprivacy"],timezones:["Europe/Prague"]},DK:{name:"Denmark",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Denmark (GDPR)",locales:["da-DK"],compliance:["gdpr","eprivacy"],timezones:["Europe/Copenhagen"]},EE:{name:"Estonia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Estonia (GDPR)",locales:["et-EE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Tallinn"]},FI:{name:"Finland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Finland (GDPR)",locales:["fi-FI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Helsinki"]},FR:{name:"France",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"France (GDPR)",locales:["fr-FR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Paris"]},DE:{name:"Germany",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Germany (GDPR)",locales:["de-DE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Berlin"]},GR:{name:"Greece",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Greece (GDPR)",locales:["el-GR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Athens"]},HU:{name:"Hungary",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Hungary (GDPR)",locales:["hu-HU"],compliance:["gdpr","eprivacy"],timezones:["Europe/Budapest"]},IE:{name:"Ireland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Ireland (GDPR)",locales:["en"],compliance:["gdpr","eprivacy"],timezones:["Europe/Dublin"]},IT:{name:"Italy",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Italy (GDPR)",locales:["it-IT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Rome"]},LV:{name:"Latvia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Latvia (GDPR)",locales:["lv-LV"],compliance:["gdpr","eprivacy"],timezones:["Europe/Riga"]},LT:{name:"Lithuania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Lithuania (GDPR)",locales:["lt-LT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vilnius"]},LU:{name:"Luxembourg",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Luxembourg (GDPR)",locales:["fr-LU","de-LU"],compliance:["gdpr","eprivacy"],timezones:["Europe/Luxembourg"]},MT:{name:"Malta",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Malta (GDPR)",locales:["mt-MT","en"],compliance:["gdpr","eprivacy"],timezones:["Europe/Malta"]},NL:{name:"Netherlands",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Netherlands (GDPR)",locales:["nl-NL"],compliance:["gdpr","eprivacy"],timezones:["Europe/Amsterdam"]},PL:{name:"Poland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Poland (GDPR)",locales:["pl-PL"],compliance:["gdpr","eprivacy"],timezones:["Europe/Warsaw"]},PT:{name:"Portugal",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Portugal (GDPR)",locales:["pt-PT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Lisbon","Atlantic/Madeira","Atlantic/Azores"]},RO:{name:"Romania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Romania (GDPR)",locales:["ro-RO"],compliance:["gdpr","eprivacy"],timezones:["Europe/Bucharest"]},SK:{name:"Slovakia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Slovakia (GDPR)",locales:["sk-SK"],compliance:["gdpr","eprivacy"],timezones:["Europe/Bratislava"]},SI:{name:"Slovenia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Slovenia (GDPR)",locales:["sl-SI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Ljubljana"]},ES:{name:"Spain",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Spain (GDPR)",locales:["es-ES"],compliance:["gdpr","eprivacy"],timezones:["Europe/Madrid","Africa/Ceuta","Atlantic/Canary"]},SE:{name:"Sweden",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Sweden (GDPR)",locales:["sv-SE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Stockholm"]},IS:{name:"Iceland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Iceland (GDPR via EEA)",locales:["is-IS"],compliance:["gdpr","eprivacy"],timezones:["Atlantic/Reykjavik"]},LI:{name:"Liechtenstein",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Liechtenstein (GDPR via EEA)",locales:["de-LI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vaduz"]},NO:{name:"Norway",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Norway (GDPR via EEA)",locales:["nb-NO"],compliance:["gdpr","eprivacy"],timezones:["Europe/Oslo","Arctic/Longyearbyen"]},AD:{name:"Andorra",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Andorra (GDPR-aligned)",locales:["ca-AD"],compliance:["gdpr"],timezones:["Europe/Andorra"]},AL:{name:"Albania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Albania (GDPR-aligned)",locales:["sq-AL"],compliance:["gdpr"],timezones:["Europe/Tirane"]},BA:{name:"Bosnia and Herzegovina",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Bosnia and Herzegovina (GDPR-aligned)",locales:["bs-BA","sr-Latn-BA"],compliance:["gdpr"],timezones:["Europe/Sarajevo"]},GG:{name:"Guernsey",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Guernsey (DPA based on GDPR)",locales:["en"],compliance:["gdpr"],timezones:["Europe/Guernsey"]},GI:{name:"Gibraltar",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Gibraltar (DPA based on UK GDPR)",locales:["en"],compliance:["uk-gdpr"],timezones:["Europe/Gibraltar"]},GL:{name:"Greenland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Greenland (Danish GDPR implementation)",locales:["da-GL"],compliance:["gdpr"],timezones:["America/Nuuk","America/Danmarkshavn","America/Scoresbysund","America/Thule"]},MC:{name:"Monaco",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Monaco (GDPR-aligned)",locales:["fr-MC"],compliance:["gdpr"],timezones:["Europe/Monaco"]},ME:{name:"Montenegro",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Montenegro (GDPR-aligned)",locales:["sr-Latn-ME"],compliance:["gdpr"],timezones:["Europe/Podgorica"]},MK:{name:"North Macedonia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"North Macedonia (GDPR-aligned)",locales:["mk-MK"],compliance:["gdpr"],timezones:["Europe/Skopje"]},RS:{name:"Serbia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Serbia (GDPR-aligned)",locales:["sr-RS"],compliance:["gdpr"],timezones:["Europe/Belgrade"]},SM:{name:"San Marino",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"San Marino (GDPR-aligned)",locales:["it-SM"],compliance:["gdpr"],timezones:["Europe/San_Marino"]},TR:{name:"T\xFCrkiye",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"T\xFCrkiye (KVKK)",locales:["tr-TR"],compliance:["kvkk"],timezones:["Europe/Istanbul"]},CA:{name:"Canada",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Canada (PIPEDA / Law 25)",locales:["en","fr-CA"],compliance:["pipeda","law25"],timezones:["America/St_Johns","America/Halifax","America/Toronto","America/Winnipeg","America/Edmonton","America/Vancouver"],overriddenRegions:{QC:{name:"Quebec",type:"region",complianceGroup:"opt-in",description:"Quebec \u2014 Law 25 (GDPR-style opt-in)"}}},US:{name:"United States",type:"country",complianceGroup:"opt-out",default:"opt-out-strict",description:"United States \u2014 opt-out-strict (CPRA) used when state cannot be detected",locales:["en","es-US"],compliance:["ccpa","cpra","vcdpa","cpa-co","ctdpa","ucpa","icdpa-ia","icdpa-in","tipa","mcdpa-mt","mcdpa-mn","ocpa","tdpsa","dpdpa-de","njdpa","nhpa","ndpa-ne","modpa","kcdpa","ridtpa"],timezones:["America/New_York","America/Chicago","America/Denver","America/Phoenix","America/Los_Angeles","America/Anchorage","Pacific/Honolulu"],overriddenRegions:{CA:{name:"California",type:"region",complianceGroup:"opt-out-strict",description:"California \u2014 CPRA/CCPA"},VA:{name:"Virginia",type:"region",complianceGroup:"opt-out",description:"Virginia \u2014 VCDPA"},CO:{name:"Colorado",type:"region",complianceGroup:"opt-out",description:"Colorado \u2014 CPA"},CT:{name:"Connecticut",type:"region",complianceGroup:"opt-out",description:"Connecticut \u2014 CTDPA"},UT:{name:"Utah",type:"region",complianceGroup:"opt-out",description:"Utah \u2014 UCPA"},TX:{name:"Texas",type:"region",complianceGroup:"opt-out",description:"Texas \u2014 TDPSA"},DE:{name:"Delaware",type:"region",complianceGroup:"opt-out",description:"Delaware \u2014 DPDPA"},NJ:{name:"New Jersey",type:"region",complianceGroup:"opt-out",description:"New Jersey \u2014 NJDPA"},OR:{name:"Oregon",type:"region",complianceGroup:"opt-out",description:"Oregon \u2014 OCPA"},MN:{name:"Minnesota",type:"region",complianceGroup:"opt-out",description:"Minnesota \u2014 MCDPA"},MD:{name:"Maryland",type:"region",complianceGroup:"opt-out",description:"Maryland \u2014 MODPA"},KY:{name:"Kentucky",type:"region",complianceGroup:"opt-out",description:"Kentucky \u2014 KCDPA"},TN:{name:"Tennessee",type:"region",complianceGroup:"opt-out",description:"Tennessee \u2014 TIPA"},NE:{name:"Nebraska",type:"region",complianceGroup:"opt-out",description:"Nebraska \u2014 NDPA"},IA:{name:"Iowa",type:"region",complianceGroup:"opt-out",description:"Iowa \u2014 ICDPA"},IN:{name:"Indiana",type:"region",complianceGroup:"opt-out",description:"Indiana \u2014 ICDPA"},MT:{name:"Montana",type:"region",complianceGroup:"opt-out",description:"Montana \u2014 MCDPA"},NH:{name:"New Hampshire",type:"region",complianceGroup:"opt-out",description:"New Hampshire \u2014 NHPA"},RI:{name:"Rhode Island",type:"region",complianceGroup:"opt-out",description:"Rhode Island \u2014 RIDTPA"}}},AR:{name:"Argentina",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Argentina (LPDP)",locales:["es-AR"],compliance:["lpdp-ar"],timezones:["America/Argentina/Buenos_Aires"]},BO:{name:"Bolivia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bolivia",locales:["es-BO"],compliance:[],timezones:["America/La_Paz"]},BR:{name:"Brazil",type:"country",complianceGroup:"opt-in-brazil",default:"opt-in-brazil",description:"Brazil (LGPD)",locales:["pt-BR"],compliance:["lgpd"],timezones:["America/Noronha","America/Sao_Paulo","America/Manaus","America/Rio_Branco"]},CL:{name:"Chile",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Chile (Law 19.628)",locales:["es-CL"],compliance:["law19628-cl"],timezones:["America/Santiago","Pacific/Easter"]},CO:{name:"Colombia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Colombia (Law 1581)",locales:["es-CO"],compliance:["law1581-co"],timezones:["America/Bogota"]},CR:{name:"Costa Rica",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Costa Rica (LPDP)",locales:["es-CR"],compliance:["lpdp-cr"],timezones:["America/Costa_Rica"]},DO:{name:"Dominican Republic",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Dominican Republic",locales:["es-DO"],compliance:["data-protection-do"],timezones:["America/Santo_Domingo"]},EC:{name:"Ecuador",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Ecuador (LOPDP)",locales:["es-EC"],compliance:["lopdp-ec"],timezones:["America/Guayaquil","Pacific/Galapagos"]},GF:{name:"French Guiana",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"French Guiana",locales:["fr-GF"],compliance:[],timezones:["America/Cayenne"]},GT:{name:"Guatemala",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guatemala",locales:["es-GT"],compliance:[],timezones:["America/Guatemala"]},GY:{name:"Guyana",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guyana",locales:["en"],compliance:[],timezones:["America/Guyana"]},HN:{name:"Honduras",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Honduras",locales:["es-HN"],compliance:[],timezones:["America/Tegucigalpa"]},HT:{name:"Haiti",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Haiti",locales:["fr-HT"],compliance:[],timezones:["America/Port-au-Prince"]},JM:{name:"Jamaica",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Jamaica",locales:["en"],compliance:[],timezones:["America/Jamaica"]},MX:{name:"Mexico",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Mexico (LFPDPPP)",locales:["es-MX"],compliance:["lfpdppp"],timezones:["America/Mexico_City","America/Cancun","America/Chihuahua","America/Hermosillo","America/Tijuana"]},NI:{name:"Nicaragua",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nicaragua",locales:["es-NI"],compliance:[],timezones:["America/Managua"]},PA:{name:"Panama",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Panama",locales:["es-PA"],compliance:["data-protection-pa"],timezones:["America/Panama"]},PE:{name:"Peru",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Peru (LPDP)",locales:["es-PE"],compliance:["lpdp-pe"],timezones:["America/Lima"]},PY:{name:"Paraguay",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Paraguay",locales:["es-PY"],compliance:[],timezones:["America/Asuncion"]},SR:{name:"Suriname",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Suriname",locales:["nl-SR"],compliance:[],timezones:["America/Paramaribo"]},SV:{name:"El Salvador",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"El Salvador",locales:["es-SV"],compliance:[],timezones:["America/El_Salvador"]},TT:{name:"Trinidad and Tobago",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Trinidad and Tobago",locales:["en"],compliance:[],timezones:["America/Port_of_Spain"]},UY:{name:"Uruguay",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Uruguay (Law 18.331)",locales:["es-UY"],compliance:["law18331-uy"],timezones:["America/Montevideo"]},VE:{name:"Venezuela",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Venezuela",locales:["es-VE"],compliance:[],timezones:["America/Caracas"]},AG:{name:"Antigua and Barbuda",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Antigua and Barbuda",locales:["en"],compliance:[],timezones:["America/Antigua"]},BB:{name:"Barbados",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Barbados",locales:["en"],compliance:[],timezones:["America/Barbados"]},BL:{name:"Saint Barth\xE9lemy",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Barth\xE9lemy",locales:["fr-BL"],compliance:[],timezones:["America/St_Barthelemy"]},BM:{name:"Bermuda",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bermuda",locales:["en"],compliance:[],timezones:["Atlantic/Bermuda"]},BS:{name:"Bahamas",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bahamas",locales:["en"],compliance:[],timezones:["America/Nassau"]},CU:{name:"Cuba",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cuba",locales:["es-CU"],compliance:[],timezones:["America/Havana"]},DM:{name:"Dominica",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Dominica",locales:["en"],compliance:[],timezones:["America/Dominica"]},GD:{name:"Grenada",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Grenada",locales:["en"],compliance:[],timezones:["America/Grenada"]},KN:{name:"Saint Kitts and Nevis",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Kitts and Nevis",locales:["en"],compliance:[],timezones:["America/St_Kitts"]},LC:{name:"Saint Lucia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Lucia",locales:["en"],compliance:[],timezones:["America/St_Lucia"]},PM:{name:"Saint Pierre and Miquelon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Pierre and Miquelon",locales:["fr-PM"],compliance:[],timezones:["America/Miquelon"]},PR:{name:"Puerto Rico",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Puerto Rico",locales:["es-PR","en"],compliance:[],timezones:["America/Puerto_Rico"]},VC:{name:"Saint Vincent and the Grenadines",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Vincent and the Grenadines",locales:["en"],compliance:[],timezones:["America/St_Vincent"]},IN:{name:"India",type:"country",complianceGroup:"opt-in-dpdpa",default:"opt-in-dpdpa",description:"India (DPDPA)",locales:["hi-IN","en","bn-IN","ta-IN"],compliance:["dpdpa"],timezones:["Asia/Kolkata","Asia/Calcutta"]},CN:{name:"China",type:"country",complianceGroup:"opt-in-china",default:"opt-in-china",description:"China (PIPL + DSL + CSL)",locales:["zh-CN"],compliance:["pipl","dsl-cn","csl-cn"],timezones:["Asia/Shanghai"]},BN:{name:"Brunei",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Brunei (Personal Data Protection Order)",locales:["ms-BN","en"],compliance:["privacy-bn"],timezones:["Asia/Brunei"]},ID:{name:"Indonesia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Indonesia (PDP Law)",locales:["id-ID"],compliance:["pdp-id"],timezones:["Asia/Jakarta","Asia/Makassar","Asia/Jayapura"]},KH:{name:"Cambodia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cambodia",locales:["km-KH"],compliance:[],timezones:["Asia/Phnom_Penh"]},LA:{name:"Laos",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Laos",locales:["lo-LA"],compliance:[],timezones:["Asia/Vientiane"]},MM:{name:"Myanmar",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Myanmar",locales:["my-MM"],compliance:[],timezones:["Asia/Yangon"]},MY:{name:"Malaysia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Malaysia (PDPA)",locales:["ms-MY","zh-MY","en"],compliance:["pdpa-my"],timezones:["Asia/Kuala_Lumpur","Asia/Kuching"]},PH:{name:"Philippines",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Philippines (DPA)",locales:["fil-PH","en"],compliance:["dpa-ph"],timezones:["Asia/Manila"]},SG:{name:"Singapore",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Singapore (PDPA)",locales:["zh-SG","ms-SG","ta-SG","en"],compliance:["pdpa-sg"],timezones:["Asia/Singapore"]},TH:{name:"Thailand",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Thailand (PDPA \u2014 GDPR-style opt-in)",locales:["th-TH"],compliance:["pdpa-th"],timezones:["Asia/Bangkok"]},TL:{name:"Timor-Leste",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Timor-Leste",locales:["pt-TL"],compliance:[],timezones:["Asia/Dili"]},VN:{name:"Vietnam",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Vietnam (PDPD)",locales:["vi-VN"],compliance:["pdpd-vn"],timezones:["Asia/Ho_Chi_Minh"]},HK:{name:"Hong Kong",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Hong Kong SAR (PDPO)",locales:["zh-HK"],compliance:["pdpl-hk"],timezones:["Asia/Hong_Kong"]},JP:{name:"Japan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Japan (APPI)",locales:["ja-JP"],compliance:["appi"],timezones:["Asia/Tokyo"]},KP:{name:"North Korea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"North Korea",locales:["ko-KP"],compliance:[],timezones:["Asia/Pyongyang"]},KR:{name:"South Korea",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"South Korea (PIPA)",locales:["ko-KR"],compliance:["pipa-kr"],timezones:["Asia/Seoul"]},MN:{name:"Mongolia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mongolia",locales:["mn-MN"],compliance:[],timezones:["Asia/Ulaanbaatar","Asia/Hovd"]},MO:{name:"Macau",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Macau SAR (PDPA)",locales:["zh-MO","pt-MO"],compliance:["pdpa-mo"],timezones:["Asia/Macau"]},TW:{name:"Taiwan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Taiwan (PDPL)",locales:["zh-TW"],compliance:["pdpl-tw"],timezones:["Asia/Taipei"]},AF:{name:"Afghanistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Afghanistan",locales:["fa-AF"],compliance:[],timezones:["Asia/Kabul"]},BD:{name:"Bangladesh",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bangladesh",locales:["bn-BD"],compliance:[],timezones:["Asia/Dhaka"]},BT:{name:"Bhutan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bhutan",locales:["dz-BT"],compliance:[],timezones:["Asia/Thimphu"]},IO:{name:"British Indian Ocean Territory",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"British Indian Ocean Territory",locales:["en"],compliance:[],timezones:["Indian/Chagos"]},LK:{name:"Sri Lanka",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Sri Lanka",locales:["si-LK","ta-LK"],compliance:["privacy-lk"],timezones:["Asia/Colombo"]},MV:{name:"Maldives",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Maldives",locales:["dv-MV"],compliance:[],timezones:["Indian/Maldives"]},NP:{name:"Nepal",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nepal",locales:["ne-NP"],compliance:["privacy-np"],timezones:["Asia/Kathmandu"]},PK:{name:"Pakistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Pakistan",locales:["ur-PK","en"],compliance:[],timezones:["Asia/Karachi"]},AM:{name:"Armenia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Armenia",locales:["hy-AM"],compliance:[],timezones:["Asia/Yerevan"]},AZ:{name:"Azerbaijan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Azerbaijan",locales:["az-AZ"],compliance:[],timezones:["Asia/Baku"]},GE:{name:"Georgia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Georgia",locales:["ka-GE"],compliance:[],timezones:["Asia/Tbilisi"]},KG:{name:"Kyrgyzstan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kyrgyzstan",locales:["ky-KG","ru-KG"],compliance:[],timezones:["Asia/Bishkek"]},KZ:{name:"Kazakhstan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kazakhstan",locales:["kk-KZ","ru-KZ"],compliance:[],timezones:["Asia/Almaty","Asia/Aqtobe"]},TJ:{name:"Tajikistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tajikistan",locales:["tg-TJ"],compliance:[],timezones:["Asia/Dushanbe"]},TM:{name:"Turkmenistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Turkmenistan",locales:["tk-TM"],compliance:[],timezones:["Asia/Ashgabat"]},UZ:{name:"Uzbekistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Uzbekistan",locales:["uz-UZ"],compliance:[],timezones:["Asia/Tashkent","Asia/Samarkand"]},AE:{name:"United Arab Emirates",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"United Arab Emirates (UAE PDPL / DIFC DPL / ADGM DPR)",locales:["ar-AE"],compliance:["uae-pdpl","difc-dpl","adgm-dpr"],timezones:["Asia/Dubai"]},BH:{name:"Bahrain",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bahrain (PDPL)",locales:["ar-BH"],compliance:["pdpl-bh"],timezones:["Asia/Bahrain"]},IL:{name:"Israel",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Israel (Privacy Protection Law)",locales:["he-IL","ar-IL"],compliance:["privacy-il"],timezones:["Asia/Jerusalem"]},IQ:{name:"Iraq",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Iraq",locales:["ar-IQ"],compliance:[],timezones:["Asia/Baghdad"]},IR:{name:"Iran",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Iran",locales:["fa-IR"],compliance:[],timezones:["Asia/Tehran"]},JO:{name:"Jordan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Jordan",locales:["ar-JO"],compliance:[],timezones:["Asia/Amman"]},KW:{name:"Kuwait",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Kuwait",locales:["ar-KW"],compliance:["privacy-kw"],timezones:["Asia/Kuwait"]},LB:{name:"Lebanon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Lebanon",locales:["ar-LB"],compliance:[],timezones:["Asia/Beirut"]},OM:{name:"Oman",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Oman (PDPL)",locales:["ar-OM"],compliance:["pdpl-om"],timezones:["Asia/Muscat"]},PS:{name:"Palestine",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Palestine",locales:["ar-PS"],compliance:[],timezones:["Asia/Gaza","Asia/Hebron"]},QA:{name:"Qatar",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Qatar (PDPL)",locales:["ar-QA"],compliance:["qpdl-qa"],timezones:["Asia/Qatar"]},SA:{name:"Saudi Arabia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Saudi Arabia (PDPL)",locales:["ar-SA"],compliance:["pdpl-sa"],timezones:["Asia/Riyadh"]},SY:{name:"Syria",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Syria",locales:["ar-SY"],compliance:[],timezones:["Asia/Damascus"]},YE:{name:"Yemen",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Yemen",locales:["ar-YE"],compliance:[],timezones:["Asia/Aden"]},BF:{name:"Burkina Faso",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Burkina Faso",locales:["fr-BF"],compliance:[],timezones:["Africa/Ouagadougou"]},BJ:{name:"Benin",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Benin",locales:["fr-BJ"],compliance:[],timezones:["Africa/Porto-Novo"]},CI:{name:"C\xF4te d'Ivoire",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"C\xF4te d'Ivoire",locales:["fr-CI"],compliance:[],timezones:["Africa/Abidjan"]},CM:{name:"Cameroon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cameroon",locales:["fr-CM","en"],compliance:[],timezones:["Africa/Douala"]},CV:{name:"Cabo Verde",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cabo Verde",locales:["pt-CV"],compliance:[],timezones:["Atlantic/Cape_Verde"]},GA:{name:"Gabon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Gabon",locales:["fr-GA"],compliance:[],timezones:["Africa/Libreville"]},GH:{name:"Ghana",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Ghana (DPA)",locales:["en"],compliance:["dpa-gh"],timezones:["Africa/Accra"]},GM:{name:"Gambia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Gambia",locales:["en"],compliance:[],timezones:["Africa/Banjul"]},GN:{name:"Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guinea",locales:["fr-GN"],compliance:[],timezones:["Africa/Conakry"]},GQ:{name:"Equatorial Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Equatorial Guinea",locales:["es-GQ","fr-GQ"],compliance:[],timezones:["Africa/Malabo"]},GW:{name:"Guinea-Bissau",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guinea-Bissau",locales:["pt-GW"],compliance:[],timezones:["Africa/Bissau"]},LR:{name:"Liberia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Liberia",locales:["en"],compliance:[],timezones:["Africa/Monrovia"]},ML:{name:"Mali",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mali",locales:["fr-ML"],compliance:[],timezones:["Africa/Bamako"]},MR:{name:"Mauritania",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mauritania",locales:["ar-MR"],compliance:[],timezones:["Africa/Nouakchott"]},NE:{name:"Niger",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Niger",locales:["fr-NE"],compliance:[],timezones:["Africa/Niamey"]},NG:{name:"Nigeria",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Nigeria (NDPA)",locales:["en"],compliance:["ndpa-ng"],timezones:["Africa/Lagos"]},SL:{name:"Sierra Leone",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Sierra Leone",locales:["en"],compliance:[],timezones:["Africa/Freetown"]},SN:{name:"Senegal",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Senegal",locales:["fr-SN"],compliance:[],timezones:["Africa/Dakar"]},TG:{name:"Togo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Togo",locales:["fr-TG"],compliance:[],timezones:["Africa/Lome"]},BI:{name:"Burundi",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Burundi",locales:["fr-BI"],compliance:[],timezones:["Africa/Bujumbura"]},DJ:{name:"Djibouti",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Djibouti",locales:["fr-DJ","ar-DJ"],compliance:[],timezones:["Africa/Djibouti"]},ER:{name:"Eritrea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Eritrea",locales:["ti-ER"],compliance:[],timezones:["Africa/Asmara"]},ET:{name:"Ethiopia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Ethiopia",locales:["am-ET"],compliance:[],timezones:["Africa/Addis_Ababa"]},KE:{name:"Kenya",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Kenya (DPA)",locales:["sw-KE","en"],compliance:["dpa-ke"],timezones:["Africa/Nairobi"]},KM:{name:"Comoros",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Comoros",locales:["ar-KM","fr-KM"],compliance:[],timezones:["Indian/Comoro"]},MG:{name:"Madagascar",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Madagascar",locales:["fr-MG"],compliance:[],timezones:["Indian/Antananarivo"]},MU:{name:"Mauritius",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Mauritius (DPA)",locales:["en","fr-MU"],compliance:["dpa-mu"],timezones:["Indian/Mauritius"]},MW:{name:"Malawi",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Malawi",locales:["en"],compliance:[],timezones:["Africa/Blantyre"]},MZ:{name:"Mozambique",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mozambique",locales:["pt-MZ"],compliance:[],timezones:["Africa/Maputo"]},RW:{name:"Rwanda",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Rwanda (DPA)",locales:["rw-RW","en"],compliance:["dpa-rw"],timezones:["Africa/Kigali"]},SC:{name:"Seychelles",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Seychelles",locales:["fr-SC","en"],compliance:[],timezones:["Indian/Mahe"]},SO:{name:"Somalia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Somalia",locales:["so-SO"],compliance:[],timezones:["Africa/Mogadishu"]},SS:{name:"South Sudan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"South Sudan",locales:["en"],compliance:[],timezones:["Africa/Juba"]},ST:{name:"S\xE3o Tom\xE9 and Pr\xEDncipe",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"S\xE3o Tom\xE9 and Pr\xEDncipe",locales:["pt-ST"],compliance:[],timezones:["Africa/Sao_Tome"]},TZ:{name:"Tanzania",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Tanzania",locales:["sw-TZ","en"],compliance:[],timezones:["Africa/Dar_es_Salaam"]},UG:{name:"Uganda",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Uganda (DPA)",locales:["en"],compliance:["dpa-ug"],timezones:["Africa/Kampala"]},AO:{name:"Angola",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Angola",locales:["pt-AO"],compliance:[],timezones:["Africa/Luanda"]},BW:{name:"Botswana",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Botswana (DPA)",locales:["en"],compliance:["dpa-bw"],timezones:["Africa/Gaborone"]},LS:{name:"Lesotho",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Lesotho",locales:["en"],compliance:[],timezones:["Africa/Maseru"]},NA:{name:"Namibia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Namibia",locales:["en"],compliance:[],timezones:["Africa/Windhoek"]},SZ:{name:"Eswatini",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Eswatini",locales:["en"],compliance:[],timezones:["Africa/Mbabane"]},ZA:{name:"South Africa",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"South Africa (POPIA)",locales:["en","af-ZA"],compliance:["popia"],timezones:["Africa/Johannesburg"]},ZM:{name:"Zambia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Zambia (DPA)",locales:["en"],compliance:["dpa-zm"],timezones:["Africa/Lusaka"]},ZW:{name:"Zimbabwe",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Zimbabwe (DPA)",locales:["en"],compliance:["dpa-zw"],timezones:["Africa/Harare"]},DZ:{name:"Algeria",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Algeria",locales:["ar-DZ","fr-DZ"],compliance:["dpa-dz"],timezones:["Africa/Algiers"]},EG:{name:"Egypt",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Egypt (DPA)",locales:["ar-EG"],compliance:["dpa-eg"],timezones:["Africa/Cairo"]},LY:{name:"Libya",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Libya",locales:["ar-LY"],compliance:[],timezones:["Africa/Tripoli"]},MA:{name:"Morocco",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Morocco",locales:["ar-MA","fr-MA"],compliance:["dpa-ma"],timezones:["Africa/Casablanca"]},SD:{name:"Sudan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Sudan",locales:["ar-SD"],compliance:[],timezones:["Africa/Khartoum"]},TN:{name:"Tunisia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Tunisia (DPA)",locales:["ar-TN","fr-TN"],compliance:["dpa-tn"],timezones:["Africa/Tunis"]},CD:{name:"DR Congo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"DR Congo",locales:["fr-CD"],compliance:[],timezones:["Africa/Kinshasa","Africa/Lubumbashi"]},CF:{name:"Central African Republic",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Central African Republic",locales:["fr-CF"],compliance:[],timezones:["Africa/Bangui"]},CG:{name:"Republic of Congo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Republic of Congo",locales:["fr-CG"],compliance:[],timezones:["Africa/Brazzaville"]},TD:{name:"Chad",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Chad",locales:["fr-TD","ar-TD"],compliance:[],timezones:["Africa/Ndjamena"]},BY:{name:"Belarus",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Belarus",locales:["be-BY","ru-BY"],compliance:[],timezones:["Europe/Minsk"]},MD:{name:"Moldova",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Moldova",locales:["ro-MD"],compliance:[],timezones:["Europe/Chisinau"]},RU:{name:"Russia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Russia",locales:["ru-RU"],compliance:[],timezones:["Europe/Kaliningrad","Europe/Moscow","Europe/Samara","Asia/Yekaterinburg","Asia/Omsk","Asia/Krasnoyarsk","Asia/Irkutsk","Asia/Yakutsk","Asia/Vladivostok","Asia/Magadan","Asia/Kamchatka"]},UA:{name:"Ukraine",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Ukraine",locales:["uk-UA"],compliance:[],timezones:["Europe/Kyiv"]},VA:{name:"Holy See",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Holy See",locales:["it-VA"],compliance:[],timezones:["Europe/Vatican"]},AU:{name:"Australia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Australia (Privacy Act)",locales:["en"],compliance:["privacy-au"],timezones:["Australia/Sydney","Australia/Brisbane","Australia/Adelaide","Australia/Darwin","Australia/Perth","Australia/Hobart"]},FJ:{name:"Fiji",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Fiji",locales:["en"],compliance:["privacy-fj"],timezones:["Pacific/Fiji"]},FM:{name:"Micronesia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Micronesia",locales:["en"],compliance:[],timezones:["Pacific/Chuuk","Pacific/Pohnpei","Pacific/Kosrae"]},KI:{name:"Kiribati",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kiribati",locales:["en"],compliance:[],timezones:["Pacific/Tarawa","Pacific/Enderbury","Pacific/Kiritimati"]},MH:{name:"Marshall Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Marshall Islands",locales:["en"],compliance:[],timezones:["Pacific/Majuro","Pacific/Kwajalein"]},MP:{name:"Northern Mariana Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Northern Mariana Islands",locales:["en"],compliance:[],timezones:["Pacific/Saipan"]},NC:{name:"New Caledonia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"New Caledonia",locales:["fr-NC"],compliance:[],timezones:["Pacific/Noumea"]},NF:{name:"Norfolk Island",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Norfolk Island",locales:["en"],compliance:[],timezones:["Pacific/Norfolk"]},NR:{name:"Nauru",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nauru",locales:["en"],compliance:[],timezones:["Pacific/Nauru"]},NU:{name:"Niue",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Niue",locales:["en"],compliance:[],timezones:["Pacific/Niue"]},NZ:{name:"New Zealand",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"New Zealand (Privacy Act)",locales:["en"],compliance:["privacy-nz"],timezones:["Pacific/Auckland","Pacific/Chatham"]},PF:{name:"French Polynesia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"French Polynesia",locales:["fr-PF"],compliance:[],timezones:["Pacific/Tahiti","Pacific/Marquesas","Pacific/Gambier"]},PG:{name:"Papua New Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Papua New Guinea",locales:["en"],compliance:["privacy-pg"],timezones:["Pacific/Port_Moresby","Pacific/Bougainville"]},PW:{name:"Palau",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Palau",locales:["en"],compliance:[],timezones:["Pacific/Palau"]},SB:{name:"Solomon Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Solomon Islands",locales:["en"],compliance:[],timezones:["Pacific/Guadalcanal"]},TO:{name:"Tonga",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tonga",locales:["en"],compliance:[],timezones:["Pacific/Tongatapu"]},TV:{name:"Tuvalu",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tuvalu",locales:["en"],compliance:[],timezones:["Pacific/Funafuti"]},VU:{name:"Vanuatu",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Vanuatu",locales:["fr-VU","en"],compliance:[],timezones:["Pacific/Efate"]},WS:{name:"Samoa",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Samoa",locales:["en"],compliance:[],timezones:["Pacific/Apia"]},UK:{name:"United Kingdom",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"United Kingdom (UK GDPR + PECR)",locales:["en"],compliance:["uk-gdpr","pecr"],timezones:["Europe/London"]},CH:{name:"Switzerland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Switzerland (revFADP)",locales:["de-CH","fr-CH","it-CH"],compliance:["revfadp"],timezones:["Europe/Zurich"]}}},Yo=Object.entries(R.countries).reduce(function(n,[e,t]){return n[e]=t.name,n},{}),Jo=Object.values(R.countries).reduce(function(n,e){return e.locales.forEach(t=>{n[t]=e.name}),n},{});var Q="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function io(n){return new TextEncoder().encode(n)}function ao(n){let e="";for(let t=0;t<n.length;t+=3){let o=n[t]??0,i=t+1<n.length?n[t+1]??0:0,a=t+2<n.length?n[t+2]??0:0;e+=Q[o>>2],e+=Q[(o&3)<<4|i>>4],t+1<n.length&&(e+=Q[(i&15)<<2|a>>6]),t+2<n.length&&(e+=Q[a&63])}return e}function nt(n){let e={v:2,ts:Math.floor(Date.now()/100),cmpId:n.cmpId,cmpV:n.cmpVersion,cs:n.consentScreen,lang:n.consentLanguage.toUpperCase().slice(0,2),vlV:n.vendorListVersion,pc:n.purposeConsents,vc:n.vendorConsents};return ao(io(JSON.stringify(e)))}var ro=["ar","he","fa","ur","ps","sd","ug","yi"];function ot(n,e){if(e==="ltr"||e==="rtl")return e;let t=n.slice(0,2).toLowerCase();return ro.includes(t)?"rtl":"ltr"}Ve();var p=()=>typeof window<"u"&&typeof document<"u",F=()=>p()?window:null;var hn=()=>p()&&typeof navigator<"u"?navigator:null;var U=["error"];function je(n){U=n}var P={info:(...n)=>{U.includes("info")&&console.info("[Consenti]",...n)},log:(...n)=>{U.includes("log")&&console.log("[Consenti]",...n)},warn:(...n)=>{U.includes("warning")&&console.warn("[Consenti]",...n)},error:(...n)=>{U.includes("error")&&console.error("[Consenti]",...n)}};function B(n){let e=document.createElement("script");if(n.src){let t=n.src.trim();if(/^javascript:/i.test(t))return P.warn(`${n.warnPrefix}: rejected src with javascript: protocol`),null;e.src=t}n.unsafeInnerHTML&&(e.innerHTML=n.unsafeInnerHTML);for(let[t,o]of Object.entries(n.attributes??{})){if(/^on/i.test(t)){P.warn(`${n.warnPrefix}: rejected attribute "${t}" (inline event handlers are not allowed)`);continue}e.setAttribute(t,o)}return document.head.appendChild(e),e}function se(n){n?.remove()}var N=class{constructor(e){this.options=e;this.scriptEl=null;this.handler=()=>this.evaluate(),p()&&(e.bind!==!1&&window.addEventListener("consenti:consentSubmitted",this.handler),this.evaluate())}evaluate(){let t=this.options.widget.getConsent()?.[this.options.cookieId]==="granted";t&&!this.scriptEl?this.inject():!t&&this.scriptEl&&this.revoke()}inject(){let e=B({...this.options.src!==void 0?{src:this.options.src}:{},...this.options.unsafeInnerHTML!==void 0?{unsafeInnerHTML:this.options.unsafeInnerHTML}:{},...this.options.attributes!==void 0?{attributes:this.options.attributes}:{},warnPrefix:"ConsentScript"});e&&(this.scriptEl=e,this.options.onLoad?.())}revoke(){se(this.scriptEl),this.scriptEl=null,this.options.onRevoke?.()}destroy(){p()&&(this.options.bind!==!1&&window.removeEventListener("consenti:consentSubmitted",this.handler),this.revoke())}};var O=class{constructor(e){this.options=e;this.scriptEl=null;this.handler=()=>this.evaluate(),p()&&(e.bind!==!1&&window.addEventListener("consenti:consentSubmitted",this.handler),this.evaluate())}evaluate(){let t=this.options.widget.getProfile()?.preferenceModal.categories[this.options.categoryId]?.cookies??[],o=this.options.widget.getConsent(),i=t.length>0&&t.every(a=>o?.[a]==="granted");i&&!this.scriptEl?this.inject():!i&&this.scriptEl&&this.revoke()}inject(){let e=B({...this.options.src!==void 0?{src:this.options.src}:{},...this.options.unsafeInnerHTML!==void 0?{unsafeInnerHTML:this.options.unsafeInnerHTML}:{},...this.options.attributes!==void 0?{attributes:this.options.attributes}:{},warnPrefix:"CategoryScript"});e&&(this.scriptEl=e,this.options.onLoad?.())}revoke(){se(this.scriptEl),this.scriptEl=null,this.options.onRevoke?.()}destroy(){p()&&(this.options.bind!==!1&&window.removeEventListener("consenti:consentSubmitted",this.handler),this.revoke())}};var yn="data-consenti-consent-script",vn="data-consenti-category-script",lo="data-consenti-bind",He="data-consenti-scanned";function po(n){return n.getAttribute(lo)!=="false"}function ce(n){if(!p())return[];let e=document.querySelectorAll(`script[type="text/plain"][${yn}]:not([${He}]), script[type="text/plain"][${vn}]:not([${He}])`),t=[];for(let o of e){o.setAttribute(He,"");let i=o.getAttribute("src")??void 0,a=i?void 0:o.textContent?.trim()||void 0,r=po(o),c=o.getAttribute(yn),s=o.getAttribute(vn);c?t.push(new N({cookieId:c,widget:n,...i!==void 0?{src:i}:{},...a!==void 0?{unsafeInnerHTML:a}:{},bind:r})):s&&t.push(new O({categoryId:s,widget:n,...i!==void 0?{src:i}:{},...a!==void 0?{unsafeInnerHTML:a}:{},bind:r}))}return t}function x(n,e,t){let o="denied";for(let[i,a]of Object.entries(e)){if(a.purpose!==t)continue;let r=n[i];if(r==="granted")return"granted";r==="objected"&&o==="denied"&&(o="objected")}return o}var uo=["ad_storage","analytics_storage","ad_user_data","ad_personalization","functionality_storage","personalization_storage","security_storage"];function q(n){let e={};for(let t of uo){let o=n[t];o==="granted"?e[t]="granted":o==="denied"||o==="objected"?e[t]="denied":e[t]=t==="functionality_storage"||t==="security_storage"?"granted":"denied"}return e.ads_data_redaction=e.ad_storage==="denied"?"true":"false",e.url_passthrough="false",e}function bn(n,e){return{necessary:"granted",functional:x(n,e,"functional"),preferences:x(n,e,"preferences"),analytics:x(n,e,"analytics"),marketing:x(n,e,"marketing")}}function Cn(n,e){return{analytics:x(n,e,"analytics"),target:x(n,e,"preferences"),manager:x(n,e,"marketing"),optimizer:x(n,e,"marketing")}}function kn(n,e){return{pixel:x(n,e,"marketing"),api:x(n,e,"marketing"),plugins:x(n,e,"functional"),facebookLogin:x(n,e,"functional")}}function Pn(n,e){return{session:x(n,e,"analytics"),heatmaps:x(n,e,"analytics"),performance:x(n,e,"analytics")}}function _n(n,e){return{identify:x(n,e,"preferences"),page:x(n,e,"analytics"),track:x(n,e,"analytics"),group:x(n,e,"analytics"),alias:x(n,e,"analytics")}}var Fe='.consenti-root{position:relative}.consenti-d-none{display:none !important}:root{--consenti-color-bg: #ffffff;--consenti-color-text: #1a2e4a;--consenti-color-text-muted: #949dab;--consenti-color-primary: #04111f;--consenti-color-primary-text: #ffffff;--consenti-color-secondary: #f0f4f8;--consenti-color-secondary-text: #1a2e4a;--consenti-color-border: #dbe4ee;--consenti-color-secondary-border: #1a2e4a;--consenti-color-overlay: #04111f;--consenti-color-accent: #d32f2f;--consenti-color-accent-text: #ffffff;--consenti-font-family: system-ui, -apple-system, sans-serif;--consenti-font-size-base: 14px;--consenti-font-size-heading: 16px;--consenti-font-weight-heading: 600;--consenti-line-height: 1.5;--consenti-spacing-xs: 5px;--consenti-spacing-sm: 8px;--consenti-spacing-md: 16px;--consenti-spacing-lg: 24px;--consenti-border-radius: 8px;--consenti-border-radius-btn: 0;--consenti-shadow: 0 4px 24px rgba(21, 101, 192, 0.14);--consenti-toggle-bg-on: #43a047;--consenti-toggle-bg-partial: #97c098;--consenti-toggle-bg-off: #9ca3af;--consenti-toggle-knob: #ffffff;--consenti-toggle-width: 52px;--consenti-toggle-height: 28px;--consenti-z-banner: 9999;--consenti-z-overlay: 9998;--consenti-z-modal: 10000}.consenti-root--dark{--consenti-color-bg: #1e2535;--consenti-color-text: #e2e8f0;--consenti-color-text-muted: #a4acb9;--consenti-color-primary: #e2e8f0;--consenti-color-primary-text: #2a3447;--consenti-color-secondary: #2a3447;--consenti-color-secondary-text: #cbd5e1;--consenti-color-border: #374151;--consenti-color-overlay: rgba(0, 0, 0, 0.65);--consenti-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);--consenti-toggle-bg-off: #6b7280}.consenti-overlay{position:fixed;inset:0;background:var(--consenti-color-overlay);z-index:var(--consenti-z-overlay)}.consenti-btn{display:inline-flex;align-items:center;justify-content:center;padding:var(--consenti-spacing-sm) var(--consenti-spacing-md);border:none;border-radius:var(--consenti-border-radius-btn);font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);font-weight:500;line-height:1;cursor:pointer;text-decoration:none;transition:opacity .15s ease}.consenti-btn:focus-visible{outline:2px solid var(--consenti-color-primary);outline-offset:2px}.consenti-btn:hover{opacity:.9}.consenti-btn--primary{background:var(--consenti-color-primary);color:var(--consenti-color-primary-text);border:1px solid var(--consenti-color-primary)}.consenti-btn--secondary{background:var(--consenti-color-secondary);color:var(--consenti-color-primary);border:1px solid var(--consenti-color-primary)}.consenti-btn--secondary:hover{background:var(--consenti-color-primary);color:var(--consenti-color-secondary)}.consenti-btn--text{background:rgba(0,0,0,0);color:var(--consenti-color-primary);padding-left:0;padding-right:0;text-decoration:underline;text-underline-offset:4px;border:1px solid rgba(0,0,0,0)}.consenti-btn--accent{background:var(--consenti-color-accent);color:var(--consenti-color-accent-text)}.consenti-btn--action{background:rgba(0,0,0,0);color:var(--consenti-color-text);font-size:20px;line-height:1;border-radius:50%;height:24px;width:24px;font-size:24px;padding:0}.consenti-banner{position:fixed;left:0;right:0;z-index:var(--consenti-z-banner);background:var(--consenti-color-bg);color:var(--consenti-color-text);font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);line-height:var(--consenti-line-height);box-shadow:var(--consenti-shadow);padding:var(--consenti-spacing-lg);display:flex;flex-wrap:wrap;align-items:center;gap:var(--consenti-spacing-md)}.consenti-banner--top{top:0;border-bottom:1px solid var(--consenti-color-border)}@media(prefers-reduced-motion: no-preference){.consenti-banner--top{animation:consenti-slide-down .2s ease-out}}.consenti-banner--bottom{bottom:0;border-top:1px solid var(--consenti-color-border)}@media(prefers-reduced-motion: no-preference){.consenti-banner--bottom{animation:consenti-slide-up .2s ease-out}}.consenti-banner--top .consenti-banner__text-container,.consenti-banner--bottom .consenti-banner__text-container{min-width:60vw}.consenti-banner--middle{top:50%;transform:translateY(-50%);left:50%;right:auto;transform:translate(-50%, -50%);width:min(600px,90vw);border-radius:var(--consenti-border-radius);flex-direction:column;align-items:flex-start}.consenti-banner--left-bottom{bottom:var(--consenti-spacing-lg);left:var(--consenti-spacing-lg);right:auto;width:min(400px,90vw);border-radius:var(--consenti-border-radius)}.consenti-banner--right-bottom{bottom:var(--consenti-spacing-lg);right:var(--consenti-spacing-lg);left:auto;width:min(400px,90vw);border-radius:var(--consenti-border-radius)}.consenti-banner__text-container{flex:1}.consenti-banner__text-container a:not(.consenti-banner__link){color:var(--consenti-color-text)}.consenti-banner__text-container a:not(.consenti-banner__link):hover{color:var(--consenti-color-primary)}.consenti-banner__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin:0 0 var(--consenti-spacing-sm);width:calc(100% - 56px)}.consenti-banner__text{margin:0}.consenti-banner__links{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);margin-top:var(--consenti-spacing-sm)}.consenti-banner__link{font-size:.87em;padding:var(--consenti-spacing-xs) var(--consenti-spacing-sm);border-radius:var(--consenti-spacing-xs)}.consenti-banner__controls{position:absolute;top:var(--consenti-spacing-sm);right:var(--consenti-spacing-sm);display:flex;align-items:center;gap:4px}.consenti-banner__buttons{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);align-items:center;margin-top:var(--consenti-spacing-sm)}.consenti-banner__close{margin-top:-5px}.consenti-banner .consenti__powered-by{bottom:0}@media(max-width: 576px){.consenti-banner{padding:var(--consenti-spacing-md);gap:var(--consenti-spacing-sm)}.consenti-banner--left-bottom,.consenti-banner--right-bottom{left:0;right:0;bottom:0;width:100%;border-radius:0;border-top:1px solid var(--consenti-color-border)}.consenti-banner--middle{width:95vw}.consenti-banner__buttons{width:100%;flex-direction:column;align-items:stretch}.consenti-banner__text-container{min-width:0;width:100%}}@keyframes consenti-slide-up{from{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes consenti-slide-down{from{transform:translateY(-100%)}to{transform:translateY(0)}}.consenti-modal{position:fixed;inset:0;z-index:var(--consenti-z-modal);display:flex;font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);color:var(--consenti-color-text);line-height:var(--consenti-line-height)}.consenti-modal--passthrough{pointer-events:none}.consenti-modal--passthrough .consenti-modal__container{pointer-events:auto}.consenti-modal--center{align-items:center;justify-content:center}.consenti-modal--left{align-items:stretch;justify-content:flex-start}.consenti-modal--left .consenti-modal__container{border-radius:0 var(--consenti-border-radius) var(--consenti-border-radius) 0;height:100%;max-height:100vh}.consenti-modal--right{align-items:stretch;justify-content:flex-end}.consenti-modal--right .consenti-modal__container{border-radius:0;height:100%;max-height:100vh}.consenti-modal--fullscreen{align-items:flex-start;justify-content:flex-start}.consenti-modal--fullscreen .consenti-modal__container{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;margin:0}.consenti-modal__overlay{position:absolute;inset:0;background:var(--consenti-color-overlay)}.consenti-modal__container{position:relative;z-index:1;background:var(--consenti-color-bg);border-radius:var(--consenti-border-radius);box-shadow:var(--consenti-shadow);width:min(560px,90vw);max-height:85vh;display:flex;flex-direction:column;overflow:hidden}@media(prefers-reduced-motion: no-preference){.consenti-modal__container{animation:consenti-fade-in .15s ease-out}}.consenti-modal__header{display:flex;justify-content:space-between;padding:var(--consenti-spacing-md) var(--consenti-spacing-lg);border-bottom:1px solid var(--consenti-color-border);flex-shrink:0;position:relative;flex-direction:column}.consenti-modal__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin:0;flex:1;width:calc(100% - 56px)}.consenti-modal__header-controls{display:flex;align-items:center;gap:6px;flex-shrink:0;position:absolute;inset-inline-end:15px;top:10px}.consenti-modal__close{flex-shrink:0;margin-top:-5px}.consenti-modal__links{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);margin-top:var(--consenti-spacing-md)}.consenti-modal__link{font-size:.87em;padding:var(--consenti-spacing-xs) var(--consenti-spacing-sm);border-radius:var(--consenti-spacing-xs)}.consenti-modal__subheading{padding-top:var(--consenti-spacing-sm);margin:0;color:var(--consenti-color-text-muted);font-size:13px}.consenti-modal__text{padding:var(--consenti-spacing-sm) 0}.consenti-modal__body{overflow-y:auto;flex:1;padding:var(--consenti-spacing-sm) var(--consenti-spacing-lg);position:relative}.consenti-modal__categories{display:flex;flex-direction:column;gap:var(--consenti-spacing-md);padding:var(--consenti-spacing-md) 0}.consenti-modal__buttons{display:flex;flex-wrap:wrap;gap:var(--consenti-spacing-sm);padding:var(--consenti-spacing-md);border-top:1px solid var(--consenti-color-border);flex-shrink:0}.consenti-modal__receipt-option{padding-top:var(--consenti-spacing-md);border-top:1px solid var(--consenti-color-border);flex-shrink:0}.consenti-modal__receipt-label{display:flex;align-items:center;gap:var(--consenti-spacing-sm);font-size:var(--consenti-font-size-base);cursor:pointer}.consenti-modal__receipt-checkbox{width:16px;height:16px;flex-shrink:0;cursor:pointer;accent-color:var(--consenti-toggle-bg-on)}.consenti-modal__receipt-desc{margin:4px 0 0 0;margin-inline-start:24px;font-size:12px;color:#6b7280}@keyframes consenti-fade-in{from{opacity:0;transform:scale(0.97)}to{opacity:1;transform:scale(1)}}.consenti-category{padding:var(--consenti-spacing-md) 0;border-bottom:1px solid var(--consenti-color-border)}.consenti-category:last-child{border-bottom:none}.consenti-category--mandatory .consenti-category__toggle{opacity:.6;cursor:default}.consenti-category__header{display:flex;align-items:center;justify-content:space-between;gap:var(--consenti-spacing-md);margin-bottom:var(--consenti-spacing-sm)}.consenti-category__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin:0}.consenti-category__text{color:var(--consenti-color-text-muted);font-size:13px;margin:0}.consenti-category__text--clamped{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.consenti-category__text-wrap{display:flex;flex-direction:column;align-items:flex-start;gap:4px}.consenti-category__show-more{background:none;border:none;padding:0;color:var(--consenti-color-primary);cursor:pointer;font-size:12px;text-decoration:underline;text-underline-offset:2px}.consenti-category__show-more:hover{opacity:.8}.consenti-category__li-desc{margin-bottom:var(--consenti-spacing-sm);font-size:12px;color:#6b7280;font-style:italic}.consenti-category__toggle{flex-shrink:0;position:relative;width:var(--consenti-toggle-width);height:var(--consenti-toggle-height);border-radius:calc(var(--consenti-toggle-height)/2);background:var(--consenti-toggle-bg-off);border:none;cursor:pointer;transition:background .2s ease;padding:0}.consenti-category__toggle:focus-visible{outline:2px solid var(--consenti-color-primary);outline-offset:2px}.consenti-category__toggle[aria-checked=true]{background:var(--consenti-toggle-bg-on)}.consenti-category__toggle--mandatory{cursor:default}.consenti-category__toggle--partial{background:var(--consenti-toggle-bg-partial, var(--consenti-color-accent, #f59e0b))}.consenti-category__toggle--partial .consenti-category__toggle-icon--check,.consenti-category__toggle--partial .consenti-category__toggle-icon--cross,.consenti-category__toggle--partial .consenti-category__toggle-icon--objected{opacity:0}.consenti-category__toggle--partial.consenti-toggle--li .consenti-category__toggle-icon--objected{opacity:0}.consenti-category__toggle--partial .consenti-category__toggle-knob{transform:translateX(calc((var(--consenti-toggle-width) - var(--consenti-toggle-height)) / 2))}.consenti-category__toggle--partial::after{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);width:8px;height:2px;border-radius:1px;background:hsla(0,0%,100%,.9);pointer-events:none;z-index:1}.consenti-category__toggle-icon{position:absolute;top:50%;transform:translateY(-50%);width:10px;height:10px;display:flex;align-items:center;justify-content:center;pointer-events:none;transition:opacity .15s ease;color:hsla(0,0%,100%,.9)}.consenti-category__toggle-icon svg{width:10px;height:10px;overflow:visible}.consenti-category__toggle-icon--check{left:8px;opacity:0}[aria-checked=true] .consenti-category__toggle-icon--check{opacity:1}.consenti-category__toggle-icon--cross{right:8px;opacity:1}[aria-checked=true] .consenti-category__toggle-icon--cross{opacity:0}.consenti-category__toggle-icon--objected{right:8px;opacity:0}.consenti-category__toggle-knob{position:absolute;top:2px;left:2px;width:calc(var(--consenti-toggle-height) - 4px);height:calc(var(--consenti-toggle-height) - 4px);border-radius:50%;background:var(--consenti-toggle-knob);transition:transform .2s ease;display:block}[aria-checked=true] .consenti-category__toggle-knob{transform:translateX(calc(var(--consenti-toggle-width) - var(--consenti-toggle-height)))}.consenti-category__params{display:flex;flex-direction:column;gap:var(--consenti-spacing-xs, 6px);margin-top:var(--consenti-spacing-sm);padding-top:var(--consenti-spacing-sm);border-top:1px dashed var(--consenti-color-border)}.consenti-category__param{display:flex;align-items:center;justify-content:space-between;gap:var(--consenti-spacing-sm)}.consenti-category__param-info{display:flex;flex-direction:column;gap:2px;min-width:0}.consenti-category__param-label{font-size:12px;font-family:var(--consenti-font-family-mono, monospace);color:var(--consenti-color-text);overflow-wrap:anywhere}.consenti-category__param-meta{font-size:11px;color:var(--consenti-color-text-muted)}.consenti-category__param-toggle{flex-shrink:0;position:relative;width:calc(var(--consenti-toggle-width)*.8);height:calc(var(--consenti-toggle-height)*.8);border-radius:calc(var(--consenti-toggle-height)*.4);background:var(--consenti-toggle-bg-off);border:none;cursor:pointer;transition:background .2s ease;padding:0}.consenti-category__param-toggle:focus-visible{outline:2px solid var(--consenti-color-primary);outline-offset:2px}.consenti-category__param-toggle[aria-checked=true]{background:var(--consenti-toggle-bg-on)}.consenti-category__param-toggle--mandatory{cursor:default;opacity:.6}.consenti-category__param-toggle .consenti-category__toggle-icon{width:8px;height:8px}.consenti-category__param-toggle .consenti-category__toggle-icon svg{width:8px;height:8px}.consenti-category__param-toggle .consenti-category__toggle-icon--check{left:6px}.consenti-category__param-toggle .consenti-category__toggle-icon--cross{right:6px}.consenti-category__param-toggle .consenti-category__toggle-icon--objected{right:6px}.consenti-category__param-toggle .consenti-category__toggle-knob{width:calc(var(--consenti-toggle-height)*.8 - 4px);height:calc(var(--consenti-toggle-height)*.8 - 4px)}.consenti-category__param-toggle[aria-checked=true] .consenti-category__toggle-knob{transform:translateX(calc(var(--consenti-toggle-width) * 0.8 - var(--consenti-toggle-height) * 0.8))}.consenti-toggle--li .consenti-category__toggle-icon--cross{opacity:0}.consenti-toggle--li .consenti-category__toggle-icon--objected{opacity:1}.consenti-toggle--li[aria-checked=true] .consenti-category__toggle-icon--objected{opacity:0}[dir=rtl] .consenti-category__toggle-knob{left:auto;right:2px}[dir=rtl] .consenti-category__toggle[aria-checked=true] .consenti-category__toggle-knob{transform:translateX(calc(-1 * (var(--consenti-toggle-width) - var(--consenti-toggle-height))))}[dir=rtl] .consenti-category__toggle--partial .consenti-category__toggle-knob{transform:translateX(calc(-1 * (var(--consenti-toggle-width) - var(--consenti-toggle-height)) / 2))}[dir=rtl] .consenti-category__param-toggle[aria-checked=true] .consenti-category__toggle-knob{transform:translateX(calc(-1 * (var(--consenti-toggle-width) * 0.8 - var(--consenti-toggle-height) * 0.8)))}[dir=rtl] .consenti-category__toggle-icon--check{left:auto;right:8px}[dir=rtl] .consenti-category__toggle-icon--cross,[dir=rtl] .consenti-category__toggle-icon--objected{right:auto;left:8px}[dir=rtl] .consenti-category__param-toggle .consenti-category__toggle-icon--check{left:auto;right:6px}[dir=rtl] .consenti-category__param-toggle .consenti-category__toggle-icon--cross,[dir=rtl] .consenti-category__param-toggle .consenti-category__toggle-icon--objected{right:auto;left:6px}.consenti-locale-switcher{position:relative;display:inline-flex}.consenti-locale-switcher__btn{font-size:1rem;line-height:1;cursor:pointer}.consenti-locale-switcher__list{position:absolute;top:calc(100% + 4px);inset-inline-end:0;z-index:calc(var(--consenti-z-modal) + 1);background:var(--consenti-color-bg);border:1px solid var(--consenti-color-border);border-radius:var(--consenti-border-radius);box-shadow:var(--consenti-shadow);list-style:none;margin:0;padding:4px 0;min-width:80px}.consenti-locale-switcher__list li{display:block}.consenti-locale-switcher__option{display:block;width:100%;padding:6px 12px;text-align:start;font-size:var(--consenti-font-size-base);color:var(--consenti-color-text);background:none;border:none;cursor:pointer}.consenti-locale-switcher__option:hover{background:var(--consenti-color-secondary)}.consenti-locale-switcher__option--active{font-weight:600;color:var(--consenti-color-primary)}.consenti-locale-switcher--modal .consenti-locale-switcher__list{inset-inline-end:0}.consenti-meta-footer{display:flex;flex-wrap:wrap;gap:.75rem;font-size:.7rem;color:var(--consenti-color-text);opacity:.6;border-top:1px solid var(--consenti-color-border);padding-top:.5rem;margin-top:.75rem}.consenti-meta-footer__item{display:inline-flex;align-items:center;gap:.25rem}.consenti-meta-footer__id{font-family:monospace;font-size:.65rem}.consenti-meta-footer__settings{background:none;border:none;padding:0;color:var(--consenti-color-primary);cursor:pointer;font-size:.7rem;text-decoration:underline;text-underline-offset:2px}.consenti-meta-footer__settings:hover{opacity:.8}.consenti--enhanced-a11y .consenti-btn{min-height:44px;min-width:44px}.consenti--enhanced-a11y .consenti-category__toggle{min-width:52px;min-height:28px}.consenti--enhanced-a11y .consenti-category__param-toggle{min-width:44px;min-height:24px}.consenti--enhanced-a11y *:focus-visible{outline:3px solid var(--consenti-color-primary);outline-offset:2px}.consenti-age-gate{position:fixed;inset:0;z-index:var(--consenti-z-modal);margin:auto;width:min(400px,90vw);height:fit-content;background:var(--consenti-color-bg);color:var(--consenti-color-text);border-radius:var(--consenti-border-radius);box-shadow:var(--consenti-shadow);padding:var(--consenti-spacing-lg);font-family:var(--consenti-font-family);font-size:var(--consenti-font-size-base);line-height:var(--consenti-line-height)}.consenti-age-gate__heading{font-size:var(--consenti-font-size-heading);font-weight:var(--consenti-font-weight-heading);margin-bottom:var(--consenti-spacing-sm)}.consenti-age-gate__text{color:var(--consenti-color-text-muted);margin-bottom:var(--consenti-spacing-md)}.consenti-age-gate__buttons{display:flex;gap:var(--consenti-spacing-sm)}.consenti__powered-by{position:absolute;inset-inline-end:var(--consenti-spacing-md);opacity:.3;color:var(--consenti-color-primary);font-size:70%}.consenti-transition-1_2x{transition:transform 300ms ease-in-out}.consenti-transition-1_2x:hover{transform:scale(1.2)}';var le=class{constructor(){this.channel=null}get isSupported(){return p()&&typeof BroadcastChannel<"u"}connect(e){this.isSupported&&(this.onMessageCallback=e,this.channel=new BroadcastChannel("consenti"),this.channel.onmessage=t=>{t.data?.type&&e(t.data)},this.channel.onmessageerror=()=>{P.warn("BroadcastChannel message error \u2014 ignoring")})}send(e){this.channel?.postMessage(e)}disconnect(){this.channel?.close(),this.channel=null,this.onMessageCallback=void 0}};function xn(n){let e={version:n.version,issuedAt:new Date().toISOString(),visitorId:n.visitorId,profileId:n.profileId,locale:n.locale,consent:n.consent};return n.signature&&(e.signature=n.signature),e}function wn(n){if(typeof window>"u"||typeof document>"u")return;let e=JSON.stringify(n,null,2),t=new Blob([e],{type:"application/json"}),o=URL.createObjectURL(t),i=document.createElement("a");i.href=o,i.download=`consenti-receipt-${n.issuedAt.slice(0,10)}.json`,i.style.display="none",document.body.appendChild(i),i.click(),document.body.removeChild(i),setTimeout(()=>URL.revokeObjectURL(o),1e3)}function S(n){return`${n}_${crypto.randomUUID().replace(/-/g,"")}`}var An="consenti_config";function mo(){if(!p())return{};try{let n=localStorage.getItem(An);return n?JSON.parse(n):{}}catch{return{}}}function go(n){if(p())try{localStorage.setItem(An,JSON.stringify(n))}catch{}}function Tn(){let n=mo();if(n.visitorId)return n.visitorId;let e=S("visi");return go({...n,visitorId:e}),e}function En(n){if(!p())return null;let e=document.cookie.match(new RegExp(`(?:^|;\\s*)${fo(n)}=([^;]*)`));return e?decodeURIComponent(e[1]??""):null}function Ue(n,e,t={}){if(!p())return;let o=t.secure??(typeof window<"u"&&typeof window.location<"u"&&window.location.protocol==="https:"),i=[`${encodeURIComponent(n)}=${encodeURIComponent(e)}`,`Path=${t.path??"/"}`,`SameSite=${t.sameSite??"Lax"}`,t.maxAge!=null?`Max-Age=${t.maxAge}`:"",o?"Secure":"",t.domain?`Domain=${t.domain}`:""];document.cookie=i.filter(Boolean).join("; ")}function Gn(n,e={}){Ue(n,"",{...e,maxAge:0})}function fo(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ho(n){if(typeof n!="object"||n===null)return!1;let e=n;return typeof e.s=="string"&&typeof e.v=="number"&&typeof e.i=="string"&&typeof e.u=="string"&&typeof e.t=="number"&&(e.g===0||e.g===1)&&typeof e.p=="number"&&typeof e.c=="object"&&e.c!==null&&typeof e.l=="string"}function pe(n){return JSON.stringify(n)}function V(n){let e=n.lastIndexOf("::sig:"),t=e!==-1?n.slice(0,e):n;try{let o=JSON.parse(t);return ho(o)?o:null}catch{return null}}function qe(n){let e={};for(let[t,o]of Object.entries(n.c))o==="g"?e[t]="granted":o==="o"?e[t]="objected":e[t]="denied";return e}function de(n){let e={};for(let[t,o]of Object.entries(n))o==="granted"?e[t]="g":o==="objected"?e[t]="o":e[t]="d";return e}var W=class{constructor(e){this.mode=e;e==="localStorage"&&p()&&typeof localStorage>"u"&&(P.warn("localStorage is not available, falling back to cookie storage"),this.mode="cookie")}read(e){return p()?this.mode==="localStorage"?localStorage.getItem(e):En(e):null}write(e,t,o={}){p()&&(this.mode==="localStorage"?localStorage.setItem(e,t):Ue(e,t,o))}remove(e,t={}){p()&&(this.mode==="localStorage"?localStorage.removeItem(e):Gn(e,t))}};function bo(n){return n*24*60*60}var I="consenti_data";function In(n="cookie"){let t=new W(n).read(I);return t&&V(t)?.l||null}var $e="consenti";function Co(n){let e=n.split("::");if(e.length<2)return null;let t=e[0]??"",o;if(t.startsWith("t:")){let s=t.slice(2),l=parseInt(s,10);if(!s||isNaN(l))return null;o=new Date(l*1e3).toISOString()}else if(t.startsWith("ConsentTimestamp:")){if(o=t.replace("ConsentTimestamp:",""),!o)return null}else return null;let i=e[1]??"",a=e[2],r={};for(let s of i.split("|")){let l=s.indexOf(":");if(l===-1)return null;let m=s.slice(0,l),d=s.slice(l+1);if(!m||d!=="granted"&&d!=="denied"&&d!=="objected")return null;r[m]=d}let c={timestamp:o,consent:r};return a?.startsWith("sig:")&&(c.signature=a.slice(4)),c}var ue=class{constructor(e,t,o,i){this.profileId=e;this.storageMode=t;this.cookieDomains=o;this.appUserId=i;this.cachedData=null;this.expiryDays=365;this.profileVersion=0;this.storage=new W(t)}setProfileExpiry(e){this.expiryDays=e}setProfileVersion(e){this.profileVersion=e}get cookieName(){return I}read(){let e=this.storage.read(I);if(e){let o=V(e);if(o)return this.cachedData=o,this.toParseConsent(o)}let t=this.migrateLegacyCookie();return t?(this.cachedData=t,this.toParseConsent(t)):null}async readAndVerify(e){let t=this.storage.read(I);if(!t){let s=this.migrateLegacyCookie();return s?(this.cachedData=s,this.toParseConsent(s)):null}let o=t.lastIndexOf("::sig:"),i=o!==-1?t.slice(0,o):t,a=o!==-1?t.slice(o+6):void 0,r=V(t);if(!r)return null;if(a){let{verifyValue:s}=await Promise.resolve().then(()=>(Ke(),We));if(!await s(i,a,e))return P.warn("Cookie signature mismatch \u2014 consent cleared and banner will re-appear"),this.delete(),null}this.cachedData=r;let c=this.toParseConsent(r);return a?{...c,signature:a}:c}write(e,t={},o){let i=this.buildCookieData(e,t),a=pe(i);o&&(a=`${a}::sig:${o}`),this.storage.write(I,a,this.buildCookieOpts()),this.cachedData=i}async writeAndSign(e,t,o={}){let{signValue:i}=await Promise.resolve().then(()=>(Ke(),We)),a=this.buildCookieData(e,o),r=pe(a),c=await i(r,t);return this.storage.write(I,`${r}::sig:${c}`,this.buildCookieOpts()),this.cachedData=a,c}delete(){let e=this.buildCookieOpts();this.storage.remove(I,e),this.deleteLegacyCookies(),this.cachedData=null}hasConsent(){return this.cachedData?!0:this.read()!==null}getConsent(){return this.cachedData?qe(this.cachedData):this.read()?.consent??null}getConsentDate(){if(this.cachedData)return new Date(this.cachedData.t*1e3);let e=this.read();return e?new Date(e.timestamp):!1}getConsentId(){if(this.cachedData)return this.cachedData.i;let e=this.storage.read(I);return e?V(e)?.i??null:null}getConsentLocale(){if(this.cachedData)return this.cachedData.l||null;let e=this.storage.read(I);return e&&V(e)?.l||null}setInMemory(e){this.cachedData={s:this.profileId,v:this.profileVersion,i:this.cachedData?.i??S("cons"),t:Math.round(Date.now()/1e3),u:this.appUserId??"",g:0,p:0,c:de(e),l:this.cachedData?.l??""}}clearInMemory(){this.cachedData=null}toParseConsent(e){return{timestamp:new Date(e.t*1e3).toISOString(),consent:qe(e)}}buildCookieData(e,t={}){return{s:this.profileId,v:this.profileVersion,i:t.consentId??S("cons"),t:Math.round(Date.now()/1e3),u:this.appUserId??"",g:t.gpcDetected?1:0,p:t.source??0,c:de(e),l:t.locale??""}}migrateLegacyCookie(){if(typeof document>"u")return null;let e=`_${this.profileId}`,t=this.storageMode==="localStorage"?typeof localStorage<"u"?Object.keys(localStorage):[]:document.cookie.split(";").map(o=>o.split("=")[0]?.trim()??"");for(let o of t){if(!o.startsWith(`${$e}_`)||!o.endsWith(e))continue;let i=this.storage.read(o);if(!i)continue;let a=Co(i);if(!a)continue;let r=o.slice($e.length+1,o.length-e.length),c=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(r)?r:"",s={s:this.profileId,v:0,i:S("cons"),t:Math.round(new Date(a.timestamp).getTime()/1e3),u:c,g:0,p:0,c:de(a.consent),l:""};return this.storage.write(I,pe(s),this.buildCookieOpts()),this.storage.remove(o,this.buildCookieOpts()),P.info(`Migrated consent cookie from "${o}" to "${I}"`),s}return null}deleteLegacyCookies(){if(typeof document>"u"||this.storageMode==="localStorage")return;let e=`_${this.profileId}`,t=this.buildCookieOpts();for(let o of document.cookie.split(";")){let i=o.split("=")[0]?.trim()??"";i.startsWith(`${$e}_`)&&i.endsWith(e)&&this.storage.remove(i,t)}}buildCookieOpts(){let e={path:"/",sameSite:"Lax",maxAge:bo(this.expiryDays)};if(this.cookieDomains){let t=this.cookieDomains.split(",")[0]?.trim();t&&(e.domain=t)}return e}};var me=class{constructor(e,t){this.profileId=e;this.gtmConfig=t;this.gtmConfig&&this.initConsentMode()}initConsentMode(){if(!p())return;let e=F();if(!e)return;let t=this.gtmConfig,o=t.dataLayer??"dataLayer";Array.isArray(e[o])||(e[o]=[]),typeof e.gtag!="function"&&(e.gtag=((...a)=>{e[o].push(a)}));let i=e.gtag;if(i("consent","default",q({})),t.containerId){let a=o!=="dataLayer"?`&l=${encodeURIComponent(o)}`:"";B({src:`https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(t.containerId)}${a}`,warnPrefix:"GTM"})}}dispatch(e,t){if(!p())return;let o=new CustomEvent(e,{detail:t,bubbles:!0});window.dispatchEvent(o),this.pushToGTM(e,t)}pushToGTM(e,t){let o=this.gtmConfig;if(!o)return;let i=F();if(!i)return;let a=o.dataLayer??"dataLayer",r=i[a];if(Array.isArray(r)&&(o.verbose&&(!o.events||o.events.length===0||o.events.includes(e))&&r.push({event:e,content:t}),e==="consenti:consentSubmitted")){let c=t.consentJson??{},s=typeof i.gtag=="function"?i.gtag:(...l)=>r.push(l);s("consent","update",q(c)),o.urlPassthrough&&s("set","url_passthrough",!0),o.adsDataRedaction&&s("set","ads_data_redaction",c.ad_storage!=="granted")}}};fe();function Mn(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function Je(n,e){if(e===void 0||e===null)return n;if(Array.isArray(n)&&Array.isArray(e)){let t=Math.max(n.length,e.length);return Array.from({length:t},(o,i)=>i>=e.length?n[i]:i>=n.length?e[i]:Je(n[i],e[i]))}if(Mn(n)&&Mn(e)){let t={...n};for(let o of Object.keys(e)){let i=e[o];if(i===null){delete t[o];continue}t[o]=Je(n[o],i)}return t}return e}function M(n,e){return Je(n,e)}function Dn(){return{tz:Intl.DateTimeFormat().resolvedOptions().timeZone,lang:navigator.language,langs:Array.from(navigator.languages)}}function Ln(n){let e=Intl.DateTimeFormat().resolvedOptions();return btoa(JSON.stringify({timezone:e.timeZone,languages:Array.from(navigator.languages??[]),language:navigator.language??"",locale:n??e.locale??navigator.language??""}))}function ko(n){return{purpose:n.purpose,...n.listenGpc?{listenGpc:!0}:{},...n.preGrant?{preGrant:!0}:{},...n.cpraCategory?{cpraCategory:n.cpraCategory}:{}}}function Po(n){let e={};for(let[t,o]of Object.entries(n))e[t]=ko(o);return e}function _o(n){return{text:n.text,style:n.style,action:n.action,...n.cookies!==void 0?{cookies:n.cookies}:{}}}function Rn(n){let e={};for(let[t,o]of Object.entries(n))e[t]=_o(o);return e}function xo(n){return{heading:n.heading,htmlText:n.htmlText,legalBasis:n.legalBasis,...n.legitimateInterestDescription!==void 0?{legitimateInterestDescription:n.legitimateInterestDescription}:{},cookies:n.cookies}}function wo(n){let e={};for(let[t,o]of Object.entries(n))e[t]=xo(o);return e}function zn(n){return{position:n.position,htmlText:n.htmlText,buttons:Rn(n.buttons),...n.heading?{heading:n.heading}:{},...n.showClose!==void 0?{showClose:n.showClose}:{},...n.showLocaleSwitcher!==void 0?{showLocaleSwitcher:n.showLocaleSwitcher}:{}}}function Ao(n){return{heading:n.heading,htmlText:n.htmlText??"",buttons:Rn(n.buttons),categories:wo(n.categories),...n.position?{position:n.position}:{},...n.subheading?{subheading:n.subheading}:{},...n.persistent!==void 0?{persistent:n.persistent}:{}}}function To(n,e,t){if(e){if(n[e])return n[e];let o=e.split("-")[0]??"",i=Object.keys(n).find(a=>a===o||a.startsWith(`${o}-`));if(i)return n[i]}return n[t]??Object.values(n)[0]}function Bn(n,e){let t=To(n.translations,e,n.defaultLocale);return{id:"0",defaultLocale:n.defaultLocale,locales:Object.keys(n.translations),cookies:Po(n.cookies),...n.expiryDays?{expiryDays:n.expiryDays}:{},mainBanner:zn(t.mainBanner),preferenceModal:Ao(t.preferenceModal),gpcMode:n.gpcMode,complianceGroup:n.complianceGroup,...t.gpcBanner?{gpcBanner:zn(t.gpcBanner)}:{}}}var tt=new Map;function Nn(n,e){tt.set(n,e)}function Eo(n){return tt.get(n)}function Go(n){for(let e of tt.values())if(e.complianceGroup===n)return e}function Qe(n){let e=n.gpcMode,t="ignore";return typeof e=="boolean"?t=e?"honor":"ignore":e&&(t=e),{id:n.id,...n.version!==void 0?{version:n.version}:{},defaultLocale:n.defaultLocale,locales:n.locales,cookies:n.cookies,mainBanner:n.mainBanner,allowReceipt:n.allowReceipt??!1,preferenceModal:n.preferenceModal,...n.expiryDays?{expiryDays:n.expiryDays}:{},...n.gpcBanner?{gpcBanner:n.gpcBanner}:{},...t?{gpcMode:t}:{},...n.darkMode!==void 0?{darkMode:n.darkMode}:{},...n.complianceGroup?{complianceGroup:n.complianceGroup}:{},...n.complianceConfig?{complianceConfig:n.complianceConfig}:{},...n.dpdpa?{dpdpa:n.dpdpa}:{},...n.hidePoweredBy!==void 0?{hidePoweredBy:n.hidePoweredBy}:{},...n.showFooterMetadata!==void 0?{showFooterMetadata:n.showFooterMetadata}:{},...n.enhanceAccessibility!==void 0?{enhanceAccessibility:n.enhanceAccessibility}:{}}}var On="__consenti_resolved_",So=3600*1e3;function Io(n,e,t){if(!t)return null;let o=`${On}${n}_${e}`;try{let i=sessionStorage.getItem(o);if(!i)return null;let a=JSON.parse(i);return Date.now()>a.expiresAt?(sessionStorage.removeItem(o),null):a}catch{return null}}function Mo(n,e,t,o){if(!t)return;let i=`${On}${n}_${e}`;try{sessionStorage.setItem(i,JSON.stringify({...o,expiresAt:Date.now()+So}))}catch{}}function Xe(n,e){if(e)return!0;let t=n.allowedOrigins;if(!t||t.length===0)return!0;let o=window.location.origin;return t.some(i=>i===o||i==="*")}async function $(n,e){let{DEFAULT_PROFILES:t}=await Promise.resolve().then(()=>(Ve(),fn)),o=t[n];return o?Bn(o,"en"):null}function Vn(n,e){let t=e.core?.usePrebuiltProfiles??"all";return t==="all"?!0:t.includes(n)}var Ze;function Do(){if(Ze)return Ze;let n=new Map,e=R.countries;for(let[t,o]of Object.entries(e))for(let i of o.timezones??[]){let a=n.get(i)??[];a.push(t),n.set(i,a)}return Ze=n,n}function Lo(n){let e=n.replace(/_/g,"-").split("-"),t=e.length>=2?e[e.length-1]?.toUpperCase():void 0;return t&&/^[A-Z]{2}$/.test(t)&&t in R.countries?t:void 0}function zo(n,e){let t=Do().get(n)??[],o=e.map(Lo).filter(i=>!!i);return t.length===1?t[0]:t.length>1?o.find(i=>t.includes(i))??t[0]:o[0]}function Ro(n,e){let t=zo(n,e),o=R.countries,i=t?o[t]:void 0;if(i?.default)return i.default;let a=n.split("/");return a[0]==="Europe"?"opt-in":a[0]==="America"?"opt-out":"opt-in"}function Y(n){let e=n.core?.locale;if(e&&e!=="auto")return e;let t=In(n.core?.storage??"cookie");return t||navigator.language}function jn(n){return n.api?.tenantId??n.core?.tenantId??"default"}async function he(n,e){try{return await ge(n,{},e)}catch{return null}}function Hn(n){let e=n;return{...e.id!==void 0?{id:e.id}:{},...e.defaultLocale!==void 0?{defaultLocale:e.defaultLocale}:{},...e.expiryDays!==void 0?{expiryDays:e.expiryDays}:{},...e.cookies!==void 0?{cookies:e.cookies}:{},...e.mainBanner!==void 0?{mainBanner:e.mainBanner}:{},...e.gpcBanner!==void 0?{gpcBanner:e.gpcBanner}:{},...e.preferenceModal!==void 0?{preferenceModal:e.preferenceModal}:{},...e.darkMode!==void 0?{darkMode:e.darkMode}:{},...e.allowedOrigins!==void 0?{allowedOrigins:e.allowedOrigins}:{},...e.dpdpa!==void 0?{dpdpa:e.dpdpa}:{},...e.complianceGroup!==void 0?{complianceGroup:e.complianceGroup}:{},...e.gpcMode!==void 0?{gpcMode:e.gpcMode}:{},...e.hidePoweredBy!==void 0?{hidePoweredBy:e.hidePoweredBy}:{},...e.allowReceipt!==void 0?{allowReceipt:e.allowReceipt}:{},...e.complianceConfig!==void 0?{complianceConfig:e.complianceConfig}:{},...e.showFooterMetadata!==void 0?{showFooterMetadata:e.showFooterMetadata}:{},...e.enhanceAccessibility!==void 0?{enhanceAccessibility:e.enhanceAccessibility}:{}}}async function Fn(n,e){let t=Go(n);if(t){if(t.deepMerge){let o=await $(n,e),i=Hn(t);return o?M(o,i):i}return qn(t,e)}}async function K(n){let{tz:e,lang:t,langs:o}=Dn(),i=Ro(e,o.length?o:[t]),a=Y(n),r=await Fn(i,a);if(r)return r;if(!Vn(i,n))throw new Error(`Pre-built profile for complianceGroup "${i}" is disallowed by usePrebuiltProfiles config.`);let c=await $(i,a);if(!c)throw new Error(`No embedded profile found for complianceGroup "${i}".`);return c}async function et(n,e){let t=Y(e),o=await Fn(n,t);if(o)return o;if(!Vn(n,e))throw new Error(`Pre-built profile for complianceGroup "${n}" is disallowed by usePrebuiltProfiles config.`);let i=await $(n,t);if(!i)throw new Error(`No embedded profile found for complianceGroup "${n}".`);return i}async function Un(n){let e=Y(n),t=jn(n),o=n.core?.cacheResolvedProfiles!==!1,i=n.api?.baseUrl??window.location.origin,a=n.api?.trustDomain??!1,r=Io(t,e,o);if(r){let d=await he(r.filePath,n.api?.authToken);if(d)return Xe(d,a)?Qe(d):(P.error(`Domain ${window.location.origin} is not in allowedOrigins for this profile. Falling back to pre-built profile.`),K(n))}let c=`${i}/consenti/api/v1/resolve-profile?data=${encodeURIComponent(Ln(e))}`,s,l,m;try{let d=await ge(c,{},n.api?.authToken);s=d.path,l=d.complianceGroup,m=d.locale,d.found&&s&&Mo(t,e,o,{filePath:`${i}${s}`,version:0,complianceGroup:l,tenantId:t,locale:m})}catch{return P.warn("resolve-profile failed; falling back to pre-built profile."),K(n)}if(s){let d=await he(`${i}${s}`,n.api?.authToken);if(d&&Xe(d,a))return Qe(d)}if(l){let d=await $(l,m);if(d)return d}return K(n)}async function Bo(n,e){let t=Y(e),o=jn(e),i=e.api?.baseUrl??window.location.origin,a=e.api?.trustDomain??!1,r=e.api?.complianceGroup??n,c=await he(`${i}/consenti/api/v1/profiles/${o}/${r}/${encodeURIComponent(t)}`,e.api?.authToken)??await he(`${i}/consenti/api/v1/profiles/${o}/${r}/default`,e.api?.authToken);return c?Xe(c,a)?Qe(c):(P.error(`Domain ${window.location.origin} is not in allowedOrigins for this profile. Falling back to pre-built profile.`),et(r,e)):(P.warn(`Could not fetch profile for ${r}; falling back to pre-built.`),et(r,e))}function qn(n,e,t){let o=n.translations?.[e];if(o===void 0)return e!==n.defaultLocale&&P.warn(`Unable to resolve requested locale "${e}" of profile "${t??n.id}", Using default "${n.defaultLocale}".`),{id:n.id,gpcMode:n.gpcMode??"ignore",allowReceipt:n.allowReceipt??!1,defaultLocale:n.defaultLocale,locales:[n.defaultLocale,...Object.keys(n.translations??{})],cookies:n.cookies??{},...n.expiryDays?{expiryDays:n.expiryDays}:{},mainBanner:n.mainBanner,...n.gpcBanner?{gpcBanner:n.gpcBanner}:{},preferenceModal:n.preferenceModal,...n.darkMode!==void 0?{darkMode:n.darkMode}:{},...n.complianceGroup?{complianceGroup:n.complianceGroup}:{}};let i=M(n.mainBanner,o.mainBanner),a=n.gpcBanner?M(n.gpcBanner,o.gpcBanner??{}):!1,r=M(n.preferenceModal??{},o.preferenceModal??{});return{id:n.id,gpcMode:n.gpcMode??"ignore",allowReceipt:n.allowReceipt??!1,defaultLocale:n.defaultLocale,locales:[n.defaultLocale,...Object.keys(n.translations??{})],cookies:n.cookies??{},...n.expiryDays?{expiryDays:n.expiryDays}:{},mainBanner:i,...a?{gpcBanner:a}:{},preferenceModal:r,...n.darkMode!==void 0?{darkMode:n.darkMode}:{},...n.complianceGroup?{complianceGroup:n.complianceGroup}:{}}}async function No(n,e){e.api?.enabled&&P.warn("Local profile used instead of server profile. Check compliance.type config.");let t=Y(e),o=Eo(n);if(o){if(o.deepMerge&&o.complianceGroup){let i=await $(o.complianceGroup,t),a=Hn(o);return i?M(i,a):a}return qn(o,t,n.description)}return P.error(`Unable to resolve locally registered profile "${n.description}", Using compliance.type: 'auto'.`),e.api?.enabled?Un(e):K(e)}async function Wn(n){let e=n.compliance?.type??"auto",t=n.api?.enabled??!1;return e==="auto"?t?Un(n):K(n):typeof e=="symbol"?No(e,n):t?Bo(e,n):et(e,n)}function z(){let n=hn();return n?"globalPrivacyControl"in n&&n.globalPrivacyControl===!0:!1}function Kn(n,e,t,o){if(o==="ignore"||!z())return{...t};let i={...t},a=H(e);for(let[r,c]of Object.entries(n))G(r,a)||c.listenGpc&&(i[r]=Ge(r,a)==="legitimate_interest"?"objected":"denied");for(let r of Object.keys(n))G(r,a)&&(i[r]="granted");return i}var $n=4,Oo="2.2";function Vo(n,e){let t=new Set,o=new Set;if(n&&e){for(let[i,a]of Object.entries(n.cookies))if(!(e[i]!=="granted"||!a.tcfVendorId)){o.add(a.tcfVendorId);for(let r of a.tcfPurposes??[])t.add(r)}}return{purposeConsents:Array.from(t).sort((i,a)=>i-a),vendorConsents:Array.from(o).sort((i,a)=>i-a)}}function ye(n,e){let t={};for(let o=1;o<=e;o++)t[o]=n.includes(o);return t}function Yn(n){if(!p())return;let e=F();if(!e||!n().tcfConfig?.enabled||e.__tcfapi)return;let t=new Map,o=0;function i(l){let{profile:m,consent:d,tcfConfig:y}=n(),h=y??{enabled:!1,cmpId:0,cmpVersion:0},{purposeConsents:u,vendorConsents:b}=Vo(m,d);return{tcString:nt({cmpId:h.cmpId,cmpVersion:h.cmpVersion,consentScreen:1,consentLanguage:"en",vendorListVersion:0,purposeConsents:u,vendorConsents:b}),tcfPolicyVersion:$n,cmpId:h.cmpId,cmpVersion:h.cmpVersion,gdprApplies:!0,eventStatus:d?"tcloaded":"cmpuishown",cmpStatus:"loaded",isServiceSpecific:!0,useNonStandardStacks:!1,publisherCC:"AA",purposeOneTreatment:!1,...l!==void 0?{listenerId:l}:{},purpose:{consents:ye(u,10),legitimateInterests:ye([],10)},vendor:{consents:ye(b,Math.max(0,...b)),legitimateInterests:ye([],0)}}}function a(){for(let[l,m]of t)m(i(l),!0)}function r(l,m,d,y){switch(l){case"ping":{let{consent:h,tcfConfig:u}=n();d({gdprApplies:!0,cmpLoaded:!0,cmpStatus:"loaded",displayStatus:h?"hidden":"visible",apiVersion:Oo,cmpVersion:u?.cmpVersion??0,cmpId:u?.cmpId??0,gvlVersion:0,tcfPolicyVersion:$n},!0);return}case"getTCData":d(i(),!0);return;case"addEventListener":{let h=++o;t.set(h,d),d(i(h),!0);return}case"removeEventListener":{let h=typeof y=="number"?y:void 0,u=h!==void 0&&t.delete(h);d(u,u);return}}}let c=e.__tcfapi?.a??[],s=((l,m,d,y)=>{r(l,m,d,y)});s.a=[],e.__tcfapi=s,window.addEventListener("consenti:consentSubmitted",a);for(let[l,m,d,y]of c)r(l,m,d,y)}function ve(n,e,t){let o=document.createElement("button");return o.type="button",n&&(o.id=n),o.className=`consenti-btn consenti-btn--${e.style}`,o.textContent=e.text,o.addEventListener("click",()=>{switch(e.action){case"custom":{let i=e.cookies;i==="*"?t.onGrantAll():i==="!"?t.onDenyAll():Array.isArray(i)&&i.length>0&&t.onGrantSpecific(i);break}case"submit":t.onSubmit();break;case"manage":t.onManage();break;case"close":t.onClose();break}}),o}function j(n,e){let t=document.createElement("div");return t.className="consenti-overlay",t.style.opacity=String(n/100),t.setAttribute("aria-hidden","true"),e&&t.addEventListener("click",e),t}var be=class{constructor(){this.el=null;this.overlayEl=null}build(e,t,o,i,a,r,c=!0,s="main"){let l=document.createElement("div");l.id="consenti-banner",l.className=`consenti-banner consenti-banner--${s} consenti-banner--${e.position}`,l.setAttribute("role","region"),l.setAttribute("aria-label","Cookie consent"),l.setAttribute("aria-live","polite");let m=document.createElement("div");m.className="consenti-banner__text-container";let d=document.createElement("div");if(d.className="consenti-banner__links",e.heading){let g=e.headingTag??"div",C=document.createElement(g);C.id="consenti-banner-heading",C.className="consenti-banner__heading",C.textContent=e.heading,m.appendChild(C)}let y=document.createElement("div");if(y.className="consenti-banner__text",y.innerHTML=e.htmlText,o){let g=document.createElement("a");g.href=o,g.className="consenti-banner__link consenti-banner__link--privacy consenti-btn consenti-btn--text",g.textContent="Privacy Policy",g.setAttribute("target","_blank"),g.setAttribute("rel","noopener noreferrer"),d.appendChild(g)}m.appendChild(y);let h=Object.entries(e.buttons),u=h.filter(g=>g[1].action==="link");if(u.length>0)for(let[,g]of u){if(!g.url)continue;let C=document.createElement("a");C.href=g.url,C.className=`consenti-banner__link consenti-btn consenti-btn--${g.style??"text"}`,C.textContent=g.text,C.setAttribute("target","_blank"),C.setAttribute("rel","noopener noreferrer"),d.appendChild(C)}(u.length>0||o)&&m.appendChild(d),l.appendChild(m);let b=h.filter(([,g])=>g.action!=="link");if(b.length>0){let g=document.createElement("div");g.className="consenti-banner__buttons";for(let[C,A]of b)g.appendChild(ve(C,A,t));l.appendChild(g)}let _=e.showClose,w=e.showLocaleSwitcher&&i&&i.length>0;if(_||w){let g=document.createElement("div");if(g.className="consenti-banner__controls",w&&i&&r&&g.appendChild(jo(i,a,r)),_){let C=document.createElement("button");C.type="button",C.className="consenti-banner__close consenti-btn consenti-transition-1_2x consenti-btn--action",C.setAttribute("aria-label","Close cookie banner"),C.textContent="\xD7",C.addEventListener("click",t.onClose),g.appendChild(C)}l.appendChild(g)}e.overlayOpacity&&e.overlayOpacity>0&&(this.overlayEl=j(e.overlayOpacity));let E=document.createElement("a");return E.href="https://consenti.dev/?utm_source=widget&utm_medium=powered-by&utm_campaign=consenti-ui",E.className="consenti__powered-by",E.textContent="Powered by Consenti \u2197",E.setAttribute("target","_blank"),E.setAttribute("rel","noopener noreferrer"),c&&E.classList.add("consenti-d-none"),l.appendChild(E),this.el=l,l}getOverlay(){return this.overlayEl}show(){this.el&&(this.el.style.display=""),this.overlayEl&&(this.overlayEl.style.display="")}hide(){this.el&&(this.el.style.display="none"),this.overlayEl&&(this.overlayEl.style.display="none")}remove(){this.el?.remove(),this.overlayEl?.remove(),this.el=null,this.overlayEl=null}};function jo(n,e,t){let o=document.createElement("div");o.className="consenti-locale-switcher";let i=document.createElement("button");i.type="button",i.className="consenti-locale-switcher__btn consenti-btn consenti-transition-1_2x consenti-btn--action",i.setAttribute("aria-label","Switch language"),i.setAttribute("aria-haspopup","listbox"),i.textContent="\u{1F310}";let a=document.createElement("ul");a.className="consenti-locale-switcher__list",a.setAttribute("role","listbox"),a.setAttribute("aria-label","Select language"),a.hidden=!0;for(let r of n){let c=document.createElement("li");c.setAttribute("role","option"),c.setAttribute("aria-selected",String(r===e));let s=document.createElement("button");s.type="button",s.className=`consenti-locale-switcher__option${r===e?" consenti-locale-switcher__option--active":""}`,s.textContent=r,s.addEventListener("click",l=>{l.stopPropagation(),a.hidden=!0,r!==e&&t(r)}),c.appendChild(s),a.appendChild(c)}return i.addEventListener("click",r=>{r.stopPropagation(),a.hidden=!a.hidden}),document.addEventListener("click",()=>{a.hidden=!0},{capture:!0,once:!1}),o.appendChild(i),o.appendChild(a),o}var Ho=["a[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])','[contenteditable="true"]'].join(", ");function Jn(n){let e=()=>Array.from(n.querySelectorAll(Ho)).filter(i=>!i.closest('[aria-hidden="true"]')),t=i=>{if(i.key!=="Tab")return;let a=e();if(a.length===0)return;let r=a[0],c=a[a.length-1];i.shiftKey?(document.activeElement===r||document.activeElement===n)&&(i.preventDefault(),c.focus()):document.activeElement===c&&(i.preventDefault(),r.focus())},o=i=>{i.key==="Escape"&&n.dispatchEvent(new CustomEvent("consenti:closeRequest",{bubbles:!0}))};return document.addEventListener("keydown",t),document.addEventListener("keydown",o),e()[0]?.focus(),()=>{document.removeEventListener("keydown",t),document.removeEventListener("keydown",o)}}var Ce=class n{constructor(){this.el=null;this.triggerEl=null;this.trapCleanup=null;this.toggleState=new Map;this.paramToggles=new Map;this.categoryToggles=new Map;this.categoryDisclosures=new Map;this.receiptCheckbox=null;this.passthrough=!1;this.mobileBreakpoint=576;this.savedBodyOverflow=void 0}build(e,t,o,i,a,r,c,s,l,m=!0){this.mobileBreakpoint=e.mobileFullScreenBreakpoint??576;let d=e.position??"center",y=document.createElement("div");y.id="consenti-modal",y.className=`consenti-modal consenti-modal--${d}`,y.setAttribute("role","dialog"),y.setAttribute("aria-modal","true");let h=e.overlayOpacity??50;if(this.passthrough=h===0,h>0){let v=e.persistent?void 0:()=>i.onClose(),k=j(h,v);k.className="consenti-modal__overlay",y.appendChild(k)}else y.classList.add("consenti-modal--passthrough");let u=document.createElement("div");u.className="consenti-modal__container";let b=document.createElement("div");b.className="consenti-modal__header";let _=document.createElement("div");if(_.className="consenti-modal__body",e.heading){let v=e.headingTag??"div",k=document.createElement(v);k.id="consenti-modal-heading",k.className="consenti-modal__heading",k.textContent=e.heading,b.appendChild(k),y.setAttribute("aria-labelledby","consenti-modal-heading")}if(e.subheading){let v=document.createElement("p");v.className="consenti-modal__subheading",v.textContent=e.subheading,b.appendChild(v)}let w=e.showClose!==!1,E=e.showLocaleSwitcher&&c&&c.length>0;if(E||w){let v=document.createElement("div");if(v.className="consenti-modal__header-controls",E&&c&&l&&v.appendChild(Fo(c,s,l)),w){let k=document.createElement("button");k.type="button",k.className="consenti-modal__close consenti-transition-1_2x consenti-btn consenti-btn--action",k.setAttribute("aria-label","Close preference modal"),k.textContent="\xD7",k.addEventListener("click",i.onClose),v.appendChild(k)}b.appendChild(v)}if(u.appendChild(b),e.htmlText){let v=document.createElement("div");v.className="consenti-modal__text",v.innerHTML=e.htmlText,_.appendChild(v)}let g=Object.entries(e.buttons),C=g.filter(v=>v[1].action==="link");if(C.length>0){let v=document.createElement("div");v.className="consenti-modal__links";for(let[,k]of C){if(!k.url)continue;let T=document.createElement("a");T.href=k.url,T.className=`consenti-modal__link consenti-btn consenti-btn--${k.style??"text"}`,T.textContent=k.text,T.setAttribute("target","_blank"),T.setAttribute("rel","noopener noreferrer"),v.appendChild(T)}b.appendChild(v)}let A=document.createElement("div");A.className="consenti-modal__categories";for(let[v,k]of Object.entries(e.categories)){let T=this.buildCategory(v,k,t,o);A.appendChild(T)}if(_.appendChild(A),u.appendChild(_),a&&_.appendChild(this.buildReceiptOption(e.receiptLabel,e.receiptDescription)),r){let v=document.createElement("div");v.className="consenti-modal__dpdpa-notice";let k=Qn=>Qn.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),T=r.grievanceEmail.includes("@")&&!r.grievanceEmail.toLowerCase().startsWith("javascript:")?r.grievanceEmail:"";v.innerHTML=[`<strong>Data Fiduciary:</strong> ${k(r.dataFiduciary)}.`,r.purposeDescription?` <strong>Purpose:</strong> ${k(r.purposeDescription)}.`:""," You may withdraw consent at any time or contact our Grievance Officer at",T?` <a href="mailto:${k(T)}">${k(T)}</a>.`:"."].join(""),u.appendChild(v)}let D=document.createElement("div");D.className="consenti-modal__buttons";for(let[v,k]of g.filter(([,T])=>T.action!=="link"))D.appendChild(ve(v,k,i));u.appendChild(D);let L=document.createElement("a");L.href="https://consenti.dev/?utm_source=widget&utm_medium=powered-by&utm_campaign=consenti-ui",L.className="consenti__powered-by",L.textContent="Powered by Consenti \u2197",L.setAttribute("target","_blank"),L.setAttribute("rel","noopener noreferrer"),m&&L.classList.add("consenti-d-none"),_.appendChild(L),y.appendChild(u),y.addEventListener("consenti:closeRequest",()=>i.onClose()),this.el=y}static appendToggleIcons(e,t){t&&e.classList.add("consenti-toggle--li");let o=document.createElement("span");o.className="consenti-category__toggle-icon consenti-category__toggle-icon--check",o.setAttribute("aria-hidden","true"),o.innerHTML='<svg viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 5L4 7.5L8.5 2.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.appendChild(o);let i=document.createElement("span");if(i.className="consenti-category__toggle-icon consenti-category__toggle-icon--cross",i.setAttribute("aria-hidden","true"),i.innerHTML='<svg viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 2L8 8M8 2L2 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',e.appendChild(i),t){let r=document.createElement("span");r.className="consenti-category__toggle-icon consenti-category__toggle-icon--objected",r.setAttribute("aria-hidden","true"),r.innerHTML='<svg viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" r="3.5" stroke="currentColor" stroke-width="1.4"/><path d="M2.5 2.5L7.5 7.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>',e.appendChild(r)}let a=document.createElement("span");a.className="consenti-category__toggle-knob",a.setAttribute("aria-hidden","true"),e.appendChild(a)}computeRollup(e,t){let o=t?"objected":"denied",i=e.map(a=>this.toggleState.get(a));return i.every(a=>a==="granted")?"allowed":i.every(a=>a===o||a===void 0)?"denied":"mixed"}updateCategoryToggleVisual(e){let t=this.categoryToggles.get(e);if(!t)return;let o=this.computeRollup(t.cookieIds,t.isLI),i=o==="allowed"?"true":o==="denied"?"false":"mixed";t.el.setAttribute("aria-checked",i),t.el.classList.toggle("consenti-category__toggle--partial",o==="mixed")}buildParamRow(e,t,o,i,a){let r=document.createElement("div");r.className="consenti-category__param";let c=document.createElement("div");c.className="consenti-category__param-info";let s=document.createElement("span");s.className="consenti-category__param-label",s.textContent=t,c.appendChild(s);let l=document.createElement("span");l.className="consenti-category__param-meta";let m=[];o?.purpose&&m.push(o.purpose),o?.cpraCategory&&m.push(`CPRA: ${o.cpraCategory}`),o?.tcfVendorId!=null&&m.push(`TCF Vendor #${o.tcfVendorId}`),l.textContent=m.join(" \xB7 "),m.length&&c.appendChild(l),r.appendChild(c);let d=a?"objected":"denied",h=(this.toggleState.get(t)??d)==="granted",u=document.createElement("button");return u.type="button",u.className=`consenti-category__param-toggle${i?" consenti-category__param-toggle--mandatory":""}`,u.setAttribute("role","switch"),u.setAttribute("aria-checked",String(h)),u.setAttribute("aria-label",t),i&&(u.setAttribute("aria-disabled","true"),u.disabled=!0),n.appendToggleIcons(u,a),i||u.addEventListener("click",()=>{let b=this.toggleState.get(t)==="granted"?d:"granted";this.toggleState.set(t,b),u.setAttribute("aria-checked",String(b==="granted")),this.updateCategoryToggleVisual(e)}),this.paramToggles.set(t,u),r.appendChild(u),r}buildCategory(e,t,o,i){let a=t.legalBasis==="legitimate_interest",r=t.legalBasis==="mandatory",c=a?"objected":"denied";for(let g of t.cookies){let C=i[g],A;C!==void 0?A=C:r||a?A="granted":A=o[g]?.preGrant?"granted":"denied",this.toggleState.set(g,A)}let s=document.createElement("div");s.className=`consenti-category${r?" consenti-category--mandatory":""}`;let l=document.createElement("div");l.className="consenti-category__header";let m=t.headingTag??"div",d=document.createElement(m);d.id=`consenti-cat-${e}-heading`,d.className="consenti-category__heading",d.textContent=t.heading,l.appendChild(d);let y=this.computeRollup(t.cookies,a),h=document.createElement("button");if(h.type="button",h.className=`consenti-category__toggle${r?" consenti-category__toggle--mandatory":""}${y==="mixed"?" consenti-category__toggle--partial":""}`,h.setAttribute("role","checkbox"),h.setAttribute("aria-checked",y==="allowed"?"true":y==="denied"?"false":"mixed"),h.setAttribute("aria-labelledby",`consenti-cat-${e}-heading`),r&&(h.setAttribute("aria-disabled","true"),h.disabled=!0),n.appendToggleIcons(h,a),this.categoryToggles.set(e,{el:h,cookieIds:t.cookies,isLI:a}),r||h.addEventListener("click",()=>{let C=this.computeRollup(t.cookies,a)==="allowed"?c:"granted";for(let A of t.cookies){this.toggleState.set(A,C);let D=this.paramToggles.get(A);D&&!D.disabled&&D.setAttribute("aria-checked",String(C==="granted"))}this.updateCategoryToggleVisual(e)}),l.appendChild(h),s.appendChild(l),a&&t.legitimateInterestDescription){let g=document.createElement("p");g.className="consenti-category__li-desc",g.textContent=t.legitimateInterestDescription,s.appendChild(g)}let u=document.createElement("div");u.className="consenti-category__text-wrap";let b=document.createElement("div");b.className="consenti-category__text consenti-category__text--clamped",b.innerHTML=t.htmlText,u.appendChild(b);let _=document.createElement("button");_.type="button",_.className="consenti-category__show-more consenti-d-none",_.setAttribute("aria-expanded","false"),_.textContent="Show more",u.appendChild(_),s.appendChild(u);let w=document.createElement("div");w.className="consenti-category__params";for(let g of t.cookies)w.appendChild(this.buildParamRow(e,g,o[g],r,a));let E=t.cookies.length>1;return w.classList.add("consenti-d-none"),s.appendChild(w),_.addEventListener("click",()=>{let g=!b.classList.toggle("consenti-category__text--clamped");E&&w.classList.toggle("consenti-d-none",!g),_.setAttribute("aria-expanded",String(g)),_.textContent=g?"Show less":"Show more"}),this.categoryDisclosures.set(e,{text:b,toggle:_,params:E?w:null}),s}buildReceiptOption(e,t){let o=document.createElement("div");o.className="consenti-modal__receipt-option";let i=document.createElement("label");i.className="consenti-modal__receipt-label";let a=document.createElement("input");a.type="checkbox",a.className="consenti-modal__receipt-checkbox",a.id="consenti-receipt-checkbox",a.setAttribute("aria-describedby","consenti-receipt-desc"),this.receiptCheckbox=a,i.appendChild(a),i.append(" "+(e??"Get a copy of my consent choices (JSON)")),o.appendChild(i);let r=document.createElement("p");return r.id="consenti-receipt-desc",r.className="consenti-modal__receipt-desc",r.textContent=t??"A JSON file will be downloaded to your device when you save your preferences.",o.appendChild(r),o}open(e,t){if(!this.el)return;this.triggerEl=e??document.activeElement,this.receiptCheckbox&&(this.receiptCheckbox.checked=!1);let o=this.mobileBreakpoint>0&&window.innerWidth<=this.mobileBreakpoint;o?this.el.classList.add("consenti-modal--fullscreen"):this.el.classList.remove("consenti-modal--fullscreen"),(t??document.body).appendChild(this.el),(!this.passthrough||o)&&(this.savedBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden"),this.passthrough||(this.trapCleanup=Jn(this.el)),this.resetCategoryDisclosures()}resetCategoryDisclosures(){for(let{text:e,toggle:t,params:o}of this.categoryDisclosures.values()){e.classList.add("consenti-category__text--clamped"),o?.classList.add("consenti-d-none"),t.setAttribute("aria-expanded","false"),t.textContent="Show more";let i=e.scrollHeight>e.clientHeight+1;t.classList.toggle("consenti-d-none",!(i||o!==null))}}close(){this.trapCleanup?.(),this.trapCleanup=null,this.savedBodyOverflow!==void 0&&(document.body.style.overflow=this.savedBodyOverflow,this.savedBodyOverflow=void 0),this.el?.remove(),this.triggerEl?.focus(),this.triggerEl=null}isOpen(){return this.el?.isConnected===!0}isReceiptRequested(){return this.receiptCheckbox?.checked??!1}getToggleConsent(e){let t={};for(let o of Object.values(e)){let i=o.legalBasis==="legitimate_interest",a=o.legalBasis==="mandatory",r=a?"granted":i?"objected":"denied";for(let c of o.cookies)t[c]=a?"granted":this.toggleState.get(c)??r}return t}destroy(){this.trapCleanup?.(),this.savedBodyOverflow!==void 0&&(document.body.style.overflow=this.savedBodyOverflow,this.savedBodyOverflow=void 0),this.el?.remove(),this.el=null,this.paramToggles.clear(),this.categoryToggles.clear(),this.categoryDisclosures.clear(),this.toggleState.clear(),this.receiptCheckbox=null}};function Fo(n,e,t){let o=document.createElement("div");o.className="consenti-locale-switcher consenti-locale-switcher--modal";let i=document.createElement("button");i.type="button",i.className="consenti-locale-switcher__btn consenti-btn consenti-btn--action consenti-transition-1_2x",i.setAttribute("aria-label","Switch language"),i.setAttribute("aria-haspopup","listbox"),i.textContent="\u{1F310}";let a=document.createElement("ul");a.className="consenti-locale-switcher__list",a.setAttribute("role","listbox"),a.setAttribute("aria-label","Select language"),a.hidden=!0;for(let r of n){let c=document.createElement("li");c.setAttribute("role","option"),c.setAttribute("aria-selected",String(r===e));let s=document.createElement("button");s.type="button",s.className=`consenti-locale-switcher__option${r===e?" consenti-locale-switcher__option--active":""}`,s.textContent=r,s.addEventListener("click",l=>{l.stopPropagation(),a.hidden=!0,r!==e&&t(r)}),c.appendChild(s),a.appendChild(c)}return i.addEventListener("click",r=>{r.stopPropagation(),a.hidden=!a.hidden}),document.addEventListener("click",()=>{a.hidden=!0},{capture:!0,once:!1}),o.appendChild(i),o.appendChild(a),o}var J=class{constructor(){this.el=null;this.overlayEl=null}buildPrompt(e,t,o){let i=document.createElement("div");i.id="consenti-age-gate",i.className="consenti-age-gate",i.setAttribute("role","dialog"),i.setAttribute("aria-modal","true"),i.setAttribute("aria-label","Age verification");let a=document.createElement("div");a.className="consenti-age-gate__heading",a.textContent=`Are you ${e} or older?`,i.appendChild(a);let r=document.createElement("div");r.className="consenti-age-gate__text",r.textContent="Please confirm your age before we show you cookie preferences.",i.appendChild(r);let c=document.createElement("div");c.className="consenti-age-gate__buttons";let s=document.createElement("button");s.type="button",s.className="consenti-btn consenti-btn--primary",s.textContent="Yes",s.addEventListener("click",t),c.appendChild(s);let l=document.createElement("button");return l.type="button",l.className="consenti-btn consenti-btn--secondary",l.textContent="No",l.addEventListener("click",o),c.appendChild(l),i.appendChild(c),this.overlayEl=j(60),this.el=i,i}buildParentalConsentMessage(e){let t=document.createElement("div");t.id="consenti-age-gate",t.className="consenti-age-gate",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-label","Parental consent required");let o=document.createElement("div");o.className="consenti-age-gate__heading",o.textContent="Parental consent required",t.appendChild(o);let i=document.createElement("div");i.className="consenti-age-gate__text",i.textContent="Only strictly necessary cookies will be used until a parent or guardian verifies consent on your behalf.",t.appendChild(i);let a=document.createElement("div");a.className="consenti-age-gate__buttons";let r=document.createElement("button");return r.type="button",r.className="consenti-btn consenti-btn--primary",r.textContent="OK",r.addEventListener("click",e),a.appendChild(r),t.appendChild(a),this.el=t,t}getOverlay(){return this.overlayEl}remove(){this.el?.remove(),this.overlayEl?.remove(),this.el=null,this.overlayEl=null}};var Zn="consenti-root",ke=class{constructor(){this.root=null;this.styleEl=null}mount(e){if(!p())throw new Error("[Consenti] Renderer.mount() called in SSR context");if(this.root)return this.root;if(e!==void 0){if(typeof e=="string"){let o=document.querySelector(e);if(!o)throw new Error(`[Consenti] rootEl selector "${e}" did not match any element.`);this.root=o}else{if(!document.contains(e))throw new Error("[Consenti] rootEl element is not attached to the document.");this.root=e}return this.root.classList.add("consenti-root"),this.root}let t=document.getElementById(Zn);return t||(t=document.createElement("div"),t.id=Zn,document.body.appendChild(t)),t.classList.add("consenti-root"),this.root=t,t}injectStyles(e){if(!p()||this.styleEl)return;let t=document.createElement("style");t.id="consenti-styles",t.textContent=e,document.head.appendChild(t),this.styleEl=t}unmount(){this.root?.remove(),this.styleEl?.remove(),this.root=null,this.styleEl=null}announceToScreenReader(e){if(!p())return;let t=document.getElementById("consenti-announcer");t||(t=document.createElement("div"),t.id="consenti-announcer",t.setAttribute("role","status"),t.setAttribute("aria-live","polite"),t.setAttribute("aria-atomic","true"),t.style.cssText="position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;",document.body.appendChild(t)),t.textContent="",requestAnimationFrame(()=>{t&&(t.textContent=e)})}};var Pe=class{constructor(e){this.initialized=!1;this.initializing=!1;this.profile=null;this.resolvedBase=null;this.categoryIndex=new Map;this.scannedScripts=[];this.consentStore=null;this.eventBus=null;this.banner=null;this.modal=null;this.ageGate=null;this.renderer=null;this._ageVerified=void 0;this._parentalConsentToken=void 0;this.broadcastChannel=new le;this.plugins=[];this._bannerVariant=null;this._bannerMounted=null;this._focusTrapListener=null;this._eventHandlers=new Map;this.config={...e,core:e.core??{}},this.readyPromise=new Promise(t=>{this.readyResolve=t}),p()&&(e.verbose?je(["error","info","warning","log"]):je(this.config.core.console??["error"]),e.api?.enabled&&this.config.core.storage==="localStorage"&&(P.warn("localStorage storage mode cannot be used with API mode (API sets cookies via Set-Cookie header). Falling back to cookie storage."),this.config.core.storage="cookie"),e.autoInit!==!1&&this.init().catch(t=>P.warn("Init error:",t)))}visitorId(){return Tn()}profileId(){return this.profile?.id??"0"}async init(){if(p()&&!this.initializing){this.initializing=!0,this.initialized=!1,this.readyPromise=new Promise(e=>{this.readyResolve=e});try{let e=this.config.core.storage??"cookie",t=await Wn(this.config);this.resolvedBase=t,this.config.darkMode!==void 0&&(t.darkMode=this.config.darkMode);let o=this.config.profileOverride?M(t,this.config.profileOverride):t,i=z();o.gpcMode=o.gpcMode??"ignore",this.profile=o,this.categoryIndex=H(o.preferenceModal.categories),this.eventBus=new me(this.profileId(),this.config.utils?.gtm),this.consentStore=new ue(this.profileId(),e,this.config.core.cookieDomains,this.config.core.userId),this.consentStore.setProfileExpiry(o.expiryDays??365),this.consentStore.setProfileVersion(o.version??0),Yn(()=>({profile:this.profile,consent:this.getConsent(),tcfConfig:this.config.compliance?.tcf})),this.renderer=new ke,!this.config.core.disableCssTemplate&&Fe&&this.renderer.injectStyles(Fe),this.banner=new be,this.modal=new Ce,this.applyTheme(),this.applyDarkMode(),this.applyDirection(),this.applyAccessibility(),this.applyStackButtonsBreakpoint(),this.broadcastChannel.connect(l=>this.handleBroadcastMessage(l)),await this.runPlugins();let a=o.cookieSigningKey??this.config.core.cookieSigningKey,c=(a?await this.consentStore.readAndVerify(a):this.consentStore.read())!==null,s=this.config.compliance?.ageGate;if(s?.enabled&&!c){this.showAgeGate(s,o);return}await this.continueInit(o,i,c)}finally{this.initializing=!1}}}async continueInit(e,t,o){if(!this.consentStore||!this.eventBus)return;if(this.eventBus.dispatch("consenti:bannerInitialized",{profileId:this.profileId(),hasExistingConsent:o,complianceGroup:e.complianceGroup??"auto",gpcDetected:t,willShow:!o&&!(t&&e.gpcMode==="strict")}),e.gpcMode!=="ignore"&&t){let c=Kn(e.cookies,e.preferenceModal.categories,{},e.gpcMode);if(e.gpcMode==="strict"){await this.submitConsent(c,!0),this.finishInit();return}if(!o){let s=e.cookieSigningKey??this.config.core.cookieSigningKey,l={gpcDetected:!0,locale:this.config.core.locale??"en"};s?this.lastSignature=await this.consentStore.writeAndSign(c,s,l):this.consentStore.write(c,l),this.broadcastChannel.send({type:"consentUpdated",consent:c,profileId:this.profileId()}),this.eventBus.dispatch("consenti:consentSubmitted",{consentJson:c,gpcDetected:!0,consentId:S("cons"),consentAction:this.deriveAction(c,!1),pageUrl:window.location.href,visitorId:this.visitorId(),timestamp:Math.round(Date.now()/1e3),profileId:this.profileId()}),this.showBanner(!0),this.finishInit();return}}let i=e.complianceGroup??"",a=i==="opt-out",r=i==="opt-out-strict";if(this.getRootElement()?.setAttribute("data-consenti-cg",i),this.config.verbose&&this.getRootElement()?.setAttribute("data-consenti-gpc",e.gpcMode??""),a&&!o){let c={};for(let m of Object.keys(e.cookies))c[m]="granted";let s=e.cookieSigningKey??this.config.core.cookieSigningKey,l={locale:this.config.core.locale??"en"};s?await this.consentStore.writeAndSign(c,s,l):this.consentStore.write(c,l),this.finishInit();return}if(r&&!o){let c={};for(let[m,d]of Object.entries(e.cookies)){if(G(m,this.categoryIndex)){c[m]="granted";continue}d.cpraCategory==="sensitive"||t&&(d.cpraCategory==="sale"||d.cpraCategory==="sharing")?c[m]="denied":c[m]="granted"}let s=e.cookieSigningKey??this.config.core.cookieSigningKey,l={locale:this.config.core.locale??"en"};s?await this.consentStore.writeAndSign(c,s,l):this.consentStore.write(c,l),this.finishInit();return}o||this.showBanner(),this.finishInit()}showAgeGate(e,t){if(!this.renderer)return;let o=e.minimumAge,i=this.renderer.mount(this.config.rootEl);this.ageGate=new J;let a=this.ageGate.buildPrompt(o,()=>{this.resolveAgeGate(!0,e,t)},()=>{this.resolveAgeGate(!1,e,t)}),r=this.ageGate.getOverlay();r&&i.appendChild(r),i.appendChild(a)}async resolveAgeGate(e,t,o){if(this.ageGate?.remove(),this.ageGate=null,this._ageVerified=e,e){await this.continueInit(o,z(),!1);return}if(t.requireParentalConsent){if(this._parentalConsentToken=S("pcon"),await this.submitConsent(this._buildDenyAllConsent()),this.eventBus?.dispatch("consenti:parentalConsentRequired",{parentalConsentToken:this._parentalConsentToken,profileId:this.profileId(),visitorId:this.visitorId(),timestamp:Math.round(Date.now()/1e3)}),this.renderer){let i=this.renderer.mount(this.config.rootEl);this.ageGate=new J;let a=this.ageGate.buildParentalConsentMessage(()=>{this.ageGate?.remove(),this.ageGate=null});i.appendChild(a)}}else await this.submitConsent(this._buildDenyAllConsent());this.finishInit()}finishInit(){this.initialized=!0,this.readyResolve(),this.scannedScripts.push(...ce(this))}applyDirection(){if(!this.renderer)return;this.renderer.mount(this.config.rootEl).setAttribute("dir",ot(this.config.core.locale??"en",this.config.core.dir))}applyDarkMode(){if(!this.renderer)return;let e=this.config.darkMode??this.profile?.darkMode??!1,t=this.renderer.mount(this.config.rootEl);e?t.classList.add("consenti-root--dark"):t.classList.remove("consenti-root--dark")}applyAccessibility(){if(!this.renderer)return;let e=this.renderer.mount(this.config.rootEl);this.profile?.enhanceAccessibility?e.classList.add("consenti--enhanced-a11y"):e.classList.remove("consenti--enhanced-a11y")}_appendMetaFooter(e,t=!1){let o=document.createElement("div");o.className="consenti-meta-footer";let i=this.consentStore?.getConsentId();if(i){let r=document.createElement("span");r.className="consenti-meta-footer__item",r.innerHTML=`ID: <code class="consenti-meta-footer__id">${i.slice(0,8)}…</code>`,o.appendChild(r)}let a=this.consentStore?.getConsentDate();if(a){let r=document.createElement("span");r.className="consenti-meta-footer__item",r.textContent=`Date: ${a.toISOString().slice(0,10)}`,o.appendChild(r)}if(this.profile?.id){let r=document.createElement("span");r.className="consenti-meta-footer__item",r.textContent=`v${this.profile.id}`,o.appendChild(r)}if(!t){let r=document.createElement("button");r.type="button",r.className="consenti-meta-footer__settings",r.textContent="Privacy Settings",r.addEventListener("click",()=>this.showModal()),o.appendChild(r)}e.appendChild(o)}applyStackButtonsBreakpoint(){if(!this.renderer||!this.profile)return;let e=this.profile.mainBanner?.stackButtonsOnBreakpoint;if(!e||e<=0)return;let t=this.renderer.mount(this.config.rootEl);t.querySelector("#consenti-stack-btn-style")?.remove();let i=document.createElement("style");i.id="consenti-stack-btn-style",i.textContent=`@media(max-width:${e}px){.consenti-banner__buttons{flex-direction:column;}.consenti-banner__btn{width:100%;}}`,t.appendChild(i)}_installFocusTrap(e){this._removeFocusTrap();let t='button:not([disabled]),[href],input:not([disabled]),select,textarea,[tabindex]:not([tabindex="-1"])',o=i=>{if(i.key!=="Tab")return;let a=Array.from(e.querySelectorAll(t)).filter(s=>!s.closest('[aria-hidden="true"]'));if(a.length===0)return;let r=a[0],c=a[a.length-1];i.shiftKey?document.activeElement===r&&(i.preventDefault(),c.focus()):document.activeElement===c&&(i.preventDefault(),r.focus())};this._focusTrapListener=o,document.addEventListener("keydown",o)}_removeFocusTrap(){this._focusTrapListener&&(document.removeEventListener("keydown",this._focusTrapListener),this._focusTrapListener=null)}applyTheme(){let e=this.config.core.theme;if(!e||!this.renderer)return;let t={"--consenti-color-bg":e.bgColor,"--consenti-color-text":e.textColor,"--consenti-color-primary":e.primaryColor,"--consenti-color-primary-text":e.primaryTextColor,"--consenti-color-secondary":e.secondaryColor,"--consenti-color-secondary-text":e.secondaryTextColor,"--consenti-color-border":e.borderColor,"--consenti-font-family":e.fontFamily,"--consenti-font-size-base":e.fontSizeBase,"--consenti-font-size-heading":e.fontSizeHeading,"--consenti-border-radius":e.borderRadius,"--consenti-border-radius-btn":e.buttonBorderRadius,"--consenti-toggle-bg-on":e.toggleBgOn,"--consenti-toggle-bg-off":e.toggleBgOff,"--consenti-color-accent":e.accentColor,"--consenti-color-accent-text":e.accentTextColor},o=this.renderer.mount(this.config.rootEl);for(let[i,a]of Object.entries(t))a!==void 0&&o.style.setProperty(i,a);if(e.fontSizeMultiplier){let i=parseFloat(e.fontSizeMultiplier);if(!isNaN(i)){let a=parseFloat(getComputedStyle(o).getPropertyValue("--consenti-font-size-base")||"14"),r=parseFloat(getComputedStyle(o).getPropertyValue("--consenti-font-size-heading")||"16");o.style.setProperty("--consenti-font-size-base",`${Math.round(a*i)}px`),o.style.setProperty("--consenti-font-size-heading",`${Math.round(r*i)}px`)}}}async runPlugins(){this.plugins=this.config.plugins??[];for(let e of this.plugins)try{await e.initialize(this)}catch(t){P.warn("Plugin initialize error:",t)}}async callPluginHook(e){for(let t of this.plugins)try{await e(t,this)}catch(o){P.warn("Plugin hook failed:",o)}}_buildGrantAllConsent(e=!1){let t={};for(let o of Object.keys(this.profile?.cookies??{}))t[o]=e&&!G(o,this.categoryIndex)?"denied":"granted";return t}_buildDenyAllConsent(e=!1){let t={};for(let o of Object.keys(this.profile?.cookies??{}))t[o]=!e&&G(o,this.categoryIndex)?"granted":"denied";return t}buildHandlers(e){return{onGrantAll:()=>{this.submitConsent(this._buildGrantAllConsent()),e==="banner"&&(this.banner?.hide(),this._bannerVariant=null)},onDenyAll:()=>{this.submitConsent(this._buildDenyAllConsent()),e==="banner"&&(this.banner?.hide(),this._bannerVariant=null)},onSubmit:()=>{if(e==="modal"&&this.modal&&this.profile){let t=this.modal.getToggleConsent(this.profile.preferenceModal.categories);this.submitConsent(t),this.hideModal()}else{let t={};for(let o of Object.keys(this.profile?.cookies??{}))G(o,this.categoryIndex)&&(t[o]="granted");this.submitConsent(t),e==="banner"&&(this.banner?.hide(),this._bannerVariant=null)}},onManage:()=>{this.showModal()},onClose:()=>{e==="modal"?this.hideModal():(this.banner?.hide(),this.eventBus?.dispatch("consenti:bannerVisibility",{visible:!1,action:!0,variant:this._bannerVariant??"main"}),this._bannerVariant=null,this.broadcastChannel.send({type:"bannerClosed"}),this.callPluginHook(t=>t.onBannerHide?.()))},onGrantSpecific:t=>{let o={};for(let i of Object.keys(this.profile?.cookies??{}))G(i,this.categoryIndex)||t.includes(i)?o[i]="granted":o[i]="denied";this.submitConsent(o),e==="banner"&&this.hideBanner()}}}deriveAction(e,t){if(t)return"update";let o=Object.keys(this.profile?.cookies??{}).filter(r=>!G(r,this.categoryIndex));if(o.length===0)return"custom";let i=o.every(r=>e[r]==="granted"),a=o.every(r=>e[r]==="denied"||e[r]==="objected");return i?"accept_all":a?"reject_all":"custom"}handleBroadcastMessage(e){switch(e.type){case"consentUpdated":if(e.profileId!==this.profileId())return;this.consentStore?.setInMemory(e.consent),this.banner?.hide(),this.modal?.isOpen()&&this.modal.close(),this.eventBus?.dispatch("consenti:consentSubmitted",{consentJson:e.consent,fromBroadcast:!0,gpcDetected:z(),consentId:S("cons"),consentAction:this.deriveAction(e.consent,!1),pageUrl:window.location.href,visitorId:this.visitorId(),timestamp:Math.round(Date.now()/1e3),profileId:this.profileId()});break;case"bannerClosed":this.banner?.hide(),this._bannerVariant=null;break;case"consentDeleted":this.consentStore?.clearInMemory();break}}hasConsent(){return p()?this.consentStore?.hasConsent()??!1:!1}getConsent(e){if(!p())return null;let t=this.consentStore?.getConsent()??null;if(!t)return null;let o=this.profile?.cookies??{};switch(e){case"google-gtm":return q(t);case"category":return bn(t,o);case"adobe":return Cn(t,o);case"meta":return kn(t,o);case"microsoft-clarity":return Pn(t,o);case"twilio-segment":return _n(t,o);default:return t}}getConsentDate(){return p()?this.consentStore?.getConsentDate()??!1:!1}getGTMConsent(){return this.getConsent("google-gtm")}async submitConsent(e,t=!1,o=0){if(!p()||!this.profile||!this.consentStore)return;let i=this.profile.complianceGroup??"",a=this.consentStore.hasConsent(),r=this.consentStore.getConsentId()??S("cons"),c=window.location.href,s={};for(let[u,b]of Object.entries(this.profile.cookies))if(G(u,this.categoryIndex))s[u]="granted";else if(i==="opt-out-strict"){let _=b.cpraCategory==="sensitive"?"denied":"granted";s[u]=e[u]??_}else{let _=i!=="opt-out"&&i!=="notice-only",w=b.preGrant?"granted":_?"denied":"granted";s[u]=e[u]??w}let l=this.deriveAction(s,a);this.eventBus?.dispatch("consenti:consentBeingSubmitted",{consentJson:s,consentId:r,fromBroadcast:!1,gpcDetected:z(),consentAction:this.deriveAction(s,!1),pageUrl:window.location.href,visitorId:this.visitorId(),timestamp:Math.round(Date.now()/1e3),profileId:this.profileId()});let m=null;if(this.config.api?.enabled)try{let u=this.config.api.baseUrl??window.location.origin,{httpRequest:b}=await Promise.resolve().then(()=>(fe(),Ye));m=await b(`${u}/consenti/api/v1/consent`,{method:"POST",body:JSON.stringify({profileId:this.profileId(),visitorId:this.visitorId(),consentJson:s,locale:this.config.core.locale??"en",gpcDetected:t||z(),consentId:r,action:l,pageUrl:c,...this._ageVerified!==void 0?{ageVerified:this._ageVerified}:{},...this._parentalConsentToken?{parentalConsentToken:this._parentalConsentToken}:{}})},this.config.api.authToken)}catch(u){P.warn("API consent submission failed:",u)}let d=this.profile.cookieSigningKey??this.config.core.cookieSigningKey,y={source:o,gpcDetected:t,consentId:r,locale:this.config.core.locale??"en"};if(d?this.lastSignature=await this.consentStore.writeAndSign(s,d,y):this.consentStore.write(s,y),(this.modal?.isReceiptRequested()??!1)&&this.profile.allowReceipt){let u=this.visitorId(),b=this.consentStore.getConsent();console.log({currentConsentVersion:b});let _={version:"1.0",visitorId:u,profileId:this.profileId(),locale:this.config.core.locale??"en",consent:s,...this.lastSignature?{signature:this.lastSignature}:{}},w=xn(_);wn(w)}return this.broadcastChannel.send({type:"consentUpdated",consent:s,profileId:this.profileId()}),this.eventBus?.dispatch("consenti:consentSubmitted",{consentJson:s,apiResponse:m,gpcDetected:t,consentId:r,consentAction:l,pageUrl:c,fromBroadcast:!1,visitorId:this.visitorId(),timestamp:Math.round(Date.now()/1e3),profileId:this.profileId()}),await this.callPluginHook(u=>u.onConsentSubmit?.(s)),this.renderer?.announceToScreenReader("Your cookie preferences have been saved."),this.hideBanner(),this.modal?.isOpen()&&this.hideModal(),m}bannerVisibility(){return this._bannerVariant??!1}modalVisibility(){return this.modal?.isOpen()?"preference":!1}showBanner(e=!1){if(!p()||!this.profile||!this.banner||!this.renderer)return;let t=e&&this.profile.gpcBanner?"gpc":"main";if(this._bannerVariant===t)return;if(this._bannerMounted===t){this.banner.show(),this._bannerVariant=t,this.eventBus?.dispatch("consenti:bannerVisibility",{visible:!0,action:!1,variant:t}),this.callPluginHook(m=>m.onBannerShow?.());return}let o=t==="gpc"?this.profile.gpcBanner:this.profile.mainBanner,i=this.renderer.mount(this.config.rootEl),a=this.buildHandlers("banner");this.banner.remove();let r=this.profile.locales,c=this.config.core.locale??"en",s=this.banner.build(o,a,void 0,r,c,m=>this.switchLocale(m),this.config.hidePoweredBy??this.profile?.hidePoweredBy??!0,t);this.profile.showFooterMetadata&&this._appendMetaFooter(s),i.appendChild(s);let l=this.banner.getOverlay();l&&i.appendChild(l),this._bannerVariant=t,this._bannerMounted=t,this.eventBus?.dispatch("consenti:bannerVisibility",{visible:!0,action:!1,variant:t}),this.callPluginHook(m=>m.onBannerShow?.())}hideBanner(){this._bannerVariant!==null&&(this.banner?.hide(),this.eventBus?.dispatch("consenti:bannerVisibility",{visible:!1,action:!0,variant:this._bannerVariant}),this._bannerVariant=null,this.broadcastChannel.send({type:"bannerClosed"}),this.renderer?.announceToScreenReader("Cookie banner dismissed."),this.callPluginHook(e=>e.onBannerHide?.()))}showModal(e){if(!p()||!this.profile||!this.modal||this.modal.isOpen())return;let t=this.buildHandlers("modal"),o=this.consentStore?.getConsent()??{},i=this.profile.complianceGroup==="opt-in-dpdpa"?this.profile.dpdpa:void 0,a=this.profile.locales,r=this.config.core.locale??"en";this.modal.build(this.profile.preferenceModal,this.profile.cookies,o,t,this.profile.allowReceipt??!1,i,a,r,s=>{this.hideModal(),this.switchLocale(s)},this.config.hidePoweredBy??!0),this.banner?.hide(),this.modal.open(e,this.renderer?.mount(this.config.rootEl));let c=document.getElementById("consenti-modal");if(this.profile.showFooterMetadata&&c){let s=c.querySelector(".consenti-modal__container");s&&this._appendMetaFooter(s,!0)}this.profile.preferenceModal?.trapFocus&&c&&this._installFocusTrap(c),this._bannerVariant!==null&&this.eventBus?.dispatch("consenti:bannerVisibility",{visible:!1,action:!!e,variant:this._bannerVariant}),this.eventBus?.dispatch("consenti:modalVisibility",{visible:!0,action:!!e}),this.callPluginHook(s=>s.onModalShow?.())}hideModal(){this.modal?.isOpen()&&(this._removeFocusTrap(),this.modal.close(),this.eventBus?.dispatch("consenti:modalVisibility",{visible:!1,action:!0}),this.callPluginHook(e=>e.onModalHide?.()),!this.consentStore?.hasConsent()&&this._bannerVariant!==null?(this.eventBus?.dispatch("consenti:bannerVisibility",{visible:!0,action:!0,variant:this._bannerVariant}),this.banner?.show()):this.consentStore?.hasConsent()||this.showBanner())}onReady(e){this.initialized?e():this.readyPromise.then(e)}get ready(){return this.readyPromise}async deleteConsent(){if(!(!p()||!this.consentStore)){if(this.config.api?.enabled)try{let e=this.config.api.baseUrl??window.location.origin,{httpRequest:t}=await Promise.resolve().then(()=>(fe(),Ye));await t(`${e}/consenti/api/v1/consent/${this.visitorId()}`,{method:"DELETE"},this.config.api?.authToken)}catch(e){P.warn("API consent deletion failed:",e)}this.consentStore.delete(),this.broadcastChannel.send({type:"consentDeleted"})}}async reConsent(){await this.deleteConsent(),this.showBanner()}getProfile(){return this.profile}getRootElement(){return p()?this.config.rootEl?typeof this.config.rootEl=="string"?document.querySelector(this.config.rootEl):this.config.rootEl:document.getElementById("consenti-root"):null}getBannerElement(){return p()?document.getElementById("consenti-banner"):null}getModalElement(){return p()?document.getElementById("consenti-modal"):null}switchLocale(e){p()&&(this.config.core.locale=e,this.banner?.remove(),this.modal?.isOpen()&&this.modal.close(),this._bannerVariant=null,this._bannerMounted=null,this.profile=null,this.initialized=!1,this.readyPromise=new Promise(t=>{this.readyResolve=t}),this.init().catch(t=>P.warn("Locale switch error:",t)))}isCookieGranted(e,t=!1){if(!p())return!1;let o=this.getConsent()?.[e];return t?o??!1:o==="granted"}isCategoryGranted(e,t=!1){if(!p()||!this.profile)return t?[]:!1;let o=this.profile.preferenceModal.categories[e];if(!o)return t?[]:!1;let i=this.getConsent();return t?o.cookies.map(a=>({[a]:i?.[a]??"denied"})):o.cookies.every(a=>i?.[a]==="granted")}async grantAll(e=!1){!p()||!this.profile||await this.submitConsent(this._buildGrantAllConsent(e),!1,1)}async denyAll(e=!1){!p()||!this.profile||(e&&P.warn("denyAll called with includingMandatory=true \u2014 mandatory cookies will be denied. Ensure this is intentional."),await this.submitConsent(this._buildDenyAllConsent(e),!1,1))}on(e,t){if(!p())return;let o=e.startsWith("consenti:")?e:`consenti:${e}`,i=r=>t(r.detail),a=this._eventHandlers.get(t)??[];a.push({name:o,wrapped:i}),this._eventHandlers.set(t,a),window.addEventListener(o,i)}off(e,t){if(!p())return;let o=e.startsWith("consenti:")?e:`consenti:${e}`,i=this._eventHandlers.get(t);if(!i)return;let a=i.findIndex(c=>c.name===o);if(a===-1)return;let r=i[a];r&&window.removeEventListener(o,r.wrapped),i.splice(a,1),i.length===0&&this._eventHandlers.delete(t)}version(){return{package:"0.3.0",profileVersion:this.profile?.id??"0",consentVersion:null}}setDarkMode(e){p()&&(this.config.darkMode=e===void 0?!this.config.darkMode:e,this.applyDarkMode())}setTheme(e){p()&&(this.config.core.theme=Object.assign({},this.config.core.theme,e),this.applyTheme())}setConfig(e){let t=M(this.config,e);this.config={...t,core:t.core??{}},p()&&(this.applyTheme(),this.applyDarkMode())}setProfile(e){if(!p()||!this.resolvedBase)return;this.config.profileOverride=this.config.profileOverride?M(this.config.profileOverride,e):e,this.profile=M(this.resolvedBase,this.config.profileOverride),this.categoryIndex=H(this.profile.preferenceModal.categories);let t=this.modal?.isOpen()??!1;if(t&&this.modal?.close(),this._bannerVariant!==null){let o=this._bannerVariant==="gpc";this._bannerVariant=null,this._bannerMounted=null,this.showBanner(o)}t&&this.showModal()}destroy(){this._removeFocusTrap();for(let e of this.plugins)try{e.destroy()}catch{}for(let e of this.scannedScripts)e.destroy();if(this.scannedScripts=[],this.modal?.destroy(),this.renderer?.unmount(),this.broadcastChannel.disconnect(),p()){for(let e of this._eventHandlers.values())for(let{name:t,wrapped:o}of e)window.removeEventListener(t,o);this._eventHandlers.clear()}this.banner=null,this.modal=null,this.renderer=null,this.consentStore=null,this.eventBus=null,this.initialized=!1}};var _e=class{};var Uo=1e3,xe=class{constructor(e){this.config=e;this.type=Symbol(e.id??Uo++),Nn(this.type,e)}getType(){return this.type}toJSON(){return this.config}};var we=class{constructor(e){this.options=e;this.granted=null;this.handler=()=>this.evaluate(),p()&&(e.bind!==!1&&window.addEventListener("consenti:consentSubmitted",this.handler),this.evaluate())}evaluate(){let e=this.options.widget.getConsent(),t=e?.[this.options.id]??"denied",o=t==="granted";if(o===this.granted)return;this.granted=o;let i=this.options.widget.getProfile()?.cookies[this.options.id],a={cookieId:this.options.id,status:t,cookie:i,consent:e};o?this.options.onGrant?.(a):this.options.onDeny?.(a)}destroy(){p()&&this.options.bind!==!1&&window.removeEventListener("consenti:consentSubmitted",this.handler)}};var Ae=class{constructor(e){this.options=e;this.granted=null;this.handler=()=>this.evaluate(),p()&&(e.bind!==!1&&window.addEventListener("consenti:consentSubmitted",this.handler),this.evaluate())}evaluate(){let t=this.options.widget.getProfile()?.preferenceModal.categories[this.options.id]?.cookies??[],o=this.options.widget.getConsent(),i=t.length>0&&t.every(r=>o?.[r]==="granted");if(i===this.granted)return;this.granted=i;let a={categoryId:this.options.id,cookieIds:t,consent:o};i?this.options.onGrant?.(a):this.options.onDeny?.(a)}destroy(){p()&&this.options.bind!==!1&&window.removeEventListener("consenti:consentSubmitted",this.handler)}};var Te=class{constructor(e){let t=e.action??"modal";if(this.clickHandler=()=>{t==="modal"?e.widget.showModal():e.widget.showBanner()},e.el)if(typeof e.el=="string"){if(!p()){this.el=document.createElement("span"),this.created=!1;return}let o=document.querySelector(e.el);if(!o)throw new Error(`[Consenti] BannerTrigger: element not found for selector "${e.el}"`);this.el=o,this.created=!1}else this.el=e.el,this.created=!1;else{let o=document.createElement("button");o.type="button",o.className="consenti-btn consenti-btn--text consenti-banner-trigger",o.textContent=e.label??"Cookie Settings",o.setAttribute("aria-label",e.label??"Open cookie settings"),this.el=o,this.created=!0}this.el.addEventListener("click",this.clickHandler)}getElement(){return this.el}destroy(){this.el.removeEventListener("click",this.clickHandler),this.created&&this.el.remove()}};return oo(qo);})();
|
|
2305
2
|
//# sourceMappingURL=index.umd.js.map
|