UNPKG

c15t

Version:

Headless JavaScript consent management platform for cookie banners, privacy preferences, consent storage, and script gating.

4,312 lines 183 kB
"use strict";
var __webpack_require__ = {};
(()=>{
    __webpack_require__.d = (exports1, getters, values)=>{
        var define = (defs, kind)=>{
            for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
                enumerable: true,
                [kind]: defs[key]
            });
        };
        define(getters, "get");
        define(values, "value");
    };
})();
(()=>{
    __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
})();
(()=>{
    __webpack_require__.r = (exports1)=>{
        if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
            value: 'Module'
        });
        Object.defineProperty(exports1, '__esModule', {
            value: true
        });
    };
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
    API_ENDPOINTS: ()=>API_ENDPOINTS,
    C15tClient: ()=>C15tClient,
    CustomClient: ()=>CustomClient,
    OfflineClient: ()=>OfflineClient,
    allConsentNames: ()=>allConsentNames,
    applyPolicyPurposeAllowlist: ()=>applyPolicyPurposeAllowlist,
    applyPolicyScopeForRuntimeGating: ()=>applyPolicyScopeForRuntimeGating,
    buildPrefetchScript: ()=>buildPrefetchScript,
    clearClientRegistry: ()=>clearClientRegistry,
    clearConsentRuntimeCache: ()=>clearConsentRuntimeCache,
    configureConsentManager: ()=>configureConsentManager,
    consentTypes: ()=>consent_types_consentTypes,
    createConsentManagerStore: ()=>createConsentManagerStore,
    createIframeBlocker: ()=>createIframeBlocker,
    deepMergeTranslations: ()=>translations_namespaceObject.deepMergeTranslations,
    defaultTranslationConfig: ()=>defaultTranslationConfig,
    deleteConsentFromStorage: ()=>deleteConsentFromStorage,
    deleteCookie: ()=>deleteCookie,
    detectBrowserLanguage: ()=>translations_namespaceObject.detectBrowserLanguage,
    emitScriptDebugEvent: ()=>emitScriptDebugEvent,
    filterConsentCategoriesByPolicy: ()=>filterConsentCategoriesByPolicy,
    flattenPolicyActionGroups: ()=>flattenPolicyActionGroups,
    generateSubjectId: ()=>generateSubjectId,
    getConsentFromStorage: ()=>getConsentFromStorage,
    getCookie: ()=>getCookie,
    getEffectivePolicy: ()=>getEffectivePolicy,
    getLoadedScriptIds: ()=>getLoadedScriptIds,
    getOrCreateConsentRuntime: ()=>getOrCreateConsentRuntime,
    getRootDomain: ()=>getRootDomain,
    has: ()=>has,
    hasPolicyHints: ()=>hasPolicyHints,
    isScriptLoaded: ()=>isScriptLoaded,
    isValidSubjectId: ()=>isValidSubjectId,
    loadScripts: ()=>loadScripts,
    mergeTranslationConfigs: ()=>translations_namespaceObject.mergeTranslationConfigs,
    policyPackPresets: ()=>types_namespaceObject.policyPackPresets,
    prepareTranslationConfig: ()=>translations_namespaceObject.prepareTranslationConfig,
    resolvePolicyActionGroups: ()=>resolvePolicyActionGroups,
    resolvePolicyAllowedActions: ()=>resolvePolicyAllowedActions,
    resolvePolicyDirection: ()=>resolvePolicyDirection,
    resolvePolicyOrderedActions: ()=>resolvePolicyOrderedActions,
    resolvePolicyPrimaryActions: ()=>resolvePolicyPrimaryActions,
    resolvePolicyUiProfile: ()=>resolvePolicyUiProfile,
    saveConsentToStorage: ()=>saveConsentToStorage,
    setCookie: ()=>setCookie,
    shouldFillPolicyActions: ()=>shouldFillPolicyActions,
    subscribeToScriptDebugEvents: ()=>subscribeToScriptDebugEvents,
    unloadScripts: ()=>unloadScripts,
    updateScripts: ()=>core_updateScripts,
    validateUIAgainstPolicy: ()=>validateUIAgainstPolicy
});
const types_namespaceObject = require("@c15t/schema/types");
const translations_namespaceObject = require("@c15t/translations");
const LEADING_SLASHES_REGEX = /^\/+/;
function createResponseContext(isSuccess, data = null, error = null, response = null) {
    return {
        data,
        error,
        ok: isSuccess,
        response
    };
}
function createErrorResponse(message, status = 500, code = 'ERROR', cause) {
    return createResponseContext(false, null, {
        message,
        status,
        code,
        cause
    }, null);
}
function utils_createErrorResponse(message, status = 500, code = 'HANDLER_ERROR', cause) {
    return createErrorResponse(message, status, code, cause);
}
async function executeHandler(endpointHandlers, handlerKey, options) {
    const handler = endpointHandlers[handlerKey];
    if (!handler) {
        const errorResponse = utils_createErrorResponse(`No endpoint handler found for '${String(handlerKey)}'`, 404, 'ENDPOINT_NOT_FOUND');
        if (options?.throw) throw new Error(`No endpoint handler found for '${String(handlerKey)}'`);
        return errorResponse;
    }
    try {
        const response = await handler(options);
        const normalizedResponse = {
            data: response.data,
            error: response.error,
            ok: response.ok ?? !response.error,
            response: response.response
        };
        return normalizedResponse;
    } catch (error) {
        const errorResponse = utils_createErrorResponse(error instanceof Error ? error.message : String(error), 0, 'HANDLER_ERROR', error);
        if (options?.throw) throw error;
        return errorResponse;
    }
}
async function customFetch(endpointHandlers, dynamicHandlers, path, options) {
    const endpointName = path.replace(LEADING_SLASHES_REGEX, '').split('/')[0];
    const handler = dynamicHandlers[path];
    if (handler) try {
        return await handler(options);
    } catch (error) {
        const errorResponse = utils_createErrorResponse(error instanceof Error ? error.message : String(error), 0, 'HANDLER_ERROR', error);
        return errorResponse;
    }
    if (!endpointName || !(endpointName in endpointHandlers)) {
        const errorResponse = utils_createErrorResponse(`No endpoint handler found for '${path}'`, 404, 'ENDPOINT_NOT_FOUND');
        return errorResponse;
    }
    return await executeHandler(endpointHandlers, endpointName, options);
}
async function init_init(endpointHandlers, options) {
    const handlerKey = 'init' in endpointHandlers && void 0 !== endpointHandlers.init ? 'init' : 'init';
    return await executeHandler(endpointHandlers, handlerKey, options);
}
async function setConsent(endpointHandlers, options) {
    return await executeHandler(endpointHandlers, 'setConsent', options);
}
class CustomClient {
    endpointHandlers;
    dynamicHandlers = {};
    constructor(options){
        this.endpointHandlers = options.endpointHandlers;
    }
    async init(options) {
        return init_init(this.endpointHandlers, options);
    }
    async setConsent(options) {
        return setConsent(this.endpointHandlers, options);
    }
    async identifyUser(options) {
        if (this.endpointHandlers.identifyUser) return this.endpointHandlers.identifyUser(options);
        const subjectId = options.body?.id;
        if (!subjectId) return {
            ok: false,
            data: null,
            response: null,
            error: {
                message: 'Subject ID is required to identify user',
                status: 400,
                code: 'MISSING_SUBJECT_ID'
            }
        };
        return this.$fetch(`/subjects/${subjectId}`, {
            ...options,
            method: 'PATCH'
        });
    }
    registerHandler(path, handler) {
        this.dynamicHandlers[path] = handler;
    }
    async $fetch(path, options) {
        return customFetch(this.endpointHandlers, this.dynamicHandlers, path, options);
    }
}
const DEFAULT_RETRY_CONFIG = {
    maxRetries: 3,
    initialDelayMs: 100,
    backoffFactor: 2,
    retryableStatusCodes: [
        500,
        502,
        503,
        504
    ],
    nonRetryableStatusCodes: [
        400,
        401,
        403,
        404
    ],
    retryOnNetworkError: true,
    shouldRetry: void 0
};
const ABSOLUTE_URL_REGEX = /^(?:[a-z+]+:)?\/\//i;
const constants_LEADING_SLASHES_REGEX = LEADING_SLASHES_REGEX;
const noop = ()=>{};
function createDebugLogger(enabled) {
    if (!enabled) return {
        log: noop,
        debug: noop
    };
    return {
        log: (...args)=>console.log('[c15t]', ...args),
        debug: (...args)=>console.debug('[c15t]', ...args)
    };
}
let _debugLogger = createDebugLogger(false);
function getDebugLogger() {
    return _debugLogger;
}
function setDebugEnabled(enabled) {
    _debugLogger = createDebugLogger(enabled);
}
const C15T_VERSION_HEADER = 'x-c15t-version';
const headers_C15T_VERSION_HEADERS = {
    [C15T_VERSION_HEADER]: "2.2.1"
};
const delay = (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
function getIdentifySubjectId(submission) {
    return submission?.subjectId || submission?.id;
}
function generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c)=>{
        const r = 16 * Math.random() | 0;
        const v = 'x' === c ? r : 0x3 & r | 0x8;
        return v.toString(16);
    });
}
function removeTrailingSlashes(str) {
    let i = str.length;
    while(i > 0 && '/' === str[i - 1])i--;
    return str.slice(0, i);
}
function resolveUrl(backendURL, path) {
    if (ABSOLUTE_URL_REGEX.test(backendURL)) {
        const backendURLObj = new URL(backendURL);
        const basePath = removeTrailingSlashes(backendURLObj.pathname);
        const cleanPath = path.replace(constants_LEADING_SLASHES_REGEX, '');
        const newPath = `${basePath}/${cleanPath}`;
        backendURLObj.pathname = newPath;
        return backendURLObj.toString();
    }
    const cleanBase = removeTrailingSlashes(backendURL);
    const cleanPath = path.replace(constants_LEADING_SLASHES_REGEX, '');
    return `${cleanBase}/${cleanPath}`;
}
const fetcher_createResponseContext = createResponseContext;
async function fetcher(context, path, options) {
    const finalRetryConfig = {
        ...context.retryConfig,
        ...options?.retryConfig || {},
        retryableStatusCodes: options?.retryConfig?.retryableStatusCodes ?? context.retryConfig.retryableStatusCodes ?? DEFAULT_RETRY_CONFIG.retryableStatusCodes,
        nonRetryableStatusCodes: options?.retryConfig?.nonRetryableStatusCodes ?? context.retryConfig.nonRetryableStatusCodes ?? DEFAULT_RETRY_CONFIG.nonRetryableStatusCodes
    };
    const { maxRetries, initialDelayMs, backoffFactor, retryableStatusCodes, nonRetryableStatusCodes, retryOnNetworkError } = finalRetryConfig;
    let attemptsMade = 0;
    let currentDelay = initialDelayMs;
    let lastErrorResponse = null;
    while(attemptsMade <= (maxRetries ?? 0)){
        const requestId = generateUUID();
        const fetchImpl = context.customFetch || globalThis.fetch;
        const resolvedUrl = resolveUrl(context.backendURL, path);
        let url;
        try {
            url = new URL(resolvedUrl);
        } catch  {
            url = new URL(resolvedUrl, window.location.origin);
        }
        if (options?.query) {
            for (const [key, value] of Object.entries(options.query))if (void 0 !== value) url.searchParams.append(key, String(value));
        }
        const requestOptions = {
            method: options?.method || 'GET',
            mode: context.corsMode,
            credentials: 'include',
            headers: {
                ...headers_C15T_VERSION_HEADERS,
                ...context.headers,
                'X-Request-ID': requestId,
                ...options?.headers
            },
            ...options?.fetchOptions
        };
        if (options?.body && 'GET' !== requestOptions.method) requestOptions.body = JSON.stringify(options.body);
        try {
            const response = await fetchImpl(url.toString(), requestOptions);
            let data = null;
            let parseError = null;
            try {
                const contentType = response.headers.get('content-type');
                if (contentType?.includes('application/json') && 204 !== response.status && '0' !== response.headers.get('content-length')) data = await response.json();
                else if (204 === response.status) data = null;
            } catch (err) {
                parseError = err;
            }
            if (parseError) {
                const errorResponse = fetcher_createResponseContext(false, null, {
                    message: 'Failed to parse response',
                    status: response.status,
                    code: 'PARSE_ERROR',
                    cause: parseError
                }, response);
                options?.onError?.(errorResponse, path);
                if (options?.throw) throw new Error('Failed to parse response');
                return errorResponse;
            }
            const isSuccess = response.status >= 200 && response.status < 300;
            if (isSuccess) {
                const successResponse = fetcher_createResponseContext(true, data, null, response);
                options?.onSuccess?.(successResponse);
                return successResponse;
            }
            const errorData = data;
            const errorResponse = fetcher_createResponseContext(false, null, {
                message: errorData?.message || `Request failed with status ${response.status}`,
                status: response.status,
                code: errorData?.code || 'API_ERROR',
                details: errorData?.details || null
            }, response);
            lastErrorResponse = errorResponse;
            let shouldRetryThisRequest = false;
            if (nonRetryableStatusCodes?.includes(response.status)) {
                getDebugLogger().debug(`Not retrying request to ${path} with status ${response.status} (nonRetryableStatusCodes)`);
                shouldRetryThisRequest = false;
            } else if ('function' == typeof finalRetryConfig.shouldRetry) try {
                shouldRetryThisRequest = finalRetryConfig.shouldRetry(response, {
                    attemptsMade,
                    url: url.toString(),
                    method: requestOptions.method || 'GET'
                });
                getDebugLogger().debug(`Custom retry strategy for ${path} with status ${response.status}: ${shouldRetryThisRequest}`);
            } catch  {
                shouldRetryThisRequest = retryableStatusCodes?.includes(response.status) ?? false;
                getDebugLogger().debug(`Custom retry strategy failed, falling back to status code check: ${shouldRetryThisRequest}`);
            }
            else {
                shouldRetryThisRequest = retryableStatusCodes?.includes(response.status) ?? false;
                getDebugLogger().debug(`Standard retry check for ${path} with status ${response.status}: ${shouldRetryThisRequest}`);
            }
            if (!shouldRetryThisRequest || attemptsMade >= (maxRetries ?? 0)) {
                options?.onError?.(errorResponse, path);
                if (options?.throw) throw new Error(errorResponse.error?.message || 'Request failed');
                return errorResponse;
            }
            attemptsMade++;
            await delay(currentDelay ?? 0);
            currentDelay = (currentDelay ?? 0) * (backoffFactor ?? 2);
        } catch (fetchError) {
            if (fetchError && 'Failed to parse response' === fetchError.message) throw fetchError;
            const isNetworkError = !(fetchError instanceof Response);
            const errorResponse = fetcher_createResponseContext(false, null, {
                message: fetchError instanceof Error ? fetchError.message : String(fetchError),
                status: 0,
                code: 'NETWORK_ERROR',
                cause: fetchError
            }, null);
            lastErrorResponse = errorResponse;
            const shouldRetryThisRequest = isNetworkError && retryOnNetworkError;
            if (!shouldRetryThisRequest || attemptsMade >= (maxRetries ?? 0)) {
                options?.onError?.(errorResponse, path);
                if (options?.throw) throw fetchError;
                return errorResponse;
            }
            attemptsMade++;
            await delay(currentDelay ?? 0);
            currentDelay = (currentDelay ?? 0) * (backoffFactor ?? 2);
        }
    }
    const maxRetriesErrorResponse = lastErrorResponse || fetcher_createResponseContext(false, null, {
        message: `Request failed after ${maxRetries} retries`,
        status: 0,
        code: 'MAX_RETRIES_EXCEEDED'
    }, null);
    options?.onError?.(maxRetriesErrorResponse, path);
    if (options?.throw) throw new Error(`Request failed after ${maxRetries} retries`);
    return maxRetriesErrorResponse;
}
function getDefaultCookieOptions(config) {
    return {
        expiryDays: config?.defaultExpiryDays ?? 365,
        crossSubdomain: config?.crossSubdomain ?? false,
        domain: config?.defaultDomain ?? '',
        path: '/',
        secure: "u" > typeof window && 'https:' === window.location.protocol,
        sameSite: 'Lax'
    };
}
function getRootDomain() {
    if ("u" < typeof window) return '';
    const hostname = window.location.hostname;
    if ('localhost' === hostname || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) return hostname;
    const parts = hostname.split('.');
    if (parts.length >= 2) return `.${parts.slice(-2).join('.')}`;
    return hostname;
}
const COOKIE_KEY_MAP = {
    consents: 'c',
    consentInfo: 'i',
    timestamp: 'ts',
    iabCustomVendorConsents: 'icv',
    iabCustomVendorLegitimateInterests: 'icvli',
    time: 't',
    type: 'y',
    id: 'id',
    subjectId: 'sid',
    externalId: 'eid',
    materialPolicyFingerprint: 'mpf',
    identityProvider: 'idp'
};
const REVERSE_COOKIE_KEY_MAP = Object.entries(COOKIE_KEY_MAP).reduce((acc, [key, value])=>{
    acc[value] = key;
    return acc;
}, {});
function shortenFlatKeys(flattened) {
    const shortened = {};
    for (const [key, value] of Object.entries(flattened)){
        const keys = key.split('.');
        const shortenedKeys = keys.map((k)=>COOKIE_KEY_MAP[k] || k);
        shortened[shortenedKeys.join('.')] = value;
    }
    return shortened;
}
function expandFlatKeys(shortened) {
    const expanded = {};
    for (const [key, value] of Object.entries(shortened)){
        const keys = key.split('.');
        const expandedKeys = keys.map((k)=>REVERSE_COOKIE_KEY_MAP[k] || k);
        expanded[expandedKeys.join('.')] = value;
    }
    return expanded;
}
function flattenObject(obj, prefix = '') {
    const flattened = {};
    for (const [key, value] of Object.entries(obj)){
        const newKey = prefix ? `${prefix}.${key}` : key;
        if (null == value) flattened[newKey] = '';
        else if ('boolean' == typeof value) {
            if (value) flattened[newKey] = '1';
        } else if ('object' != typeof value || Array.isArray(value)) flattened[newKey] = String(value);
        else Object.assign(flattened, flattenObject(value, newKey));
    }
    return flattened;
}
function unflattenObject(flattened) {
    const result = {};
    for (const [key, value] of Object.entries(flattened)){
        const keys = key.split('.');
        if (0 === keys.length) continue;
        let current = result;
        for(let i = 0; i < keys.length - 1; i++){
            const k = keys[i];
            if (void 0 !== k) {
                if (!current[k]) current[k] = {};
                current = current[k];
            }
        }
        const lastKey = keys[keys.length - 1];
        if (void 0 !== lastKey) if ('1' === value) current[lastKey] = true;
        else if ('0' === value) current[lastKey] = false;
        else if ('' === value) current[lastKey] = null;
        else if (Number.isNaN(Number(value)) || '' === value) current[lastKey] = value;
        else current[lastKey] = Number(value);
    }
    return result;
}
function flatToString(flattened) {
    return Object.entries(flattened).map(([key, value])=>`${key}:${value}`).join(',');
}
function stringToFlat(str) {
    if (!str) return {};
    const result = {};
    const pairs = str.split(',');
    for (const pair of pairs){
        const colonIndex = pair.indexOf(':');
        if (-1 === colonIndex) continue;
        const key = pair.substring(0, colonIndex);
        const value = pair.substring(colonIndex + 1);
        result[key] = value;
    }
    return result;
}
function setCookie(name, value, options, config) {
    if ("u" < typeof document) return;
    const opts = {
        ...getDefaultCookieOptions(config),
        ...options
    };
    if (opts.crossSubdomain && !options?.domain) opts.domain = getRootDomain();
    try {
        let cookieValue;
        if ('string' == typeof value) cookieValue = value;
        else {
            const flattened = flattenObject(value);
            const shortened = shortenFlatKeys(flattened);
            cookieValue = flatToString(shortened);
        }
        const date = new Date();
        date.setTime(date.getTime() + 24 * opts.expiryDays * 3600000);
        const expires = `expires=${date.toUTCString()}`;
        const parts = [
            `${name}=${cookieValue}`,
            expires,
            `path=${opts.path}`
        ];
        if (opts.domain) parts.push(`domain=${opts.domain}`);
        if (opts.secure) parts.push('secure');
        if (opts.sameSite) parts.push(`SameSite=${opts.sameSite}`);
        document.cookie = parts.join('; ');
    } catch (error) {
        console.warn(`Failed to set cookie "${name}":`, error);
    }
}
function getCookie(name) {
    if ("u" < typeof document) return null;
    try {
        const nameEQ = `${name}=`;
        const cookies = document.cookie.split(';');
        for (const cookie of cookies){
            let c = cookie;
            while(' ' === c.charAt(0))c = c.substring(1);
            if (0 === c.indexOf(nameEQ)) {
                const cookieValue = c.substring(nameEQ.length);
                if (cookieValue.includes(':')) {
                    const shortened = stringToFlat(cookieValue);
                    const expanded = expandFlatKeys(shortened);
                    const nested = unflattenObject(expanded);
                    return nested;
                }
                return cookieValue;
            }
        }
        return null;
    } catch (error) {
        console.warn(`Failed to get cookie "${name}":`, error);
        return null;
    }
}
function deleteCookie(name, options, config) {
    if ("u" < typeof document) return;
    const opts = {
        ...getDefaultCookieOptions(config),
        ...options
    };
    if (opts.crossSubdomain && !options?.domain) opts.domain = getRootDomain();
    try {
        const parts = [
            `${name}=`,
            'expires=Thu, 01 Jan 1970 00:00:00 GMT',
            `path=${opts.path}`
        ];
        if (opts.domain) parts.push(`domain=${opts.domain}`);
        document.cookie = parts.join('; ');
    } catch (error) {
        console.warn(`Failed to delete cookie "${name}":`, error);
    }
}
const defaultTranslationConfig = {
    translations: {
        en: translations_namespaceObject.enTranslations
    },
    defaultLanguage: 'en',
    disableAutoLanguageSwitch: false
};
const consent_types_consentTypes = [
    {
        defaultValue: true,
        description: 'These trackers are used for activities that are strictly necessary to operate or deliver the service you requested from us and, therefore, do not require you to consent.',
        disabled: true,
        display: true,
        gdprType: 1,
        name: 'necessary'
    },
    {
        defaultValue: false,
        description: 'These trackers enable basic interactions and functionalities that allow you to access selected features of our service and facilitate your communication with us.',
        display: false,
        gdprType: 2,
        name: 'functionality'
    },
    {
        defaultValue: false,
        description: 'These trackers help us to measure traffic and analyze your behavior to improve our service.',
        display: false,
        gdprType: 4,
        name: 'measurement'
    },
    {
        defaultValue: false,
        description: 'These trackers help us to improve the quality of your user experience and enable interactions with external content, networks, and platforms.',
        display: false,
        gdprType: 3,
        name: 'experience'
    },
    {
        defaultValue: false,
        description: 'These trackers help us to deliver personalized ads or marketing content to you, and to measure their performance.',
        display: false,
        gdprType: 5,
        name: 'marketing'
    }
];
const allConsentNames = consent_types_consentTypes.map((consent)=>consent.name);
const STORAGE_KEY = 'privacy-consent-storage';
const initial_state_initialState = {
    debug: false,
    config: {
        pkg: 'c15t',
        version: "2.2.1",
        mode: 'Unknown'
    },
    consents: consent_types_consentTypes.reduce((acc, consent)=>{
        acc[consent.name] = consent.defaultValue;
        return acc;
    }, {}),
    selectedConsents: consent_types_consentTypes.reduce((acc, consent)=>{
        acc[consent.name] = consent.defaultValue;
        return acc;
    }, {}),
    consentInfo: null,
    branding: 'c15t',
    activeUI: 'none',
    isLoadingConsentInfo: false,
    hasFetchedBanner: false,
    lastBannerFetchData: null,
    consentCategories: [
        'necessary'
    ],
    callbacks: {},
    locationInfo: null,
    overrides: void 0,
    legalLinks: {},
    translationConfig: defaultTranslationConfig,
    user: void 0,
    networkBlocker: void 0,
    storageConfig: void 0,
    includeNonDisplayedConsents: false,
    consentTypes: consent_types_consentTypes,
    iframeBlockerConfig: {
        disableAutomaticBlocking: false
    },
    scripts: [],
    loadedScripts: {},
    scriptIdMap: {},
    model: 'opt-in',
    policyBanner: {},
    policyDialog: {},
    policyCategories: null,
    policyScopeMode: null,
    initDataSource: null,
    initDataSourceDetail: null,
    iab: null,
    reloadOnConsentRevoked: true,
    ssrDataUsed: false,
    ssrSkippedReason: null
};
function sanitizeIdentifier(value) {
    if ('string' != typeof value) return;
    const normalized = value.trim();
    if ('' === normalized || 'undefined' === normalized || 'null' === normalized) return;
    return normalized;
}
function sanitizeSubjectIdentifiers(identifiers) {
    const externalId = sanitizeIdentifier(identifiers.externalId);
    const identityProvider = sanitizeIdentifier(identifiers.identityProvider);
    return {
        ...externalId ? {
            externalId
        } : {},
        ...identityProvider ? {
            identityProvider
        } : {}
    };
}
function sanitizeConsentInfo(consentInfo) {
    if (!consentInfo) return consentInfo;
    const sanitized = {
        ...consentInfo
    };
    const { externalId, identityProvider } = sanitizeSubjectIdentifiers({
        externalId: sanitized.externalId,
        identityProvider: sanitized.identityProvider
    });
    if (externalId) sanitized.externalId = externalId;
    else delete sanitized.externalId;
    if (identityProvider) sanitized.identityProvider = identityProvider;
    else delete sanitized.identityProvider;
    return sanitized;
}
function isLegacyConsentFormat(data) {
    if ('object' != typeof data || null === data) return false;
    const record = data;
    const consentInfo = record.consentInfo;
    if (!consentInfo || 'object' != typeof consentInfo) return false;
    const hasLegacyId = 'string' == typeof consentInfo.id;
    const hasSubjectId = 'string' == typeof consentInfo.subjectId;
    return hasLegacyId && !hasSubjectId;
}
function migrateLegacyStorage(config) {
    const newKey = config?.storageKey || "c15t";
    const legacyKey = STORAGE_KEY;
    if (newKey === legacyKey) return;
    try {
        if ("u" > typeof window && window.localStorage) {
            const existingData = window.localStorage.getItem(newKey);
            if (existingData) return void window.localStorage.removeItem(legacyKey);
            const legacyData = window.localStorage.getItem(legacyKey);
            if (legacyData) {
                window.localStorage.setItem(newKey, legacyData);
                window.localStorage.removeItem(legacyKey);
                getDebugLogger().log(`Migrated consent data from "${legacyKey}" to "${newKey}"`);
            }
        }
    } catch (error) {
        console.warn('[c15t] Failed to migrate legacy storage:', error);
    }
}
function saveConsentToStorage(data, options, config) {
    let localStorageSuccess = false;
    let cookieSuccess = false;
    const storageKey = config?.storageKey || "c15t";
    const existing = getConsentFromStorage(config);
    const mergedData = {
        ...existing,
        ...data,
        consentInfo: sanitizeConsentInfo(data.consentInfo || existing?.consentInfo ? {
            ...existing?.consentInfo ?? {},
            ...data.consentInfo ?? {}
        } : void 0),
        iabCustomVendorConsents: data.iabCustomVendorConsents ?? existing?.iabCustomVendorConsents,
        iabCustomVendorLegitimateInterests: data.iabCustomVendorLegitimateInterests ?? existing?.iabCustomVendorLegitimateInterests
    };
    const cleanedData = {
        ...mergedData
    };
    if (!cleanedData.iabCustomVendorConsents || 0 === Object.keys(cleanedData.iabCustomVendorConsents).length) delete cleanedData.iabCustomVendorConsents;
    if (!cleanedData.iabCustomVendorLegitimateInterests || 0 === Object.keys(cleanedData.iabCustomVendorLegitimateInterests).length) delete cleanedData.iabCustomVendorLegitimateInterests;
    try {
        if ("u" > typeof window && window.localStorage) {
            window.localStorage.setItem(storageKey, JSON.stringify(cleanedData));
            localStorageSuccess = true;
        }
    } catch (error) {
        console.warn('Failed to save consent to localStorage:', error);
    }
    try {
        setCookie(storageKey, cleanedData, options, config);
        cookieSuccess = true;
    } catch (error) {
        console.warn('Failed to save consent to cookie:', error);
    }
    if (!localStorageSuccess && !cookieSuccess) throw new Error('Failed to save consent to any storage method');
}
function normalizeConsentData(data) {
    const consents = data.consents || {};
    const normalizedConsents = {
        ...consents
    };
    for (const consentName of allConsentNames)normalizedConsents[consentName] = consents[consentName] ?? false;
    return {
        ...data,
        consents: normalizedConsents
    };
}
function getConsentFromStorage(config) {
    migrateLegacyStorage(config);
    const storageKey = config?.storageKey || "c15t";
    let localStorageData = null;
    let cookieData = null;
    try {
        if ("u" > typeof window && window.localStorage) {
            const stored = window.localStorage.getItem(storageKey);
            if (stored) localStorageData = JSON.parse(stored);
        }
    } catch (error) {
        console.warn('Failed to read consent from localStorage:', error);
    }
    try {
        cookieData = getCookie(storageKey);
    } catch (error) {
        console.warn('Failed to read consent from cookie:', error);
    }
    let chosenData = null;
    let chosenSource = null;
    if (cookieData) {
        chosenData = cookieData;
        chosenSource = 'cookie';
    } else if (localStorageData) {
        chosenData = localStorageData;
        chosenSource = 'localStorage';
    }
    if (chosenData && chosenSource) {
        const isCrossSubdomain = config?.crossSubdomain === true || !!config?.defaultDomain;
        if ('localStorage' !== chosenSource || cookieData) {
            if ('cookie' === chosenSource) try {
                if ("u" > typeof window && window.localStorage) {
                    let normalizedCookieData = chosenData;
                    if ('object' == typeof normalizedCookieData && null !== normalizedCookieData && 'consents' in normalizedCookieData) normalizedCookieData = normalizeConsentData(normalizedCookieData);
                    let normalizedLocalStorageData = null;
                    try {
                        const stored = window.localStorage.getItem(storageKey);
                        if (stored) {
                            const parsed = JSON.parse(stored);
                            normalizedLocalStorageData = 'object' == typeof parsed && null !== parsed && 'consents' in parsed ? normalizeConsentData(parsed) : parsed;
                        }
                    } catch  {
                        normalizedLocalStorageData = null;
                    }
                    const cookieJson = JSON.stringify(normalizedCookieData);
                    const localStorageJson = JSON.stringify(normalizedLocalStorageData);
                    if (cookieJson !== localStorageJson) {
                        window.localStorage.setItem(storageKey, cookieJson);
                        if (normalizedLocalStorageData) if (isCrossSubdomain) getDebugLogger().log('Updated localStorage with consent from cookie (cross-subdomain mode)');
                        else getDebugLogger().log('Updated localStorage with consent from cookie');
                        else getDebugLogger().log('Synced consent from cookie to localStorage');
                    }
                }
            } catch (error) {
                console.warn('[c15t] Failed to sync consent to localStorage:', error);
            }
        } else try {
            setCookie(storageKey, chosenData, void 0, config);
            getDebugLogger().log('Synced consent from localStorage to cookie');
        } catch (error) {
            console.warn('[c15t] Failed to sync consent to cookie:', error);
        }
    }
    if (chosenData && isLegacyConsentFormat(chosenData)) {
        getDebugLogger().log('Detected legacy consent format (v1.x). Re-consent required for v2.0.');
        deleteConsentFromStorage(void 0, config);
        return null;
    }
    if (chosenData && 'object' == typeof chosenData) {
        const normalizedData = normalizeConsentData(chosenData);
        if ('object' == typeof normalizedData && null !== normalizedData && 'consentInfo' in normalizedData) {
            const dataWithConsentInfo = normalizedData;
            dataWithConsentInfo.consentInfo = sanitizeConsentInfo(dataWithConsentInfo.consentInfo);
            return dataWithConsentInfo;
        }
        return normalizedData;
    }
    return chosenData;
}
function deleteConsentFromStorage(options, config) {
    const storageKey = config?.storageKey || "c15t";
    try {
        if ("u" > typeof window && window.localStorage) {
            window.localStorage.removeItem(storageKey);
            if (storageKey !== STORAGE_KEY) window.localStorage.removeItem(STORAGE_KEY);
        }
    } catch (error) {
        console.warn('Failed to remove consent from localStorage:', error);
    }
    try {
        deleteCookie(storageKey, options, config);
        if (storageKey !== STORAGE_KEY) deleteCookie(STORAGE_KEY, options, config);
    } catch (error) {
        console.warn('Failed to remove consent cookie:', error);
    }
}
const API_ENDPOINTS = {
    INIT: '/init',
    POST_SUBJECT: '/subjects',
    GET_SUBJECT: '/subjects',
    PATCH_SUBJECT: '/subjects',
    CHECK_CONSENT: '/consents/check',
    LIST_SUBJECTS: '/subjects'
};
async function withFallback(context, endpoint, method, options, fallbackFn) {
    try {
        const response = await fetcher(context, endpoint, {
            method,
            ...options
        });
        if (response.ok) return response;
        console.warn(`API request failed, falling back to offline mode for ${endpoint}`);
        return fallbackFn(options);
    } catch (error) {
        console.warn(`Error calling ${endpoint}, falling back to offline mode:`, error);
        return fallbackFn(options);
    }
}
async function offlineFallbackForIdentifyUser(options) {
    const pendingSubmissionsKey = 'c15t-pending-identify-submissions';
    const newSubjectId = getIdentifySubjectId(options?.body);
    try {
        if ("u" > typeof window && options?.body && window.localStorage) {
            let pendingSubmissions = [];
            try {
                const storedSubmissions = window.localStorage.getItem(pendingSubmissionsKey);
                if (storedSubmissions) pendingSubmissions = JSON.parse(storedSubmissions);
            } catch (e) {
                console.warn('Error parsing pending identify submissions:', e);
                pendingSubmissions = [];
            }
            const newSubmission = options.body;
            const isDuplicate = pendingSubmissions.some((submission)=>getIdentifySubjectId(submission) === newSubjectId && submission.externalId === newSubmission.externalId);
            if (!isDuplicate) {
                pendingSubmissions.push(newSubmission);
                window.localStorage.setItem(pendingSubmissionsKey, JSON.stringify(pendingSubmissions));
                getDebugLogger().log('Queued identify user submission for retry on next page load');
            }
        }
    } catch (error) {
        console.warn('Failed to write to localStorage in identify offline fallback:', error);
    }
    const response = fetcher_createResponseContext(true, null, null, null);
    if (options?.onSuccess) await options.onSuccess(response);
    return response;
}
async function identifyUser(context, storageConfig, options) {
    const { body, ...restOptions } = options;
    const subjectId = getIdentifySubjectId(body);
    if (!body || !subjectId) return {
        ok: false,
        data: null,
        response: null,
        error: {
            message: 'Subject ID is required to identify user',
            status: 400,
            code: 'MISSING_SUBJECT_ID'
        }
    };
    const existingData = getConsentFromStorage(storageConfig);
    saveConsentToStorage({
        consents: existingData?.consents || {},
        consentInfo: {
            ...existingData?.consentInfo,
            time: existingData?.consentInfo?.time || Date.now(),
            subjectId,
            externalId: body.externalId,
            identityProvider: body.identityProvider
        }
    }, void 0, storageConfig);
    const path = `${API_ENDPOINTS.PATCH_SUBJECT}/${subjectId}`;
    const { subjectId: _subjectId, id: _legacySubjectId, ...patchBody } = body;
    return withFallback(context, path, 'PATCH', {
        ...restOptions,
        body: patchBody
    }, async (fallbackOptions)=>{
        const fullBody = {
            subjectId,
            ...fallbackOptions?.body
        };
        return offlineFallbackForIdentifyUser({
            ...fallbackOptions,
            body: fullBody
        });
    });
}
function resolveNoPolicyFallback() {
    return types_namespaceObject.policyDefaults.offlineNoBanner();
}
function resolveFallbackPolicy(options) {
    if (options.explicitPolicy) return options.explicitPolicy;
    return types_namespaceObject.policyDefaults.offlineOptInBanner();
}
function buildFallbackInitData(options) {
    const data = {
        jurisdiction: options.jurisdiction ?? 'NONE',
        location: {
            countryCode: options.countryCode ?? null,
            regionCode: options.regionCode ?? null
        },
        translations: {
            language: options.language ?? 'en',
            translations: options.translations ?? translations_namespaceObject.enTranslations
        },
        branding: 'c15t',
        gvl: options.gvl ?? null
    };
    if (options.policy) data.policy = options.policy;
    if (options.policyDecision) data.policyDecision = options.policyDecision;
    if (options.policySnapshotToken) data.policySnapshotToken = options.policySnapshotToken;
    return data;
}
async function createFallbackContext(options, data) {
    const response = fetcher_createResponseContext(true, data, null, null);
    if (options?.onSuccess) await options.onSuccess(response);
    return response;
}
async function offlineFallbackForConsentBanner(options, iabConfig) {
    const fallbackPolicy = resolveFallbackPolicy({});
    let gvl = null;
    if (iabConfig?.enabled && 'iab' === fallbackPolicy.model) try {
        const fetchGVL = iabConfig._module?.fetchGVL;
        if (fetchGVL) {
            const acceptLanguage = options?.headers?.['accept-language'];
            gvl = await fetchGVL(iabConfig.vendorIds, acceptLanguage ? {
                headers: {
                    'accept-language': acceptLanguage
                }
            } : void 0);
        }
    } catch (error) {
        console.warn('Failed to fetch GVL in offline fallback:', error);
    }
    const fallbackData = buildFallbackInitData({
        countryCode: options?.headers?.['x-c15t-country'] ?? null,
        regionCode: options?.headers?.['x-c15t-region'] ?? null,
        gvl,
        policy: fallbackPolicy
    });
    return createFallbackContext(options, fallbackData);
}
async function hosted_init_init(context, options, iabConfig) {
    try {
        const response = await fetcher(context, API_ENDPOINTS.INIT, {
            method: 'GET',
            ...options
        });
        if (response.ok) return response;
        console.warn('API request failed, falling back to offline mode for consent banner');
        return offlineFallbackForConsentBanner(options, iabConfig);
    } catch (error) {
        console.warn('Error fetching consent banner info, falling back to offline mode:', error);
        return offlineFallbackForConsentBanner(options, iabConfig);
    }
}
const PENDING_CONSENT_KEY = 'c15t-pending-consent-submissions';
const PENDING_IDENTIFY_KEY = 'c15t-pending-identify-submissions';
function checkPendingConsentSubmissions(_context, processPendingSubmissions) {
    const pendingSubmissionsKey = PENDING_CONSENT_KEY;
    if ("u" < typeof window || !window.localStorage) return;
    try {
        window.localStorage.setItem('c15t-storage-test-key', 'test');
        window.localStorage.removeItem('c15t-storage-test-key');
        const pendingSubmissionsStr = window.localStorage.getItem(pendingSubmissionsKey);
        if (!pendingSubmissionsStr) return;
        const pendingSubmissions = JSON.parse(pendingSubmissionsStr);
        if (!pendingSubmissions.length) return void window.localStorage.removeItem(pendingSubmissionsKey);
        getDebugLogger().log(`Found ${pendingSubmissions.length} pending consent submission(s) to retry`);
        setTimeout(()=>{
            processPendingSubmissions(pendingSubmissions);
        }, 2000);
    } catch (error) {
        console.warn('Failed to check for pending consent submissions:', error);
    }
}
async function processPendingConsentSubmissions(context, submissions) {
    const pendingSubmissionsKey = PENDING_CONSENT_KEY;
    const maxRetries = 3;
    const remainingSubmissions = [
        ...submissions
    ];
    for(let i = 0; i < maxRetries && remainingSubmissions.length > 0; i++){
        const successfulSubmissions = [];
        for(let j = 0; j < remainingSubmissions.length; j++){
            const submission = remainingSubmissions[j];
            if (submission) try {
                const { externalId: externalSubjectId, identityProvider } = sanitizeSubjectIdentifiers({
                    externalId: submission.externalSubjectId,
                    identityProvider: submission.identityProvider
                });
                const sanitizedSubmission = {
                    ...submission,
                    ...externalSubjectId ? {
                        externalSubjectId
                    } : {},
                    ...identityProvider ? {
                        identityProvider
                    } : {}
                };
                if (!externalSubjectId) delete sanitizedSubmission.externalSubjectId;
                if (!identityProvider) delete sanitizedSubmission.identityProvider;
                getDebugLogger().log('Retrying consent submission:', submission);
                const response = await fetcher(context, API_ENDPOINTS.POST_SUBJECT, {
                    method: 'POST',
                    body: sanitizedSubmission
                });
                if (response.ok) {
                    getDebugLogger().log('Successfully resubmitted consent');
                    successfulSubmissions.push(j);
                }
            } catch (error) {
                console.warn('Failed to resend consent submission:', error);
            }
        }
        for(let k = successfulSubmissions.length - 1; k >= 0; k--){
            const index = successfulSubmissions[k];
            if (void 0 !== index) remainingSubmissions.splice(index, 1);
        }
        if (0 === remainingSubmissions.length) break;
        if (i < maxRetries - 1) await delay(1000 * (i + 1));
    }
    try {
        if ("u" > typeof window && window.localStorage) if (remainingSubmissions.length > 0) {
            window.localStorage.setItem(pendingSubmissionsKey, JSON.stringify(remainingSubmissions));
            getDebugLogger().log(`${remainingSubmissions.length} consent submissions still pending for future retry`);
        } else {
            window.localStorage.removeItem(pendingSubmissionsKey);
            getDebugLogger().log('All pending consent submissions processed successfully');
        }
    } catch (error) {
        console.warn('Error updating pending submissions storage:', error);
    }
}
function checkPendingIdentifySubmissions(_context, processPendingSubmissions) {
    if ("u" < typeof window || !window.localStorage) return;
    try {
        const pendingSubmissionsStr = window.localStorage.getItem(PENDING_IDENTIFY_KEY);
        if (!pendingSubmissionsStr) return;
        const pendingSubmissions = JSON.parse(pendingSubmissionsStr);
        if (!pendingSubmissions.length) return void window.localStorage.removeItem(PENDING_IDENTIFY_KEY);
        getDebugLogger().log(`Found ${pendingSubmissions.length} pending identify user submission(s) to retry`);
        setTimeout(()=>{
            processPendingSubmissions(pendingSubmissions);
        }, 2500);
    } catch (error) {
        console.warn('Failed to check for pending identify submissions:', error);
    }
}
async function processPendingIdentifySubmissions(context, submissions) {
    const maxRetries = 3;
    const remainingSubmissions = [
        ...submissions
    ];
    for(let i = 0; i < maxRetries && remainingSubmissions.length > 0; i++){
        const successfulSubmissions = [];
        for(let j = 0; j < remainingSubmissions.length; j++){
            const submission = remainingSubmissions[j];
            if (!submission) continue;
            const subjectId = getIdentifySubjectId(submission);
            if (!subjectId) {
                console.warn('Dropping pending identify submission without a subject ID');
                successfulSubmissions.push(j);
                continue;
            }
            if (!submission.externalId) {
                console.warn('Dropping pending identify submission without an externalId');
                successfulSubmissions.push(j);
                continue;
            }
            try {
                getDebugLogger().log('Retrying identify user submission:', submission);
                const path = `${API_ENDPOINTS.PATCH_SUBJECT}/${subjectId}`;
                const { subjectId: _subjectId, id: _legacySubjectId, ...patchBody } = submission;
                const response = await fetcher(context, path, {
                    method: 'PATCH',
                    body: patchBody
                });
                if (response.ok) {
                    getDebugLogger().log('Successfully resubmitted identify user');
                    successfulSubmissions.push(j);
                }
            } catch (error) {
                console.warn('Failed to resend identify user submission:', error);
            }
        }
        for(let k = successfulSubmissions.length - 1; k >= 0; k--){
            const index = successfulSubmissions[k];
            if (void 0 !== index) remainingSubmissions.splice(index, 1);
        }
        if (0 === remainingSubmissions.length) break;
        if (i < maxRetries - 1) await delay(1000 * (i + 1));
    }
    try {
        if ("u" > typeof window && window.localStorage) if (remainingSubmissions.length > 0) {
            window.localStorage.setItem(PENDING_IDENTIFY_KEY, JSON.stringify(remainingSubmissions));
            getDebugLogger().log(`${remainingSubmissions.length} identify submissions still pending for future retry`);
        } else {
            window.localStorage.removeItem(PENDING_IDENTIFY_KEY);
            getDebugLogger().log('All pending identify submissions processed successfully');
        }
    } catch (error) {
        console.warn('Error updating pending identify submissions storage:', error);
    }
}
async function offlineFallbackForSetConsent(storageConfig, options) {
    const pendingSubmissionsKey = 'c15t-pending-consent-submissions';
    const subjectId = options?.body?.subjectId;
    try {
        if ("u" > typeof window) {
            saveConsentToStorage({
                consents: options?.body?.preferences || {},
                consentInfo: {
                    time: Date.now(),
                    subjectId,
                    externalId: options?.body?.externalSubjectId,
                    identityProvider: options?.body?.identityProvider
                }
            }, void 0, storageConfig);
            if (options?.body && window.localStorage) {
                let pendingSubmissions = [];
                try {
                    const storedSubmissions = window.localStorage.getItem(pendingSubmissionsKey);
                    if (storedSubmissions) pendingSubmissions = JSON.parse(storedSubmissions);
                } catch (e) {
                    console.warn('Error parsing pending submissions:', e);
                    pendingSubmissions = [];
                }
                const newSubmission = options.body;
                const isDuplicate = pendingSubmissions.some((submission)=>JSON.stringify(submission) === JSON.stringify(newSubmission));
                if (!isDuplicate) {
                    pendingSubmissions.push(newSubmission);
                    window.localStorage.setItem(pendingSubmissionsKey, JSON.stringify(pendingSubmissions));
                    getDebugLogger().log('Queued consent submission for retry on next page load');
                }
            }
        }
    } catch (error) {
        console.warn('Failed to write to localStorage in offline fallback:', error);
    }
    const response = fetcher_createResponseContext(true, null, null, null);
    if (options?.onSuccess) await options.onSuccess(response);
    return response;
}
async function set_consent_setConsent(context, storageConfig, options) {
    saveConsentToStorage({
        consents: options?.body?.preferences || {},
        consentInfo: {
            time: Date.now(),
            subjectId: options?.body?.subjectId,
            externalId: options?.body?.externalSubjectId,
            identityProvider: options?.body?.identityProvider
        }
    }, void 0, storageConfig);
    const response = await withFallback(context, API_ENDPOINTS.POST_SUBJECT, 'POST', options, async (fallbackOptions)=>offlineFallbackForSetConsent(storageConfig, fallbackOptions));
    return response;
}
class C15tClient {
    backendURL;
    storageConfig;
    iabConfig;
    headers;
    customFetch;
    corsMode;
    retryConfig;
    fetcherContext;
    constructor(options){
        this.backendURL = options.backendURL.endsWith('/') ? options.backendURL.slice(0, -1) : options.backendURL;
        this.headers = {
            'Content-Type': 'application/json',
            ...options.headers
        };
        this.customFetch = options.customFetch;
        this.corsMode = options.corsMode || 'cors';
        this.storageConfig = options.storageConfig;
        this.iabConfig = options.iabConfig;
        this.retryConfig = {
            maxRetries: options.retryConfig?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries ?? 3,
            initialDelayMs: options.retryConfig?.initialDelayMs ?? DEFAULT_RETRY_CONFIG.initialDelayMs ?? 100,
            backoffFactor: options.retryConfig?.backoffFactor ?? DEFAULT_RETRY_CONFIG.backoffFactor ?? 2,
            retryableStatusCodes: options.retryConfig?.retryableStatusCodes ?? DEFAULT_RETRY_CONFIG.retryableStatusCodes,
            nonRetryableStatusCodes: options.retryConfig?.nonRetryableStatusCodes ?? DEFAULT_RETRY_CONFIG.nonRetryableStatusCodes,
            shouldRetry: options.retryConfig?.shouldRetry ?? DEFAULT_RETRY_CONFIG.shouldRetry,
            retryOnNetworkError: options.retryConfig?.retryOnNetworkError ?? DEFAULT_RETRY_CONFIG.retryOnNetworkError
        };
        this.fetcherContext = {
            backendURL: this.backendURL,
            headers: this.headers,
            customFetch: this.customFetch,
            corsMode: this.corsMode,
            retryConfig: this.retryConfig
        };
        this.checkPendingConsentSubmissions();
        this.checkPendingIdentifySubmissions();
    }
    async init(options) {
        return hosted_init_init(this.fetcherContext, options, this.iabConfig);
    }
    async setConsent(options) {
        return set_consent_setConsent(this.fetcherContext, this.storageConfig, options);
    }
    async identifyUser(options) {
        return identifyUser(this.fetcherContext, this.storageConfig, options);
    }
    async $fetch(path, options) {
        return fetcher(this.fetcherContext, path, options);
    }
    checkPendingConsentSubmissions() {
        checkPendingConsentSubmissions(this.fetcherContext, (submissions)=>this.processPendingConsentSubmissions(submissions));
    }
    async processPendingConsentSubmissions(submissions) {
        return processPendingConsentSubmissions(this.fetcherContext, submissions);
    }
    checkPendingIdentifySubmissions() {
        checkPendingIdentifySubmissions(this.fetcherContext, (submissions)=>this.processPendingIdentifySubmissions(submissions));
    }
    async processPendingIdentifySubmissions(submissions) {
        return processPendingIdentifySubmissions(this.fetcherContext, submissions);
    }
}
function checkJurisdiction(countryCode, regionCode) {
    const jurisdictions = {
        EU: new Set([
            'AT',
            'BE',
            'BG',
            'HR',
            'CY',
            'CZ',
            'DK',
            'EE',
            'FI',
            'FR',
            'DE',
            'GR',
            'HU',
            'IE',
            'IT',
            'LV',
            'LT',
            'LU',
            'MT',
            'NL',
            'PL',
            'PT',
            'RO',
            'SK',
            'SI',
            'ES',
            'SE'
        ]),
        EEA: new Set([
            'IS',
            'NO',
            'LI'
        ]),
        UK: new Set([
            'GB'
        ]),
        CH: new Set([
            'CH'
        ]),
        BR: new Set([
            'BR'
        ]),
        CA: new Set([
            'CA'
        ]),
        AU: new Set([
            'AU'
        ]),
        JP: new Set([
            'JP'
        ]),
        KR: new Set([
            'KR'
        ]),
        CA_QC_REGIONS: new Set([
            'QC'
        ])
    };
    let jurisdictionCode = 'NONE';
    if (countryCode) {
        const normalizedCountryCode = countryCode.toUpperCase();
        const normalizedRegionCode = regionCode && 'string' == typeof regionCode ? (regionCode.includes('-') ? regionCode.split('-').pop() : regionCode).toUpperCase() : null;
        if ('CA' === normalizedCountryCode && normalizedRegionCode && jurisdictions.CA_QC_REGIONS.has(normalizedRegionCode)) return 'QC_LAW25';
        const jurisdictionMap = [
            {
                sets: [
                    jurisdictions.EU,
                    jurisdictions.EEA,
                    jurisdictions.UK
                ],
                code: 'GDPR'
            },
            {
                sets: [
                    jurisdictions.CH
                ],
                code: 'CH'
            },
            {
                sets: [
                    jurisdictions.BR
                ],
                code: 'BR'
            },
            {
                sets: [
                    jurisdictions.CA
                ],
                code: 'PIPEDA'
            },
            {
                sets: [
                    jurisdictions.AU
                ],
                code: 'AU'
            },
            {
                sets: [
                    jurisdictions.JP
                ],
                code: 'APPI'
            },
            {
                sets: [
                    jurisdictions.KR
                ],
                code: 'PIPA'
            }
        ];
        for (const { sets, code } of jurisdictionMap)if (sets.some((set)=>set.has(normalizedCountryCode))) {
            jurisdictionCode = code;
            break;
        }
    }
    return jurisdictionCode;
}
function utils_createResponseContext(data = null) {
    return createResponseContext(true, data);
}
async function handleOfflineResponse(options) {
    const emptyResponse = utils_createResponseContext();
    if (options?.onSuccess) await options.onSuccess(emptyResponse);
    return emptyResponse;
}
const DEFAULT_PROFILE = 'default';
function normalizeLanguage(value) {
    if (!value) return;
    const normalized = value.split(',')[0]?.split(';')[0]?.trim().toLowerCase();
    if (!normalized) return;
    return normalized.split('-')[0] ?? void 0;
}
function getProfileLanguages(profiles, profile) {
    return Object.keys(profiles[profile]?.translations ?? {}).sort();
}
function resolveActiveProfile(input) {
    const requestedProfile = input.policyProfile ?? input.defaultProfile;
    return input.profiles[requestedProfile] ? requestedProfile : input.defaultProfile;
}
function resolveProfileFallbackLanguage(input) {
    const configuredFallbackLanguage = normalizeLanguage(input.profile?.fallbackLanguage) ?? 'en';
    const profileLanguages = Object.keys(input.profile?.translations ?? {}).sort();
    if (profileLanguages.includes(configuredFallbackLanguage)) return configuredFallbackLanguage;
    if (profileLanguages.includes('en')) return 'en';
    return profileLanguages[0] ?? configuredFallbackLanguage;
}
function resolveOfflinePolicyTranslations(input) {
    const profiles = input.i18n.messages ?? {};
    const defaultProfile = input.i18n.defaultProfile ?? DEFAULT_PROFILE;
    const profile = resolveActiveProfile({
        profiles,
        defaultProfile,
        policyProfile: input.policyI18n?.messageProfile
    });
    const profileLanguages = getProfileLanguages(profiles, profile);
    const fallbackLanguage = resolveProfileFallbackLanguage({
        profile: profiles[profile]
    });
    const policyLanguage = normalizeLanguage(input.policyI18n?.language);
    const requestedLanguage = policyLanguage ?? (0, translations_namespaceObject.selectLanguage)(profileLanguages, {
        header: input.acceptLanguage,
        fallback: fallbackLanguage
    });
    const resolvedLanguage = profiles[profile]?.translations[requestedLanguage] ? requestedLanguage : fallbackLanguage;
    const base = translations_namespaceObject.enTranslations;
    const custom = profiles[profile]?.translations[resolvedLanguage];
    return {
        language: resolvedLanguage,
        translations: custom ? (0, translations_namespaceObject.deepMergeTranslations)(base, custom) : base
    };
}
function resolveConfiguredFallbackLanguage(translations, defaultLanguage) {
    const configuredLanguages = Object.keys(translations).sort();
    const normalizedDefault = defaultLanguage?.toLowerCase();
    if (normalizedDefault && configuredLanguages.includes(normalizedDefault)) return normalizedDefault;
    if (configuredLanguages.includes('en')) return 'en';
    return configuredLanguages[0] ?? 'en';
}
async function offline_init_init(initialTranslationConfig, options, iabConfig, policyConfig) {
    const country = options?.headers?.['x-c15t-country'] ?? 'GB';
    const region = options?.headers?.['x-c15t-region'] ?? null;
    const headerLanguage = options?.headers?.['accept-language'] ?? null;
    const jurisdictionCode = checkJurisdiction(country, region);
    const configuredPolicies = policyConfig?.policyPacks;
    const hasExplicitPolicies = policyConfig?.policyPacks !== void 0;
    const i18nValidation = (0, types_namespaceObject.validatePolicyI18nConfig)({
        i18n: policyConfig?.i18n,
        policies: configuredPolicies
    });
    for (const warning of i18nValidation.warnings)console.warn(`[c15t] offlinePolicy.i18n: ${warning}`);
    if (i18nValidation.errors.length > 0) throw new Error(`Invalid offlinePolicy.i18n configuration:\n${i18nValidation.errors.map((error)=>`- ${error}`).join('\n')}`);
    if (configuredPolicies && configuredPolicies.length > 0) (0, types_namespaceObject.validatePolicies)(configuredPolicies, {
        iabEnabled: iabConfig?.enabled === true
    });
    const resolvedPolicyDecision = configuredPolicies && configuredPolicies.length > 0 ? await (0, types_namespaceObject.resolvePolicyDecision)({
        policies: configuredPolicies,
        countryCode: country,
        regionCode: region,
        jurisdiction: jurisdictionCode,
        iabEnabled: iabConfig?.enabled === true
    }) : void 0;
    const shouldUseSyntheticFallbackDefaults = !policyConfig?.policy && !resolvedPolicyDecision && !hasExplicitPolicies;
    const resolvedPolicyConfig = {
        ...policyConfig,
        policy: policyConfig?.policy ?? resolvedPolicyDecision?.policy ?? (hasExplicitPolicies ? resolveNoPolicyFallback() : void 0) ?? (shouldUseSyntheticFallbackDefaults ? resolveFallbackPolicy({}) : void 0),
        policyDecision: policyConfig?.policyDecision ?? (resolvedPolicyDecision ? {
            policyId: resolvedPolicyDecision.policy.id,
            fingerprint: resolvedPolicyDecision.fingerprint,
            matchedBy: resolvedPolicyDecision.matchedBy,
            country,
            region,
            jurisdiction: jurisdictionCode
        } : void 0)
    };
    let language;
    let translationsForLanguage;
    if (policyConfig?.i18n?.messages && Object.keys(policyConfig.i18n.messages).length > 0) {
        const resolvedTranslations = resolveOfflinePolicyTranslations({
            acceptLanguage: headerLanguage,
            i18n: policyConfig.i18n,
            policyI18n: resolvedPolicyConfig.policy?.i18n
        });
        language = resolvedTranslations.language;
        translationsForLanguage = resolvedTranslations.translations;
    } else if (initialTranslationConfig?.translations && Object.keys(initialTranslationConfig.translations).length > 0) {
        const customTranslations = initialTranslationConfig.translations;
        const availableLanguages = Object.keys(customTranslations);
        const fallbackLanguage = resolveConfiguredFallbackLanguage(customTranslations, initialTranslationConfig.defaultLanguage);
        language = (0, translations_namespaceObject.selectLanguage)(availableLanguages, {
            header: headerLanguage,
            fallback: fallbackLanguage
        });
        const base = translations_namespaceObject.enTranslations;
        const customForLanguage = customTranslations[language] ?? {};
        translationsForLanguage = (0, translations_namespaceObject.deepMergeTranslations)(base, customForLanguage);
    } else {
        const availableLanguages = Object.keys(defaultTranslationConfig.translations);
        const fallbackLanguage = defaultTranslationConfig.defaultLanguage ?? 'en';
        language = (0, translations_namespaceObject.selectLanguage)(availableLanguages, {
            header: headerLanguage,
            fallback: fallbackLanguage
        });
        translationsForLanguage = defaultTranslationConfig.translations[language];
    }
    let gvl = null;
    if (iabConfig?.enabled && resolvedPolicyConfig.policy?.model === 'iab') if (iabConfig.gvl) gvl = iabConfig.gvl;
    else try {
        const fetchGVL = iabConfig._module?.fetchGVL;
        if (fetchGVL) gvl = await fetchGVL(iabConfig.vendorIds, {
            headers: {
                'accept-language': language
            }
        });
    } catch (error) {
        console.warn('Failed to fetch GVL in offline mode:', error);
    }
    const responseData = buildFallbackInitData({
        jurisdiction: jurisdictionCode,
        countryCode: country,
        regionCode: region,
        language,
        translations: translationsForLanguage,
        gvl,
        policy: resolvedPolicyConfig.policy,
        policyDecision: resolvedPolicyConfig.policyDecision,
        policySnapshotToken: resolvedPolicyConfig.policySnapshotToken
    });
    const response = utils_createResponseContext(responseData);
    if (options?.onSuccess) await options.onSuccess(response);
    return response;
}
async function offline_set_consent_setConsent(storageConfig, options) {
    const subjectId = options?.body?.subjectId;
    try {
        if ("u" > typeof window) saveConsentToStorage({
            consentInfo: {
                time: Date.now(),
                subjectId,
                externalId: options?.body?.externalSubjectId,
                identityProvider: options?.body?.identityProvider
            },
            consents: options?.body?.preferences || {}
        }, void 0, storageConfig);
    } catch (error) {
        console.warn('Failed to write to storage:', error);
    }
    return await handleOfflineResponse(options);
}
class OfflineClient {
    storageConfig;
    initialTranslationConfig;
    iabConfig;
    policyConfig;
    constructor(storageConfig, initialTranslationConfig, iabConfig, policyConfig){
        this.storageConfig = storageConfig;
        this.initialTranslationConfig = initialTranslationConfig;
        this.iabConfig = iabConfig;
        this.policyConfig = policyConfig;
    }
    async init(options) {
        return offline_init_init(this.initialTranslationConfig, options, this.iabConfig, this.policyConfig);
    }
    async setConsent(options) {
        return offline_set_consent_setConsent(this.storageConfig, options);
    }
    async identifyUser(options) {
        console.warn('identifyUser called in offline mode - external ID will not be linked');
        return handleOfflineResponse(options);
    }
    async $fetch(_path, options) {
        return await handleOfflineResponse(options);
    }
}
const DEFAULT_BACKEND_URL = '/api/c15t';
const DEFAULT_CLIENT_MODE = 'hosted';
let hasWarnedAboutLegacyC15tMode = false;
function normalizeClientMode(mode) {
    if ('c15t' === mode) {
        const nodeEnv = "u" > typeof globalThis && 'process' in globalThis ? globalThis.process?.env?.NODE_ENV : void 0;
        if (!hasWarnedAboutLegacyC15tMode && 'production' !== nodeEnv) {
            hasWarnedAboutLegacyC15tMode = true;
            console.warn("[c15t] `mode: 'c15t'` is deprecated and will be removed in a future major release. Use `mode: 'hosted'` instead.");
        }
        return DEFAULT_CLIENT_MODE;
    }
    if ('offline' === mode || 'custom' === mode) return mode;
    return DEFAULT_CLIENT_MODE;
}
function assertUnreachableMode(mode) {
    throw new Error(`Unsupported client mode: ${String(mode)}`);
}
function resolveOfflinePolicyOption(options) {
    if (void 0 !== options.offlinePolicy) return options.offlinePolicy;
    return options.store?.offlinePolicy;
}
const clientRegistry = new Map();
function serializeStorageConfig(storageConfig) {
    if (!storageConfig) return '';
    const sorted = Object.keys(storageConfig).sort().map((key)=>{
        const value = storageConfig[key];
        if (null == value) return `${key}:null`;
        return `${key}:${String(value)}`;
    }).join('|');
    return sorted;
}
function getClientCacheKey(options) {
    const normalizedMode = normalizeClientMode(options.mode);
    const resolvedOfflinePolicy = resolveOfflinePolicyOption(options);
    const storageConfigPart = serializeStorageConfig(options.storageConfig);
    const storageKey = storageConfigPart ? `:storage:${storageConfigPart}` : '';
    if ('offline' === normalizedMode) {
        const initialTranslations = options.store?.initialTranslationConfig?.translations;
        const initialDefaultLanguage = options.store?.initialTranslationConfig?.defaultLanguage;
        let translationPart = '';
        translationPart = initialTranslations ? `:translations:${Object.keys(initialTranslations).sort().join(',')}` : '';
        let defaultLanguagePart = '';
        defaultLanguagePart = initialDefaultLanguage ? `:default-language:${initialDefaultLanguage}` : '';
        const iabConfig = options.store?.iab;
        let iabPart = '';
        iabPart = iabConfig?.enabled ? ':iab:enabled' : '';
        let offlinePolicyPart = '';
        if (resolvedOfflinePolicy) offlinePolicyPart = `:policy:${(0, types_namespaceObject.createDeterministicFingerprintSync)(resolvedOfflinePolicy)}`;
        return `offline${storageKey}${translationPart}${defaultLanguagePart}${iabPart}${offlinePolicyPart}`;
    }
    if ('custom' === normalizedMode) {
        const handlers = 'endpointHandlers' in options ? options.endpointHandlers : void 0;
        const handlerKeys = Object.keys(handlers || {}).sort().join(',');
        return `custom:${handlerKeys}${storageKey}`;
    }
    let headersPart = '';
    if ('headers' in options && options.headers) {
        const headerKeys = Object.keys(options.headers).sort();
        headersPart = `:headers:${headerKeys.map((k)=>`${k}=${options.headers?.[k]}`).join(',')}`;
    }
    return `hosted:${options.backendURL || ''}${headersPart}${storageKey}`;
}
function configureConsentManager(options) {
    const cacheKey = getClientCacheKey(options);
    if (clientRegistry.has(cacheKey)) {
        if ('offline' !== options.mode && 'custom' !== options.mode && 'headers' in options && options.headers) {
            const existingClient = clientRegistry.get(cacheKey);
            if (existingClient instanceof C15tClient) existingClient.headers = {
                'Content-Type': 'application/json',
                ...options.headers
            };
        }
        const existingClient = clientRegistry.get(cacheKey);
        if (existingClient) return new Proxy(existingClient, {
            get (target, prop) {
                return target[prop];
            }
        });
    }
    const mode = normalizeClientMode(options.mode);
    let client;
    switch(mode){
        case 'custom':
            {
                const customOptions = options;
                client = new CustomClient({
                    endpointHandlers: customOptions.endpointHandlers
                });
                break;
            }
        case 'offline':
            {
                const iabConfig = options.store?.iab;
                const policyConfig = resolveOfflinePolicyOption(options);
                client = new OfflineClient(options.storageConfig, options.store?.initialTranslationConfig, iabConfig ? {
                    enabled: iabConfig.enabled,
                    vendorIds: iabConfig.vendors,
                    gvl: iabConfig.gvl,
                    _module: iabConfig._module
                } : void 0, policyConfig);
                break;
            }
        case 'hosted':
            {
                const hostedOptions = options;
                const iabConfig = options.store?.iab;
                client = new C15tClient({
                    backendURL: hostedOptions.backendURL || DEFAULT_BACKEND_URL,
                    headers: hostedOptions.headers,
                    customFetch: hostedOptions.customFetch,
                    retryConfig: hostedOptions.retryConfig,
                    storageConfig: options.storageConfig,
                    iabConfig: iabConfig ? {
                        enabled: iabConfig.enabled,
                        vendorIds: iabConfig.vendors,
                        gvl: iabConfig.gvl,
                        _module: iabConfig._module
                    } : void 0
                });
                break;
            }
        default:
            client = assertUnreachableMode(mode);
            break;
    }
    clientRegistry.set(cacheKey, client);
    return client;
}
function clearClientRegistry() {
    clientRegistry.clear();
}
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
function base58Encode(bytes) {
    const base = BigInt(58);
    let num = BigInt(0);
    for (const byte of bytes)num = num * BigInt(256) + BigInt(byte);
    const chars = [];
    while(num > 0){
        const remainder = num % base;
        chars.unshift(BASE58_ALPHABET.charAt(Number(remainder)));
        num /= base;
    }
    for (const byte of bytes)if (0 === byte) chars.unshift(BASE58_ALPHABET.charAt(0));
    else break;
    return chars.join('') || BASE58_ALPHABET.charAt(0);
}
const EPOCH_TIMESTAMP = 1700000000000;
function generateSubjectId() {
    const buf = crypto.getRandomValues(new Uint8Array(20));
    const t = Date.now() - EPOCH_TIMESTAMP;
    const high = Math.floor(t / 0x100000000);
    const low = t >>> 0;
    buf[0] = high >>> 24 & 255;
    buf[1] = high >>> 16 & 255;
    buf[2] = high >>> 8 & 255;
    buf[3] = 255 & high;
    buf[4] = low >>> 24 & 255;
    buf[5] = low >>> 16 & 255;
    buf[6] = low >>> 8 & 255;
    buf[7] = 255 & low;
    return `sub_${base58Encode(buf)}`;
}
function isValidSubjectId(id) {
    if (!id.startsWith('sub_')) return false;
    const encoded = id.slice(4);
    if (0 === encoded.length) return false;
    for (const char of encoded)if (!BASE58_ALPHABET.includes(char)) return false;
    return true;
}
function isConsentCategory(value) {
    return allConsentNames.includes(value);
}
function flattenLayout(layout) {
    if (!layout) return [];
    return layout.flatMap((group)=>Array.isArray(group) ? group : [
            group
        ]);
}
function applyPolicyPurposeAllowlist(preferences, allowedPurposeIds) {
    if (!allowedPurposeIds || 0 === allowedPurposeIds.length || allowedPurposeIds.includes('*')) return preferences;
    const allowed = new Set([
        'necessary',
        ...allowedPurposeIds
    ]);
    const next = {};
    for (const [key, value] of Object.entries(preferences))next[key] = allowed.has(key) ? value : false;
    return next;
}
function stripDisallowedPreferenceKeys(preferences, allowedPurposeIds) {
    if (!allowedPurposeIds || 0 === allowedPurposeIds.length || allowedPurposeIds.includes('*')) return preferences;
    const allowed = new Set([
        'necessary',
        ...allowedPurposeIds
    ]);
    const next = {};
    for (const [key, value] of Object.entries(preferences))if (allowed.has(key)) next[key] = value;
    return next;
}
function filterConsentCategoriesByPolicy(categories, allowedPurposeIds) {
    const uniqueCategories = Array.from(new Set(categories));
    if (!allowedPurposeIds || 0 === allowedPurposeIds.length || allowedPurposeIds.includes('*')) return uniqueCategories;
    const allowedCategories = new Set([
        'necessary',
        ...allowedPurposeIds.filter(isConsentCategory)
    ]);
    const filtered = uniqueCategories.filter((category)=>allowedCategories.has(category));
    if (!filtered.includes('necessary')) filtered.unshift('necessary');
    return filtered;
}
function shouldEnforcePolicyCategoryScope(allowedPurposeIds, scopeMode = 'permissive') {
    return 'strict' === scopeMode && Array.isArray(allowedPurposeIds) && allowedPurposeIds.length > 0 && !allowedPurposeIds.includes('*');
}
function applyPolicyScopeForRuntimeGating(consents, _allowedPurposeIds, _scopeMode = 'permissive') {
    return consents;
}
function getEffectivePolicy(initData) {
    return initData?.policy;
}
function validateUIAgainstPolicy(params) {
    const { policy, state } = params;
    if (!policy) return [];
    const issues = [];
    if (policy.ui?.mode && state.mode !== policy.ui.mode) issues.push({
        code: 'mode_mismatch',
        message: `UI mode "${state.mode}" does not match policy mode "${policy.ui.mode}".`
    });
    const surfacePolicy = 'banner' === state.mode ? policy.ui?.banner : 'dialog' === state.mode ? policy.ui?.dialog : void 0;
    const allowedActions = surfacePolicy?.allowedActions;
    if (allowedActions && allowedActions.length > 0) {
        const disallowed = state.actions.filter((action)=>!allowedActions.includes(action));
        if (disallowed.length > 0) issues.push({
            code: 'action_not_allowed',
            message: `UI renders actions not allowed by policy: ${disallowed.join(', ')}`
        });
    }
    const expectedLayout = surfacePolicy?.layout;
    if (expectedLayout && expectedLayout.length > 0) {
        const expected = flattenLayout(expectedLayout);
        const actual = state.actions.filter((action)=>expected.includes(action));
        if (expected.join('|') !== actual.join('|')) issues.push({
            code: 'group_layout_mismatch',
            message: `UI action order "${actual.join(', ')}" does not match policy layout "${expected.join(', ')}".`
        });
    }
    if (surfacePolicy?.direction && state.direction) {
        if (surfacePolicy.direction !== state.direction) issues.push({
            code: 'direction_mismatch',
            message: `UI action direction "${state.direction}" does not match policy action direction "${surfacePolicy.direction}".`
        });
    }
    if (surfacePolicy?.uiProfile && state.uiProfile) {
        if (surfacePolicy.uiProfile !== state.uiProfile) issues.push({
            code: 'ui_profile_mismatch',
            message: `UI profile "${state.uiProfile}" does not match policy UI profile "${surfacePolicy.uiProfile}".`
        });
    }
    if ('boolean' == typeof surfacePolicy?.scrollLock && 'boolean' == typeof state.scrollLock && surfacePolicy.scrollLock !== state.scrollLock) issues.push({
        code: 'scroll_lock_mismatch',
        message: `UI scroll lock "${state.scrollLock ? 'on' : 'off'}" does not match policy scroll lock "${surfacePolicy.scrollLock ? 'on' : 'off'}".`
    });
    return issues;
}
function validateNonEmptyConditions(conditions, conditionType) {
    if (0 === conditions.length) throw new TypeError(`${conditionType} condition cannot be empty`);
}
function evaluateCategoryCondition(category, consents) {
    if (!(category in consents)) throw new Error(`Consent category "${category}" not found in consent state`);
    return consents[category] || false;
}
function evaluateAndCondition(andCondition, consents) {
    const andConditions = Array.isArray(andCondition) ? andCondition : [
        andCondition
    ];
    validateNonEmptyConditions(andConditions, 'AND');
    return andConditions.every((subCondition)=>evaluateConditionRecursive(subCondition, consents));
}
function evaluateOrCondition(orCondition, consents) {
    const orConditions = Array.isArray(orCondition) ? orCondition : [
        orCondition
    ];
    validateNonEmptyConditions(orConditions, 'OR');
    return orConditions.some((subCondition)=>evaluateConditionRecursive(subCondition, consents));
}
function evaluateConditionRecursive(condition, consents) {
    if ('string' == typeof condition) return evaluateCategoryCondition(condition, consents);
    if ('object' == typeof condition && null !== condition) {
        if ('and' in condition) return evaluateAndCondition(condition.and, consents);
        if ('or' in condition) return evaluateOrCondition(condition.or, consents);
        if ('not' in condition) return !evaluateConditionRecursive(condition.not, consents);
    }
    throw new TypeError(`Invalid condition structure: ${JSON.stringify(condition)}`);
}
function has(condition, consents, options) {
    const runtimeConsents = options ? applyPolicyScopeForRuntimeGating(consents, options.policyCategories, options.policyScopeMode) : consents;
    return evaluateConditionRecursive(condition, runtimeConsents);
}
function extractConsentNamesFromCondition(condition) {
    const categories = new Set();
    function recurse(cond) {
        if ('string' == typeof cond) return void categories.add(cond);
        if ('object' == typeof cond && null !== cond) {
            if ('and' in cond) {
                const conditions = Array.isArray(cond.and) ? cond.and : [
                    cond.and
                ];
                conditions.forEach(recurse);
            } else if ('or' in cond) {
                const conditions = Array.isArray(cond.or) ? cond.or : [
                    cond.or
                ];
                conditions.forEach(recurse);
            } else if ('not' in cond) recurse(cond.not);
        }
    }
    recurse(condition);
    return Array.from(categories);
}
function createDefaultConsentState() {
    return {
        experience: false,
        functionality: false,
        marketing: false,
        measurement: false,
        necessary: true
    };
}
function determineRequiredConsent(iframe) {
    const categoryAttr = iframe.getAttribute('data-category');
    if (!categoryAttr) return;
    if (!allConsentNames.includes(categoryAttr)) throw new Error(`Invalid category attribute "${categoryAttr}" on iframe. Must be one of: ${allConsentNames.join(', ')}`);
    return categoryAttr;
}
function processIframeElement(iframe, consents) {
    const dataSrc = iframe.getAttribute('data-src');
    const requiredConsent = determineRequiredConsent(iframe);
    if (!requiredConsent) return;
    const hasConsent = has(requiredConsent, consents);
    if (hasConsent) {
        if (dataSrc && !iframe.src) {
            iframe.src = dataSrc;
            iframe.removeAttribute('data-src');
        }
    } else if (iframe.src) iframe.removeAttribute('src');
}
function createIframeBlocker(config = {}, initialConsents) {
    const blockerConfig = {
        disableAutomaticBlocking: false,
        ...config
    };
    let consents = initialConsents || createDefaultConsentState();
    function processIframes() {
        const iframes = document.querySelectorAll('iframe');
        iframes.forEach((iframe)=>{
            processIframeElement(iframe, consents);
        });
    }
    function setupMutationObserver() {
        const observer = new MutationObserver((mutations)=>{
            mutations.forEach((mutation)=>{
                mutation.addedNodes.forEach((node)=>{
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        const element = node;
                        if (element.tagName && 'IFRAME' === element.tagName.toUpperCase()) processIframeElement(element, consents);
                        const iframes = element.querySelectorAll?.('iframe');
                        if (iframes) iframes.forEach((iframe)=>{
                            processIframeElement(iframe, consents);
                        });
                    }
                });
            });
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
        return observer;
    }
    let mutationObserver = null;
    if (!blockerConfig.disableAutomaticBlocking) {
        processIframes();
        mutationObserver = setupMutationObserver();
    }
    return {
        updateConsents: (newConsents)=>{
            consents = {
                ...consents,
                ...newConsents
            };
            processIframes();
        },
        processIframes,
        destroy: ()=>{
            if (mutationObserver) {
                mutationObserver.disconnect();
                mutationObserver = null;
            }
        }
    };
}
function getIframeConsentCategories() {
    if ("u" < typeof document) return [];
    const iframes = document.querySelectorAll('iframe[data-category]');
    const categories = new Set();
    if (!iframes) return [];
    iframes.forEach((iframe)=>{
        const categoryAttr = iframe.getAttribute('data-category');
        if (!categoryAttr) return;
        const category = categoryAttr.trim();
        if (allConsentNames.includes(category)) categories.add(category);
    });
    return Array.from(categories);
}
function processAllIframes(consents) {
    if ("u" < typeof document) return;
    const iframes = document.querySelectorAll('iframe');
    if (!iframes) return;
    iframes.forEach((iframe)=>{
        processIframeElement(iframe, consents);
    });
}
function setupIframeObserver(getConsents, onCategoriesDiscovered) {
    const observer = new MutationObserver((mutations)=>{
        const currentConsents = getConsents();
        let hasNewCategories = false;
        mutations.forEach((mutation)=>{
            mutation.addedNodes.forEach((node)=>{
                if (node.nodeType === Node.ELEMENT_NODE) {
                    const element = node;
                    if (element.tagName && 'IFRAME' === element.tagName.toUpperCase()) {
                        processIframeElement(element, currentConsents);
                        if (element.hasAttribute('data-category')) hasNewCategories = true;
                    }
                    const iframes = element.querySelectorAll?.('iframe');
                    if (iframes && iframes.length > 0) iframes.forEach((iframe)=>{
                        processIframeElement(iframe, currentConsents);
                        if (iframe.hasAttribute('data-category')) hasNewCategories = true;
                    });
                }
            });
        });
        if (hasNewCategories && onCategoriesDiscovered) {
            const categories = getIframeConsentCategories();
            if (categories.length > 0) onCategoriesDiscovered(categories);
        }
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
    return observer;
}
const DEFAULT_POLICY_ACTIONS = [
    'reject',
    'accept',
    'customize'
];
function dedupeActions(actions) {
    if (!actions || 0 === actions.length) return [];
    return [
        ...new Set(actions)
    ];
}
function resolvePolicyAllowedActions(params) {
    const allowed = dedupeActions(params.allowedActions);
    return allowed.length > 0 ? allowed : [
        ...DEFAULT_POLICY_ACTIONS
    ];
}
function flattenPolicyActionGroups(layout) {
    if (!layout || 0 === layout.length) return [];
    return layout.flatMap((group)=>Array.isArray(group) ? group : [
            group
        ]);
}
function resolvePolicyActionGroups(params) {
    const allowedActions = dedupeActions(params.allowedActions);
    if (0 === allowedActions.length) return [];
    if (!params.layout || 0 === params.layout.length) return [
        [
            ...allowedActions
        ]
    ];
    const allowedSet = new Set(allowedActions);
    const groups = [];
    const seen = new Set();
    for (const group of params.layout){
        const actions = dedupeActions(Array.isArray(group) ? group : [
            group
        ]).filter((action)=>{
            if (!allowedSet.has(action) || seen.has(action)) return false;
            seen.add(action);
            return true;
        });
        if (actions.length > 0) groups.push(actions);
    }
    return groups.length > 0 ? groups : [
        [
            ...allowedActions
        ]
    ];
}
function resolvePolicyOrderedActions(params) {
    return flattenPolicyActionGroups(resolvePolicyActionGroups({
        allowedActions: params.allowedActions,
        layout: params.layout
    }));
}
function resolvePolicyPrimaryActions(params) {
    const defaultPrimary = params.orderedActions.includes('customize') ? [
        'customize'
    ] : [];
    if (!params.primaryActions || 0 === params.primaryActions.length) return defaultPrimary;
    const filtered = params.primaryActions.filter((action)=>params.orderedActions.includes(action));
    return filtered.length > 0 ? filtered : defaultPrimary;
}
function resolvePolicyDirection(direction) {
    if ('column' === direction) return 'column';
    return 'row';
}
function resolvePolicyUiProfile(profile) {
    if ('balanced' === profile || 'compact' === profile || 'strict' === profile) return profile;
    return 'compact';
}
function shouldFillPolicyActions(params) {
    const effectiveUiProfile = resolvePolicyUiProfile(params.uiProfile);
    const actionCount = new Set(params.actionGroups.flat()).size;
    const isSplitLayout = params.actionGroups.length > 1;
    const isColumn = 'column' === params.direction;
    return 'strict' === effectiveUiProfile || 'balanced' === effectiveUiProfile && (actionCount <= 2 || 3 === actionCount && (isSplitLayout || isColumn));
}
function hasPolicyHints(surface) {
    if (!surface) return false;
    return Object.values(surface).some((value)=>{
        if (Array.isArray(value)) return value.length > 0;
        return void 0 !== value;
    });
}
function global_privacy_control_hasGlobalPrivacyControlSignal() {
    if ("u" < typeof window) return false;
    try {
        const navigatorWithGPC = window.navigator;
        const value = navigatorWithGPC.globalPrivacyControl;
        return true === value || '1' === value;
    } catch  {
        return false;
    }
}
const request_context_ABSOLUTE_URL_REGEX = /^https?:\/\//;
function trimTrailingSlash(value) {
    if ('/' === value) return value;
    return value.endsWith('/') ? value.slice(0, -1) : value;
}
function normalizeAbsoluteURL(url) {
    const normalized = url.toString();
    return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;
}
function request_context_buildRequestContextHeaders(overrides) {
    const headers = {};
    if (overrides?.country) headers['x-c15t-country'] = overrides.country;
    if (overrides?.region) headers['x-c15t-region'] = overrides.region;
    if (overrides?.language) headers['accept-language'] = overrides.language;
    return headers;
}
function canonicalizeBrowserBackendURL(backendURL) {
    try {
        const normalizedBackendURL = trimTrailingSlash(backendURL);
        if (request_context_ABSOLUTE_URL_REGEX.test(normalizedBackendURL)) return normalizeAbsoluteURL(new URL(normalizedBackendURL));
        if (!normalizedBackendURL.startsWith('/')) return;
        return normalizeAbsoluteURL(new URL(normalizedBackendURL, window.location.origin));
    } catch  {
        return;
    }
}
function createRuntimeRequestContextMatcher(options) {
    const normalizedBackendURL = canonicalizeBrowserBackendURL(options.backendURL);
    if (!normalizedBackendURL) return;
    const detectedGpc = global_privacy_control_hasGlobalPrivacyControlSignal();
    return {
        backendURL: normalizedBackendURL,
        country: options.overrides?.country,
        region: options.overrides?.region,
        language: options.overrides?.language,
        gpc: options.overrides?.gpc ?? ('boolean' == typeof detectedGpc ? detectedGpc : false),
        credentials: options.credentials ?? 'include'
    };
}
function matchesStoredRequestContext(stored, matcher) {
    if (stored.backendURL !== matcher.backendURL) return false;
    if (stored.gpc !== matcher.gpc) return false;
    if (void 0 !== matcher.country && stored.country !== matcher.country) return false;
    if (void 0 !== matcher.region && stored.region !== matcher.region) return false;
    if (void 0 !== matcher.language && stored.language !== matcher.language) return false;
    if (void 0 !== stored.credentials && stored.credentials !== matcher.credentials) return false;
    return true;
}
const WINDOW_PROMISES_KEY = '__c15tInitialDataPromises';
function getBrowserWindow() {
    if ("u" < typeof window) return;
    return window;
}
function getMatchingPrefetchEntry(options) {
    const browserWindow = getBrowserWindow();
    if (!browserWindow) return;
    const matcher = createRuntimeRequestContextMatcher({
        backendURL: options.backendURL,
        overrides: options.overrides,
        credentials: options.credentials
    });
    if (!matcher) return;
    const entries = Object.values(browserWindow[WINDOW_PROMISES_KEY] ?? {});
    const matches = entries.filter((entry)=>{
        const requestContext = entry.requestContext;
        return requestContext ? matchesStoredRequestContext(requestContext, matcher) : false;
    });
    return 1 === matches.length ? matches[0] : void 0;
}
function getMatchingPrefetchedInitialData(options) {
    return getMatchingPrefetchEntry(options)?.promise;
}
function buildPrefetchScript(options) {
    const payload = {
        backendURL: options.backendURL,
        credentials: options.credentials ?? 'include',
        headers: {
            ...headers_C15T_VERSION_HEADERS,
            ...request_context_buildRequestContextHeaders(options.overrides)
        },
        requestContext: {
            country: options.overrides?.country ?? null,
            region: options.overrides?.region ?? null,
            language: options.overrides?.language ?? null
        }
    };
    const json = JSON.stringify(payload).replace(/</g, '\\u003c');
    return `(() => {
  const mapKey = '${WINDOW_PROMISES_KEY}';
  if (typeof window === 'undefined') {
    return;
  }
  const payload = ${json};
  const trimTrailingSlash = (value) => {
    if (value === '/') {
      return value;
    }
    return value.endsWith('/') ? value.slice(0, -1) : value;
  };
  const canonicalizeBackendURL = (backendURL) => {
    try {
      const normalizedBackendURL = trimTrailingSlash(backendURL);
      if (/^https?:\\/\\//.test(normalizedBackendURL)) {
        return trimTrailingSlash(new URL(normalizedBackendURL).toString());
      }
      if (!normalizedBackendURL.startsWith('/')) {
        return undefined;
      }
      return trimTrailingSlash(
        new URL(normalizedBackendURL, window.location.origin).toString()
      );
    } catch {
      return undefined;
    }
  };
  const buildCacheKey = (url, credentials, headers, gpc) => {
    const sortedHeaders = Object.entries(headers)
      .sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey))
      .map(([key, value]) => key + ':' + value)
      .join('|');
    return url + '|' + credentials + '|gpc:' + String(gpc) + '|' + sortedHeaders;
  };
  const detectGpc = () => {
    try {
      const value = window.navigator.globalPrivacyControl;
      return value === true || value === '1';
    } catch {
      return false;
    }
  };
  const backendURL = canonicalizeBackendURL(payload.backendURL);
  if (!backendURL) {
    return;
  }
  const gpc = detectGpc();
  const requestContext = {
    backendURL,
    country: payload.requestContext.country,
    region: payload.requestContext.region,
    language: payload.requestContext.language,
    gpc,
    credentials: payload.credentials
  };
  const url = backendURL + '/init';
  const cacheKey = buildCacheKey(url, payload.credentials, payload.headers, gpc);
  const promises = (window[mapKey] = window[mapKey] || {});
  if (promises[cacheKey]) {
    return;
  }
  const promise = fetch(url, {
    method: 'GET',
    credentials: payload.credentials,
    headers: payload.headers
  })
    .then((response) => (response.ok ? response.json() : undefined))
    .then((init) => (init
      ? {
          init,
          gvl: init.gvl,
          metadata: {
            requestContext
          }
        }
      : undefined))
    .catch(() => undefined);
  promises[cacheKey] = {
    promise,
    requestContext
  };
})();`;
}
const REGISTRY_KEY = '__c15tScriptDebugListeners';
let fallbackListeners = null;
function getListeners() {
    if ("u" < typeof window) {
        if (!fallbackListeners) fallbackListeners = new Set();
        return fallbackListeners;
    }
    const host = window;
    const existing = host[REGISTRY_KEY];
    if (existing) return existing;
    const listeners = new Set();
    host[REGISTRY_KEY] = listeners;
    return listeners;
}
function emitScriptDebugEvent(event) {
    const fullEvent = {
        ...event,
        timestamp: Date.now()
    };
    for (const listener of getListeners())try {
        listener(fullEvent);
    } catch (error) {
        console.error("Failed to handle c15t script debug event listener", error);
    }
    return fullEvent;
}
function subscribeToScriptDebugEvents(listener) {
    const listeners = getListeners();
    listeners.add(listener);
    return ()=>{
        listeners.delete(listener);
    };
}
function generateRandomScriptId() {
    if ("u" > typeof crypto && crypto.randomUUID) return crypto.randomUUID().replace(/-/g, '').substring(0, 8);
    if ("u" > typeof crypto && crypto.getRandomValues) {
        const array = new Uint8Array(4);
        crypto.getRandomValues(array);
        return Array.from(array, (byte)=>byte.toString(36)).join('').padEnd(8, '0').substring(0, 8);
    }
    const randomStr = Math.random().toString(36).substring(2);
    return randomStr.padEnd(8, '0').substring(0, 8);
}
function getScriptElementId(scriptId, anonymizeId, scriptIdMap) {
    if (anonymizeId) {
        if (scriptIdMap[scriptId]) return scriptIdMap[scriptId];
        scriptIdMap[scriptId] = generateRandomScriptId();
        return scriptIdMap[scriptId];
    }
    return `c15t-script-${scriptId}`;
}
const loadedScripts = new Map();
function hasLoadedScript(src) {
    return loadedScripts.has(src);
}
function getLoadedScript(src) {
    return loadedScripts.get(src);
}
function setLoadedScript(src, element) {
    loadedScripts.set(src, element);
}
function deleteLoadedScript(src) {
    loadedScripts.delete(src);
}
function utils_getLoadedScriptsSnapshot() {
    return loadedScripts;
}
function hasIABConsent(script, iabConsent) {
    if (void 0 !== script.vendorId) {
        const vendorKey = String(script.vendorId);
        if (!iabConsent.vendorConsents[vendorKey]) return false;
    }
    if (script.iabPurposes && script.iabPurposes.length > 0) {
        const hasAllPurposeConsents = script.iabPurposes.every((purposeId)=>true === iabConsent.purposeConsents[purposeId]);
        if (!hasAllPurposeConsents) return false;
    }
    if (script.iabLegIntPurposes && script.iabLegIntPurposes.length > 0) {
        const hasAllLegIntConsents = script.iabLegIntPurposes.every((purposeId)=>true === iabConsent.purposeLegitimateInterests[purposeId]);
        if (!hasAllLegIntConsents) return false;
    }
    if (script.iabSpecialFeatures && script.iabSpecialFeatures.length > 0) {
        const hasAllSpecialFeatures = script.iabSpecialFeatures.every((featureId)=>true === iabConsent.specialFeatureOptIns[featureId]);
        if (!hasAllSpecialFeatures) return false;
    }
    return true;
}
function scriptHasConsent(script, consents, options) {
    if (options?.model === 'iab' && options.iabConsent && (void 0 !== script.vendorId || script.iabPurposes || script.iabLegIntPurposes || script.iabSpecialFeatures)) return hasIABConsent(script, options.iabConsent);
    return has(script.category, consents);
}
function emitLifecycleEvent(script, action, message, info, data) {
    emitScriptDebugEvent({
        source: "script-loader",
        scope: 'lifecycle',
        action,
        message,
        scriptId: script.id,
        elementId: info?.elementId,
        hasConsent: info?.hasConsent,
        callback: getCallbackFromAction(action, data),
        data
    });
}
function getCallbackFromAction(action, data) {
    if ('callback_start' === action || 'callback_complete' === action || 'callback_error' === action) return data?.callback;
}
function getErrorMessage(error) {
    if (error instanceof Error) return error.message;
    if ('string' == typeof error) return error;
    return 'Unknown error';
}
function invokeScriptCallback(script, callbackName, callback, info) {
    if (!callback) return;
    emitLifecycleEvent(script, 'callback_start', `${callbackName} started`, info, {
        callback: callbackName
    });
    try {
        callback(info);
        emitLifecycleEvent(script, 'callback_complete', `${callbackName} completed`, info, {
            callback: callbackName
        });
    } catch (error) {
        emitLifecycleEvent(script, 'callback_error', `${callbackName} failed`, info, {
            callback: callbackName,
            error: getErrorMessage(error)
        });
        throw error;
    }
}
function loadScripts(scripts, consents, scriptIdMap = {}, options) {
    const loadedScriptIds = [];
    scripts.forEach((script)=>{
        const hasConsent = scriptHasConsent(script, consents, options);
        if (!script.alwaysLoad && !hasConsent) return void emitLifecycleEvent(script, 'skipped', 'Script skipped due to missing consent', {
            hasConsent
        }, {
            reason: 'missing_consent'
        });
        if (hasLoadedScript(script.id)) {
            const callbackInfo = {
                id: script.id,
                elementId: getScriptElementId(script.id, false !== script.anonymizeId, scriptIdMap),
                hasConsent,
                consents
            };
            emitLifecycleEvent(script, 'already_loaded', 'Script already loaded; running consent sync', callbackInfo);
            invokeScriptCallback(script, 'onConsentChange', script.onConsentChange, callbackInfo);
            return;
        }
        if (script.src && script.textContent) throw new Error(`Script '${script.id}' cannot have both 'src' and 'textContent'. Choose one.`);
        if (!script.src && !script.textContent && !script.callbackOnly) throw new Error(`Script '${script.id}' must have either 'src', 'textContent', or 'callbackOnly' set to true.`);
        if (true === script.callbackOnly) {
            const shouldAnonymize = false !== script.anonymizeId;
            const elementId = getScriptElementId(script.id, shouldAnonymize, scriptIdMap);
            const callbackInfo = {
                id: script.id,
                elementId,
                consents,
                hasConsent
            };
            invokeScriptCallback(script, 'onBeforeLoad', script.onBeforeLoad, callbackInfo);
            invokeScriptCallback(script, 'onLoad', script.onLoad, callbackInfo);
            setLoadedScript(script.id, null);
            loadedScriptIds.push(script.id);
            emitLifecycleEvent(script, 'loaded', "Callback-only script marked as loaded", callbackInfo, {
                callbackOnly: true
            });
            return;
        }
        const shouldAnonymize = false !== script.anonymizeId;
        const elementId = getScriptElementId(script.id, shouldAnonymize, scriptIdMap);
        if (true === script.persistAfterConsentRevoked) {
            const existingElement = document.getElementById(elementId);
            if (existingElement) {
                const callbackInfo = {
                    id: script.id,
                    hasConsent,
                    elementId,
                    consents,
                    element: existingElement
                };
                emitLifecycleEvent(script, 'already_loaded', "Persisted script element already exists; reusing it", callbackInfo, {
                    reason: 'persisted_element'
                });
                invokeScriptCallback(script, 'onConsentChange', script.onConsentChange, callbackInfo);
                invokeScriptCallback(script, 'onLoad', script.onLoad, callbackInfo);
                setLoadedScript(script.id, existingElement);
                loadedScriptIds.push(script.id);
                emitLifecycleEvent(script, 'loaded', "Existing script element marked as loaded", callbackInfo, {
                    reusedElement: true
                });
                return;
            }
        }
        const scriptElement = document.createElement("script");
        scriptElement.id = elementId;
        if (script.src) scriptElement.src = script.src;
        else if (script.textContent) scriptElement.textContent = script.textContent;
        if (script.fetchPriority) scriptElement.fetchPriority = script.fetchPriority;
        if (script.async) scriptElement.async = true;
        else if (false === script.async) scriptElement.async = false;
        if (script.defer) scriptElement.defer = true;
        const nonce = script.nonce ?? options?.nonce;
        if (nonce) scriptElement.nonce = nonce;
        if (script.attributes) Object.entries(script.attributes).forEach(([key, value])=>{
            scriptElement.setAttribute(key, value);
        });
        const callbackInfo = {
            id: script.id,
            hasConsent,
            elementId,
            consents,
            element: scriptElement
        };
        if (script.onLoad) if (script.textContent) setTimeout(()=>{
            invokeScriptCallback(script, 'onLoad', script.onLoad, {
                ...callbackInfo
            });
        }, 0);
        else {
            emitLifecycleEvent(script, 'load_listener_attached', 'Attached load listener', callbackInfo);
            scriptElement.addEventListener('load', ()=>{
                invokeScriptCallback(script, 'onLoad', script.onLoad, {
                    ...callbackInfo
                });
            });
        }
        if (script.onError) if (script.textContent) ;
        else {
            emitLifecycleEvent(script, 'error_listener_attached', 'Attached error listener', callbackInfo);
            scriptElement.addEventListener('error', ()=>{
                invokeScriptCallback(script, 'onError', script.onError, {
                    ...callbackInfo,
                    error: new Error(`Failed to load script: ${script.src}`)
                });
            });
        }
        invokeScriptCallback(script, 'onBeforeLoad', script.onBeforeLoad, callbackInfo);
        const target = script.target ?? 'head';
        const targetElement = 'body' === target ? document.body : document.head;
        if (!targetElement) throw new Error(`Document ${target} is not available for script injection`);
        targetElement.appendChild(scriptElement);
        emitLifecycleEvent(script, 'element_appended', `Script element appended to ${target}`, callbackInfo, {
            target
        });
        setLoadedScript(script.id, scriptElement);
        loadedScriptIds.push(script.id);
        emitLifecycleEvent(script, 'loaded', 'Script marked as loaded', callbackInfo);
    });
    return loadedScriptIds;
}
function unloadScripts(scripts, consents, scriptIdMap = {}, options) {
    const unloadedScriptIds = [];
    scripts.forEach((script)=>{
        const hasConsent = scriptHasConsent(script, consents, options);
        if (!hasLoadedScript(script.id)) return;
        if (script.alwaysLoad) return;
        if (!hasConsent) {
            const scriptElement = getLoadedScript(script.id);
            const callbackInfo = {
                id: script.id,
                elementId: getScriptElementId(script.id, false !== script.anonymizeId, scriptIdMap),
                hasConsent,
                consents,
                element: scriptElement && null !== scriptElement ? scriptElement : void 0
            };
            if (true === script.callbackOnly || null === scriptElement) {
                deleteLoadedScript(script.id);
                unloadedScriptIds.push(script.id);
                emitLifecycleEvent(script, 'unloaded', "Callback-only script marked as unloaded", callbackInfo, {
                    callbackOnly: true
                });
            } else if (scriptElement) if (script.persistAfterConsentRevoked) {
                deleteLoadedScript(script.id);
                unloadedScriptIds.push(script.id);
                emitLifecycleEvent(script, 'unloaded', "Persistent script marked as unloaded without removing element", callbackInfo, {
                    removedElement: false,
                    persistAfterConsentRevoked: true
                });
            } else {
                scriptElement.remove();
                deleteLoadedScript(script.id);
                unloadedScriptIds.push(script.id);
                emitLifecycleEvent(script, 'unloaded', 'Script element removed after consent revocation', callbackInfo, {
                    removedElement: true
                });
            }
        }
    });
    return unloadedScriptIds;
}
function core_updateScripts(scripts, consents, scriptIdMap = {}, options) {
    const unloaded = unloadScripts(scripts, consents, scriptIdMap, options);
    const loaded = loadScripts(scripts, consents, scriptIdMap, options);
    return {
        loaded,
        unloaded
    };
}
function isScriptLoaded(scriptId) {
    return hasLoadedScript(scriptId);
}
function getLoadedScriptIds() {
    return Array.from(utils_getLoadedScriptsSnapshot().keys());
}
function reloadScript(scriptId, scripts, consents, scriptIdMap = {}, options) {
    const script = scripts.find((s)=>s.id === scriptId);
    if (!script) return false;
    if (hasLoadedScript(scriptId)) {
        const scriptElement = getLoadedScript(scriptId);
        if (true === script.callbackOnly || null === scriptElement) deleteLoadedScript(scriptId);
        else if (scriptElement) {
            if (!script.persistAfterConsentRevoked) scriptElement.remove();
            deleteLoadedScript(scriptId);
        }
    }
    if (!script.alwaysLoad && !scriptHasConsent(script, consents, options)) {
        emitLifecycleEvent(script, 'skipped', 'Reload skipped due to missing consent', {
            hasConsent: false,
            elementId: getScriptElementId(script.id, false !== script.anonymizeId, scriptIdMap)
        }, {
            reason: 'reload_missing_consent'
        });
        return false;
    }
    loadScripts([
        script
    ], consents, scriptIdMap, options);
    return true;
}
function createScriptManager(getState, setState) {
    const updateScriptsFn = ()=>{
        const { scripts, consents, scriptIdMap, model, iab, nonce, policyCategories, policyScopeMode } = getState();
        const iabConsent = iab?.config.enabled ? {
            vendorConsents: iab.vendorConsents,
            vendorLegitimateInterests: iab.vendorLegitimateInterests,
            purposeConsents: iab.purposeConsents,
            purposeLegitimateInterests: iab.purposeLegitimateInterests,
            specialFeatureOptIns: iab.specialFeatureOptIns
        } : void 0;
        const runtimeConsents = applyPolicyScopeForRuntimeGating(consents, policyCategories, policyScopeMode);
        const result = core_updateScripts(scripts, runtimeConsents, scriptIdMap, {
            model,
            iabConsent,
            nonce
        });
        const newLoadedScripts = {
            ...getState().loadedScripts
        };
        result.loaded.forEach((id)=>{
            newLoadedScripts[id] = true;
        });
        result.unloaded.forEach((id)=>{
            newLoadedScripts[id] = false;
        });
        setState({
            loadedScripts: newLoadedScripts
        });
        return result;
    };
    return {
        updateScripts: ()=>updateScriptsFn(),
        setScripts: (scripts)=>{
            const state = getState();
            const newScriptIdMap = {
                ...state.scriptIdMap
            };
            scripts.forEach((script)=>{
                if (false !== script.anonymizeId) newScriptIdMap[script.id] = generateRandomScriptId();
            });
            const newCategories = scripts.flatMap((script)=>extractConsentNamesFromCondition(script.category));
            setState({
                scripts: [
                    ...state.scripts,
                    ...scripts
                ],
                scriptIdMap: newScriptIdMap
            });
            getState().updateConsentCategories(newCategories);
            updateScriptsFn();
        },
        removeScript: (scriptId)=>{
            const state = getState();
            if (hasLoadedScript(scriptId)) {
                const scriptElement = getLoadedScript(scriptId);
                if (scriptElement) {
                    scriptElement.remove();
                    deleteLoadedScript(scriptId);
                }
            }
            const newScriptIdMap = {
                ...state.scriptIdMap
            };
            delete newScriptIdMap[scriptId];
            setState({
                scripts: state.scripts.filter((script)=>script.id !== scriptId),
                loadedScripts: {
                    ...state.loadedScripts,
                    [scriptId]: false
                },
                scriptIdMap: newScriptIdMap
            });
        },
        reloadScript: (scriptId)=>{
            const state = getState();
            const iabConsent = state.iab?.config.enabled ? {
                vendorConsents: state.iab.vendorConsents,
                vendorLegitimateInterests: state.iab.vendorLegitimateInterests,
                purposeConsents: state.iab.purposeConsents,
                purposeLegitimateInterests: state.iab.purposeLegitimateInterests,
                specialFeatureOptIns: state.iab.specialFeatureOptIns
            } : void 0;
            const runtimeConsents = applyPolicyScopeForRuntimeGating(state.consents, state.policyCategories, state.policyScopeMode);
            return reloadScript(scriptId, state.scripts, runtimeConsents, state.scriptIdMap, {
                model: state.model,
                iabConsent,
                nonce: state.nonce
            });
        },
        isScriptLoaded: (scriptId)=>isScriptLoaded(scriptId),
        getLoadedScriptIds: ()=>getLoadedScriptIds()
    };
}
const vanilla_namespaceObject = require("zustand/vanilla");
function createIframeManager(get, _set) {
    let observer = null;
    let isInitialized = false;
    return {
        initializeIframeBlocker: ()=>{
            if (isInitialized) return;
            if ("u" < typeof document) return;
            const state = get();
            const runtimeConsents = applyPolicyScopeForRuntimeGating(state.consents, state.policyCategories, state.policyScopeMode);
            if (state.iframeBlockerConfig?.disableAutomaticBlocking) return;
            const discoverAndRegisterCategories = ()=>{
                const iframeCategories = getIframeConsentCategories();
                if (iframeCategories.length > 0) get().updateConsentCategories(iframeCategories);
            };
            if ('loading' === document.readyState) document.addEventListener('DOMContentLoaded', discoverAndRegisterCategories);
            else discoverAndRegisterCategories();
            setTimeout(discoverAndRegisterCategories, 100);
            processAllIframes(runtimeConsents);
            observer = setupIframeObserver(()=>{
                const nextState = get();
                return applyPolicyScopeForRuntimeGating(nextState.consents, nextState.policyCategories, nextState.policyScopeMode);
            }, (categories)=>get().updateConsentCategories(categories));
            isInitialized = true;
        },
        updateIframeConsents: ()=>{
            if (!isInitialized) return;
            if ("u" < typeof document) return;
            const state = get();
            const { consents, iframeBlockerConfig } = state;
            if (iframeBlockerConfig?.disableAutomaticBlocking) return;
            processAllIframes(applyPolicyScopeForRuntimeGating(consents, state.policyCategories, state.policyScopeMode));
        },
        destroyIframeBlocker: ()=>{
            if (!isInitialized) return;
            if ("u" < typeof document) return;
            const state = get();
            const { iframeBlockerConfig } = state;
            if (iframeBlockerConfig?.disableAutomaticBlocking) return;
            if (observer) {
                observer.disconnect();
                observer = null;
            }
            isInitialized = false;
        }
    };
}
const PENDING_CONSENT_SYNC_KEY = 'c15t:pending-consent-sync';
function shouldReloadOnConsentChange(previousConsents, newConsents, previousConsentInfo, reloadOnConsentRevoked, consentTypes) {
    if (!reloadOnConsentRevoked) return false;
    if (null === previousConsentInfo) return false;
    const disabledNames = new Set(consentTypes.filter((t)=>t.disabled).map((t)=>t.name));
    const wasAnyConsentRevoked = Object.entries(newConsents).some(([key, value])=>!disabledNames.has(key) && true === previousConsents[key] && false === value);
    return wasAnyConsentRevoked;
}
function haveConsentsChanged(previousConsents, nextConsents, consentTypes) {
    return consentTypes.some((consentType)=>previousConsents[consentType.name] !== nextConsents[consentType.name]);
}
function getConsentCategoryLists(consents, consentCategories, consentTypes) {
    const activeCategories = new Set(consentCategories);
    const allowedCategories = [];
    const deniedCategories = [];
    for (const consentType of consentTypes)if (activeCategories.has(consentType.name)) if (consents[consentType.name]) allowedCategories.push(consentType.name);
    else deniedCategories.push(consentType.name);
    return {
        allowedCategories,
        deniedCategories
    };
}
async function saveConsents({ manager, type, get, set, options, emitConsentChanged }) {
    const { callbacks, selectedConsents, consents, consentTypes, updateScripts, updateIframeConsents, updateNetworkBlockerConsents, consentCategories, locationInfo, model, consentInfo, reloadOnConsentRevoked, lastBannerFetchData } = get();
    const previousConsents = {
        ...consents
    };
    const previousConsentInfo = consentInfo;
    const newConsents = {
        ...selectedConsents ?? consents ?? {}
    };
    const givenAt = Date.now();
    if ('all' === type) {
        for (const consent of consentTypes)if (consentCategories.includes(consent.name)) newConsents[consent.name] = true;
    } else if ('necessary' === type) for (const consent of consentTypes)newConsents[consent.name] = true === consent.disabled ? consent.defaultValue : false;
    const effectivePolicy = getEffectivePolicy(lastBannerFetchData);
    const policyCategories = effectivePolicy?.consent?.categories;
    const shouldEnforcePolicyScope = shouldEnforcePolicyCategoryScope(policyCategories, effectivePolicy?.consent?.scopeMode ?? null);
    const effectiveConsents = shouldEnforcePolicyScope ? applyPolicyPurposeAllowlist(newConsents, policyCategories) : newConsents;
    const requestPreferences = shouldEnforcePolicyScope ? stripDisallowedPreferenceKeys(effectiveConsents, policyCategories) : effectiveConsents;
    const didChange = haveConsentsChanged(previousConsents, effectiveConsents, consentTypes);
    const nextConsentCategoryLists = getConsentCategoryLists(effectiveConsents, consentCategories, consentTypes);
    const previousConsentCategoryLists = getConsentCategoryLists(previousConsents, consentCategories, consentTypes);
    const consentChangedPayload = didChange ? {
        preferences: effectiveConsents,
        previousPreferences: previousConsents,
        allowedCategories: nextConsentCategoryLists.allowedCategories,
        deniedCategories: nextConsentCategoryLists.deniedCategories,
        previousAllowedCategories: previousConsentCategoryLists.allowedCategories,
        previousDeniedCategories: previousConsentCategoryLists.deniedCategories
    } : null;
    const materialPolicyFingerprint = lastBannerFetchData?.policy ? await (0, types_namespaceObject.createMaterialPolicyFingerprint)(lastBannerFetchData.policy) : void 0;
    let subjectId = consentInfo?.subjectId;
    if (!subjectId) subjectId = generateSubjectId();
    const storedIdentifiers = sanitizeSubjectIdentifiers({
        externalId: get().consentInfo?.externalId,
        identityProvider: get().consentInfo?.identityProvider
    });
    const userIdentifiers = sanitizeSubjectIdentifiers({
        externalId: get().user?.id,
        identityProvider: get().user?.identityProvider
    });
    const externalId = storedIdentifiers.externalId ?? userIdentifiers.externalId;
    const identityProvider = storedIdentifiers.identityProvider ?? userIdentifiers.identityProvider;
    const nextConsentInfo = {
        time: givenAt,
        subjectId,
        materialPolicyFingerprint,
        ...externalId ? {
            externalId
        } : {},
        ...identityProvider ? {
            identityProvider
        } : {}
    };
    const needsReload = shouldReloadOnConsentChange(previousConsents, effectiveConsents, previousConsentInfo, reloadOnConsentRevoked, consentTypes);
    set({
        consents: effectiveConsents,
        selectedConsents: effectiveConsents,
        activeUI: 'none',
        consentInfo: nextConsentInfo
    });
    saveConsentToStorage({
        consents: effectiveConsents,
        consentInfo: nextConsentInfo
    }, void 0, get().storageConfig);
    if (needsReload) {
        const pendingSync = {
            type,
            subjectId,
            preferences: requestPreferences,
            givenAt,
            jurisdiction: locationInfo?.jurisdiction ?? void 0,
            jurisdictionModel: model,
            domain: window.location.hostname,
            uiSource: options?.uiSource ?? 'api',
            policySnapshotToken: lastBannerFetchData?.policySnapshotToken,
            ...externalId ? {
                externalId
            } : {},
            ...identityProvider ? {
                identityProvider
            } : {}
        };
        try {
            localStorage.setItem(PENDING_CONSENT_SYNC_KEY, JSON.stringify(pendingSync));
        } catch  {}
        callbacks.onConsentSet?.({
            preferences: effectiveConsents
        });
        if (consentChangedPayload) emitConsentChanged?.(consentChangedPayload);
        callbacks.onBeforeConsentRevocationReload?.({
            preferences: effectiveConsents
        });
        window.location.reload();
        return;
    }
    await new Promise((resolve)=>setTimeout(resolve, 0));
    updateIframeConsents();
    updateScripts();
    updateNetworkBlockerConsents();
    callbacks.onConsentSet?.({
        preferences: effectiveConsents
    });
    if (consentChangedPayload) emitConsentChanged?.(consentChangedPayload);
    const consent = await manager.setConsent({
        body: {
            type: 'cookie_banner',
            domain: window.location.hostname,
            preferences: requestPreferences,
            subjectId,
            jurisdiction: locationInfo?.jurisdiction ?? void 0,
            jurisdictionModel: model ?? void 0,
            givenAt,
            uiSource: options?.uiSource ?? 'api',
            consentAction: type,
            policySnapshotToken: lastBannerFetchData?.policySnapshotToken,
            ...externalId ? {
                externalSubjectId: externalId
            } : {},
            ...identityProvider ? {
                identityProvider
            } : {}
        }
    });
    if (!consent.ok) {
        const errorMsg = consent.error?.message ?? 'Failed to save consents';
        callbacks.onError?.({
            error: errorMsg
        });
        if (!callbacks.onError) console.error(errorMsg);
    }
}
function determineModel(jurisdiction, iabEnabled) {
    if (null == jurisdiction || 'NONE' === jurisdiction) return null;
    if (iabEnabled && [
        'UK_GDPR',
        'GDPR'
    ].includes(jurisdiction)) return 'iab';
    if ([
        'UK_GDPR',
        'GDPR',
        'CH',
        'BR',
        'APPI',
        'PIPA',
        'QC_LAW25'
    ].includes(jurisdiction)) return 'opt-in';
    if ([
        'CCPA',
        'AU',
        'PIPEDA'
    ].includes(jurisdiction)) return 'opt-out';
    return 'opt-in';
}
function calculateAutoGrantedConsents(shouldAutoGrant, hasGpcSignal) {
    if (!shouldAutoGrant) return null;
    return {
        necessary: true,
        functionality: true,
        experience: true,
        marketing: !hasGpcSignal,
        measurement: !hasGpcSignal
    };
}
function computeAutoGrantInfo(jurisdiction, iabEnabled, consentInfo, policyModel, gpcOverride, policyGpc) {
    const consentModel = 'none' === policyModel ? null : policyModel ?? determineModel(jurisdiction, iabEnabled);
    const shouldCheckGpc = void 0 !== policyGpc ? policyGpc : true;
    const hasGpcSignal = shouldCheckGpc ? void 0 !== gpcOverride ? gpcOverride : global_privacy_control_hasGlobalPrivacyControlSignal() : false;
    const shouldAutoGrantConsents = (null === consentModel || 'opt-out' === consentModel) && null === consentInfo;
    const autoGrantedConsents = calculateAutoGrantedConsents(shouldAutoGrantConsents, hasGpcSignal);
    return {
        consentModel,
        autoGrantedConsents
    };
}
function buildStoreUpdate(data, config, effectiveIABEnabled, initSourceMetadata) {
    const { get, initialTranslationConfig } = config;
    const { consentInfo, consentTypes } = get();
    const { translations, location } = data;
    const { consentModel, autoGrantedConsents } = computeAutoGrantInfo(data.jurisdiction ?? null, effectiveIABEnabled, consentInfo, data.policy?.model, config.get().overrides?.gpc, data.policy?.consent?.gpc);
    const update = {
        model: consentModel,
        isLoadingConsentInfo: false,
        branding: data.branding ?? 'c15t',
        hasFetchedBanner: true,
        lastBannerFetchData: data,
        locationInfo: {
            countryCode: location?.countryCode ?? null,
            regionCode: location?.regionCode ?? null,
            jurisdiction: data.jurisdiction ?? null
        },
        policyBanner: {
            allowedActions: data.policy?.ui?.banner?.allowedActions,
            primaryActions: data.policy?.ui?.banner?.primaryActions,
            layout: data.policy?.ui?.banner?.layout,
            direction: data.policy?.ui?.banner?.direction,
            uiProfile: data.policy?.ui?.banner?.uiProfile,
            scrollLock: data.policy?.ui?.banner?.scrollLock
        },
        policyDialog: {
            allowedActions: data.policy?.ui?.dialog?.allowedActions,
            primaryActions: data.policy?.ui?.dialog?.primaryActions,
            layout: data.policy?.ui?.dialog?.layout,
            direction: data.policy?.ui?.dialog?.direction,
            uiProfile: data.policy?.ui?.dialog?.uiProfile,
            scrollLock: data.policy?.ui?.dialog?.scrollLock
        },
        policyCategories: data.policy?.consent?.categories ?? null,
        policyScopeMode: data.policy?.consent?.scopeMode ?? null,
        initDataSource: initSourceMetadata?.initDataSource ?? null,
        initDataSourceDetail: initSourceMetadata?.initDataSourceDetail ?? null
    };
    if (null === consentInfo) if (data.policy?.ui?.mode) update.activeUI = data.policy.ui.mode;
    else update.activeUI = consentModel ? 'banner' : 'none';
    if (autoGrantedConsents) {
        update.consents = autoGrantedConsents;
        update.selectedConsents = autoGrantedConsents;
    }
    const policyCategories = data.policy?.consent?.categories;
    const hasStrictPolicyCategoryAllowlist = shouldEnforcePolicyCategoryScope(policyCategories, data.policy?.consent?.scopeMode ?? null);
    if (hasStrictPolicyCategoryAllowlist) {
        const uniqueAllowedCategories = filterConsentCategoriesByPolicy(allConsentNames, policyCategories);
        update.consentCategories = uniqueAllowedCategories;
        update.consents = applyPolicyPurposeAllowlist(update.consents ?? get().consents, uniqueAllowedCategories);
        update.selectedConsents = applyPolicyPurposeAllowlist(update.selectedConsents ?? get().selectedConsents, uniqueAllowedCategories);
    }
    const preselectedCategories = data.policy?.consent?.preselectedCategories;
    const shouldApplyPreselectedCategories = null === consentInfo && !autoGrantedConsents && Array.isArray(preselectedCategories) && preselectedCategories.length > 0;
    if (shouldApplyPreselectedCategories) {
        const displayedConsentNames = update.consentCategories ?? get().consentCategories;
        const preselectedScope = hasStrictPolicyCategoryAllowlist ? filterConsentCategoriesByPolicy(displayedConsentNames, policyCategories) : displayedConsentNames;
        const allowedPreselectedCategories = filterConsentCategoriesByPolicy(preselectedScope, preselectedCategories);
        const preselectedSet = new Set(allowedPreselectedCategories);
        const selectedConsentBaseline = update.selectedConsents ?? get().selectedConsents;
        update.selectedConsents = consentTypes.length > 0 ? consentTypes.reduce((acc, consent)=>{
            acc[consent.name] = true === consent.disabled ? consent.defaultValue : preselectedSet.has(consent.name);
            return acc;
        }, {}) : Object.fromEntries(Object.keys(selectedConsentBaseline).map((category)=>[
                category,
                'necessary' === category || preselectedSet.has(category)
            ]));
    }
    if (translations?.language && translations?.translations) {
        let customMessages;
        customMessages = initialTranslationConfig?.translations ? {
            translations: initialTranslationConfig.translations
        } : void 0;
        update.translationConfig = (0, translations_namespaceObject.prepareTranslationConfig)({
            translations: {
                [translations.language]: translations.translations
            },
            disableAutoLanguageSwitch: true,
            defaultLanguage: translations.language
        }, customMessages);
    }
    return update;
}
function triggerCallbacks(data, config, autoGrantedConsents) {
    const { get } = config;
    const { callbacks } = get();
    const { translations } = data;
    if (autoGrantedConsents) callbacks?.onConsentSet?.({
        preferences: autoGrantedConsents
    });
    if (translations?.language && translations?.translations) callbacks?.onBannerFetched?.({
        jurisdiction: data.jurisdiction,
        location: data.location,
        translations: {
            language: translations.language,
            translations: translations.translations
        }
    });
}
function getDefaultConsents(consentTypes) {
    return consentTypes.reduce((acc, consent)=>{
        acc[consent.name] = consent.defaultValue;
        return acc;
    }, {});
}
async function updateStore(data, config, _hasLocalStorageAccess, prefetchedGVL, initSourceMetadata) {
    const { set, get } = config;
    const initialState = get();
    const currentPolicyFingerprint = data.policy ? await (0, types_namespaceObject.createMaterialPolicyFingerprint)(data.policy) : void 0;
    if (initialState.consentInfo && currentPolicyFingerprint) {
        const storedPolicyFingerprint = initialState.consentInfo.materialPolicyFingerprint;
        if (storedPolicyFingerprint && storedPolicyFingerprint !== currentPolicyFingerprint) {
            const resetConsents = getDefaultConsents(initialState.consentTypes);
            deleteConsentFromStorage(void 0, initialState.storageConfig);
            set({
                consents: resetConsents,
                selectedConsents: resetConsents,
                consentInfo: null
            });
        } else if (!storedPolicyFingerprint) {
            const updatedConsentInfo = {
                ...initialState.consentInfo,
                materialPolicyFingerprint: currentPolicyFingerprint
            };
            saveConsentToStorage({
                consents: initialState.consents,
                consentInfo: updatedConsentInfo
            }, void 0, initialState.storageConfig);
            set({
                consentInfo: updatedConsentInfo
            });
        }
    }
    const { consentInfo } = get();
    let iab = get().iab;
    if (config.iabConfig && !iab) {
        const iabModule = config.iabConfig._module;
        if (iabModule) {
            iab = iabModule.createIABManager(config.iabConfig, get, set, config.manager);
            set({
                iab
            });
        } else console.error('[c15t] IAB config provided without IAB module. Install @c15t/iab and use the iab() wrapper: `import { iab } from "@c15t/iab"; iab({ cmpId: ... })`');
    }
    const serverDisabledGVL = iab?.config.enabled && !prefetchedGVL;
    const effectiveIABEnabled = iab?.config.enabled && !serverDisabledGVL;
    if (serverDisabledGVL) console.warn('IAB mode disabled: Server returned 200 without GVL. Client IAB settings overridden.');
    const { consentModel, autoGrantedConsents } = computeAutoGrantInfo(data.jurisdiction ?? null, effectiveIABEnabled, consentInfo, data.policy?.model, get().overrides?.gpc, data.policy?.consent?.gpc);
    const storeUpdate = buildStoreUpdate(data, config, effectiveIABEnabled, initSourceMetadata);
    if (serverDisabledGVL && iab) storeUpdate.iab = {
        ...iab,
        config: {
            ...iab.config,
            enabled: false
        }
    };
    else if (iab && null != data.cmpId) storeUpdate.iab = {
        ...iab,
        config: {
            ...iab.config,
            cmpId: data.cmpId
        }
    };
    set(storeUpdate);
    triggerCallbacks(data, config, autoGrantedConsents);
    get().updateScripts();
    if (effectiveIABEnabled && 'iab' === consentModel && iab) {
        const serverCustomVendors = data.customVendors ?? [];
        const clientCustomVendors = iab.config.customVendors ?? [];
        const serverVendorIds = new Set(serverCustomVendors.map((v)=>v.id));
        const mergedCustomVendors = [
            ...serverCustomVendors,
            ...clientCustomVendors.filter((v)=>!serverVendorIds.has(v.id))
        ];
        const mergedConfig = {
            ...iab.config,
            customVendors: mergedCustomVendors,
            ...null != data.cmpId && {
                cmpId: data.cmpId
            }
        };
        const iabModule = config.iabConfig?._module;
        if (iabModule) iabModule.initializeIABMode(mergedConfig, {
            set,
            get
        }, prefetchedGVL).catch((err)=>{
            console.error('Failed to initialize IAB mode in updateStore:', err);
        });
    }
}
function checkLocalStorageAccess(set) {
    try {
        if (window.localStorage) {
            window.localStorage.setItem('c15t-storage-test-key', 'test');
            window.localStorage.removeItem('c15t-storage-test-key');
            return true;
        }
    } catch (error) {
        console.warn('localStorage not available, skipping consent banner:', error);
        set({
            isLoadingConsentInfo: false,
            activeUI: 'none'
        });
    }
    return false;
}
function shouldReuseSSRData(config, data) {
    const requestContext = data.metadata?.requestContext;
    if (!requestContext || !config.backendURL) return true;
    const matcher = createRuntimeRequestContextMatcher({
        backendURL: config.backendURL,
        overrides: config.get().overrides,
        credentials: config.requestCredentials
    });
    if (!matcher) return true;
    return matchesStoredRequestContext(requestContext, matcher);
}
async function initConsentManager(config) {
    const { get, set, manager } = config;
    const { callbacks } = get();
    if ("u" < typeof window) return;
    const hasLocalStorageAccess = checkLocalStorageAccess(set);
    if (!hasLocalStorageAccess) return;
    set({
        isLoadingConsentInfo: true
    });
    processPendingConsentSync(manager, callbacks);
    const ssrResult = await tryUseSSRData(config);
    if (ssrResult) return ssrResult;
    return fetchFromAPI(config, hasLocalStorageAccess, manager, callbacks);
}
async function tryUseSSRData(config) {
    const { ssrData, set } = config;
    if (!ssrData) return void set({
        ssrDataUsed: false,
        ssrSkippedReason: 'no_data'
    });
    const data = await ssrData;
    if (data?.init && !shouldReuseSSRData(config, data)) return void set({
        ssrDataUsed: false,
        ssrSkippedReason: 'context_mismatch'
    });
    if (data?.init) {
        const initSourceMetadata = inferSSRInitSourceMetadata(data);
        await updateStore(data.init, config, true, data.gvl, {
            initDataSource: initSourceMetadata.initDataSource,
            initDataSourceDetail: initSourceMetadata.initDataSourceDetail
        });
        set({
            ssrDataUsed: true,
            ssrSkippedReason: null
        });
        return data.init;
    }
    set({
        ssrDataUsed: false,
        ssrSkippedReason: 'fetch_failed'
    });
}
async function fetchFromAPI(config, hasLocalStorageAccess, manager, callbacks) {
    const { set, get } = config;
    try {
        const { language, country, region } = config.get().overrides ?? {};
        const initContext = await manager.init({
            headers: {
                ...language && {
                    'accept-language': language
                },
                ...country && {
                    'x-c15t-country': country
                },
                ...region && {
                    'x-c15t-region': region
                }
            },
            onError: callbacks.onError ? (context)=>{
                callbacks.onError?.({
                    error: context.error?.message || 'Unknown error'
                });
            } : void 0
        });
        const { data, error } = initContext;
        if (error || !data) throw new Error(`Failed to fetch consent banner info: ${error?.message}`);
        const initSourceMetadata = inferInitSourceMetadata(initContext, get().config.mode);
        await updateStore(data, config, hasLocalStorageAccess, data.gvl ?? void 0, initSourceMetadata);
        return data;
    } catch (error) {
        console.error('Error fetching consent banner information:', error);
        set({
            isLoadingConsentInfo: false,
            activeUI: 'none'
        });
        const errorMessage = error instanceof Error ? error.message : 'Unknown error fetching consent banner information';
        callbacks.onError?.({
            error: errorMessage
        });
        return;
    }
}
function inferInitSourceMetadata(initContext, mode) {
    const response = initContext?.response ?? null;
    if (response) {
        const cache = inspectBackendCache(response.headers);
        if (cache.isCacheHit) return {
            initDataSource: 'backend-cache-hit',
            initDataSourceDetail: cache.detail
        };
        return {
            initDataSource: 'backend',
            initDataSourceDetail: cache.detail
        };
    }
    if ('offline' === mode) return {
        initDataSource: 'offline-mode',
        initDataSourceDetail: null
    };
    if ('custom' === mode) return {
        initDataSource: 'custom',
        initDataSourceDetail: null
    };
    if ('hosted' === mode || 'c15t' === mode) return {
        initDataSource: 'offline-fallback',
        initDataSourceDetail: null
    };
    return {
        initDataSource: 'backend',
        initDataSourceDetail: null
    };
}
function inferSSRInitSourceMetadata(data) {
    const cache = data.metadata?.cache;
    const requestDurationMs = data.metadata?.requestDurationMs;
    const detailParts = [
        'via=ssr'
    ];
    if (cache?.detail) detailParts.push(cache.detail);
    if ('number' == typeof requestDurationMs && Number.isFinite(requestDurationMs)) detailParts.push(`duration=${Math.max(0, Math.round(requestDurationMs))}ms`);
    const detail = detailParts.length > 0 ? detailParts.join(', ') : null;
    if (cache?.isHit === true) return {
        initDataSource: 'backend-cache-hit',
        initDataSourceDetail: detail
    };
    if (cache) return {
        initDataSource: 'backend',
        initDataSourceDetail: detail
    };
    return {
        initDataSource: 'ssr',
        initDataSourceDetail: detail
    };
}
function inspectBackendCache(headers) {
    const cacheHeaders = [
        'x-vercel-cache',
        'cf-cache-status',
        'x-cache',
        'cache-status'
    ];
    let headerDetail = null;
    let headerIndicatesHit = false;
    for (const headerName of cacheHeaders){
        const headerValue = headers.get(headerName);
        if (headerValue) {
            headerDetail = `${headerName}=${headerValue}`;
            headerIndicatesHit = /\b(hit|stale|revalidated|updating)\b/i.test(headerValue);
            break;
        }
    }
    const ageHeader = headers.get('age');
    const ageValue = ageHeader ? Number.parseInt(ageHeader, 10) : NaN;
    const ageIndicatesCache = Number.isFinite(ageValue) && ageValue > 0;
    const ageDetail = ageIndicatesCache ? `age=${ageValue}` : null;
    const detail = headerDetail && ageDetail ? `${headerDetail}, ${ageDetail}` : headerDetail ?? ageDetail;
    return {
        isCacheHit: headerIndicatesHit || ageIndicatesCache,
        detail
    };
}
function processPendingConsentSync(manager, callbacks) {
    try {
        const pendingSync = localStorage.getItem(PENDING_CONSENT_SYNC_KEY);
        if (!pendingSync) return;
        localStorage.removeItem(PENDING_CONSENT_SYNC_KEY);
        const data = JSON.parse(pendingSync);
        const { externalId: externalSubjectId, identityProvider } = sanitizeSubjectIdentifiers({
            externalId: data.externalId,
            identityProvider: data.identityProvider
        });
        manager.setConsent({
            body: {
                type: 'cookie_banner',
                domain: data.domain,
                preferences: data.preferences,
                subjectId: data.subjectId,
                jurisdiction: data.jurisdiction,
                jurisdictionModel: data.jurisdictionModel ?? void 0,
                givenAt: data.givenAt,
                uiSource: data.uiSource ?? 'api',
                policySnapshotToken: data.policySnapshotToken,
                ...externalSubjectId ? {
                    externalSubjectId
                } : {},
                ...identityProvider ? {
                    identityProvider
                } : {}
            }
        }).then((result)=>{
            if (!result.ok) {
                const errorMsg = result.error?.message ?? 'Failed to sync consent after reload';
                callbacks.onError?.({
                    error: errorMsg
                });
                if (!callbacks.onError) console.error('Failed to sync consent after reload:', errorMsg);
            }
        }).catch((err)=>{
            const errorMsg = err instanceof Error ? err.message : 'Failed to sync consent after reload';
            callbacks.onError?.({
                error: errorMsg
            });
            if (!callbacks.onError) console.error('Failed to sync consent after reload:', err);
        });
    } catch  {}
}
function normalizeMethod(method) {
    if (!method) return 'GET';
    return method.toUpperCase();
}
function createUrl(rawUrl) {
    if (!rawUrl) return null;
    try {
        if ("u" < typeof window) return null;
        return new URL(rawUrl, window.location.href);
    } catch  {
        return null;
    }
}
function hostnameMatchesRule(hostname, rule) {
    if (!hostname) return false;
    const ruleDomain = rule.domain.trim().toLowerCase();
    const targetHost = hostname.trim().toLowerCase();
    if (!ruleDomain || !targetHost) return false;
    if (targetHost === ruleDomain) return true;
    const suffix = `.${ruleDomain}`;
    const hasSuffix = targetHost.endsWith(suffix);
    return hasSuffix;
}
function pathMatchesRule(pathname, rule) {
    const hasPathFilter = 'string' == typeof rule.pathIncludes;
    if (!hasPathFilter) return true;
    if (!pathname) return false;
    return pathname.includes(rule.pathIncludes);
}
function methodMatchesRule(method, rule) {
    if (!rule.methods || 0 === rule.methods.length) return true;
    if (!method) return false;
    const upperMethod = normalizeMethod(method);
    return rule.methods.some((allowedMethod)=>normalizeMethod(allowedMethod) === upperMethod);
}
function shouldApplyRule(url, method, rule) {
    if (!hostnameMatchesRule(url.hostname, rule)) return false;
    if (!pathMatchesRule(url.pathname, rule)) return false;
    if (!methodMatchesRule(method, rule)) return false;
    return true;
}
function shouldBlockRequest(request, consents, config) {
    if (!config) return {
        shouldBlock: false
    };
    const isEnabled = false !== config.enabled;
    if (!isEnabled) return {
        shouldBlock: false
    };
    if (!config.rules || 0 === config.rules.length) return {
        shouldBlock: false
    };
    const url = createUrl(request.url);
    if (!url) return {
        shouldBlock: false
    };
    const method = normalizeMethod(request.method);
    for (const rule of config.rules){
        const applies = shouldApplyRule(url, method, rule);
        if (!applies) continue;
        const hasRequiredConsent = has(rule.category, consents);
        if (!hasRequiredConsent) return {
            shouldBlock: true,
            rule
        };
    }
    return {
        shouldBlock: false
    };
}
function createNetworkBlockerManager(get, _set) {
    let originalFetch = null;
    let originalXhrOpen = null;
    let originalXhrSend = null;
    let isInitialized = false;
    let blockingConsents = null;
    const notifyBlockedRequest = (config, info)=>{
        if (!config) return;
        if (false !== config.logBlockedRequests) {
            const ruleId = info.rule?.id ?? 'unknown';
            console.warn('[c15t] Network request blocked by consent manager', {
                method: info.method,
                url: info.url,
                ruleId
            });
        }
        if (config.onRequestBlocked) config.onRequestBlocked(info);
    };
    const getBlockingConsents = ()=>{
        if (blockingConsents) return blockingConsents;
        return get().consents;
    };
    const patchFetch = ()=>{
        if ("u" < typeof window) return;
        const hasFetch = 'function' == typeof window.fetch;
        if (!hasFetch) return;
        if (originalFetch) return;
        originalFetch = window.fetch;
        window.fetch = (input, init)=>{
            const state = get();
            const config = state.networkBlocker;
            if (!originalFetch) throw new Error('Network blocker fetch wrapper not initialized.');
            const hasRules = config?.enabled && config?.rules && config?.rules.length > 0;
            if (!hasRules) return originalFetch.call(window, input, init);
            let method = 'GET';
            if (init?.method) method = init.method;
            else if (input instanceof Request) method = input.method;
            let url;
            url = 'string' == typeof input || input instanceof URL ? input.toString() : input.url;
            const consents = getBlockingConsents();
            const { shouldBlock, rule } = shouldBlockRequest({
                url,
                method
            }, consents, config);
            if (shouldBlock) {
                notifyBlockedRequest(config, {
                    method,
                    url,
                    rule
                });
                const blockedResponse = new Response(null, {
                    status: 451,
                    statusText: 'Request blocked by consent manager'
                });
                return Promise.resolve(blockedResponse);
            }
            return originalFetch.call(window, input, init);
        };
    };
    const patchXmlHttpRequest = ()=>{
        if ("u" < typeof window) return;
        const hasXhr = void 0 !== window.XMLHttpRequest && 'function' == typeof window.XMLHttpRequest.prototype.open && 'function' == typeof window.XMLHttpRequest.prototype.send;
        if (!hasXhr) return;
        if (originalXhrOpen || originalXhrSend) return;
        originalXhrOpen = window.XMLHttpRequest.prototype.open;
        originalXhrSend = window.XMLHttpRequest.prototype.send;
        window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
            const internal = this;
            internal.__c15tMethod = method;
            internal.__c15tUrl = url;
            if (!originalXhrOpen) throw new Error('Network blocker XHR open wrapper not initialized.');
            return originalXhrOpen.call(this, method, url, async ?? true, user, password);
        };
        window.XMLHttpRequest.prototype.send = function(body) {
            const state = get();
            const config = state.networkBlocker;
            const isEnabled = config?.enabled !== false;
            const hasRules = isEnabled && config?.rules && config?.rules.length > 0;
            if (hasRules) {
                const internal = this;
                const method = internal.__c15tMethod || 'GET';
                const url = internal.__c15tUrl || '';
                const consents = getBlockingConsents();
                const { shouldBlock, rule } = shouldBlockRequest({
                    url,
                    method
                }, consents, config);
                if (shouldBlock) {
                    notifyBlockedRequest(config, {
                        method,
                        url,
                        rule
                    });
                    try {
                        this.abort();
                    } catch  {}
                    const progressEvent = new ProgressEvent('error');
                    if ('function' == typeof this.onerror) this.onerror(progressEvent);
                    this.dispatchEvent(progressEvent);
                    return;
                }
            }
            if (!originalXhrSend) throw new Error('Network blocker XHR send wrapper not initialized.');
            return originalXhrSend.call(this, body);
        };
    };
    return {
        initializeNetworkBlocker: ()=>{
            if (isInitialized) return;
            if ("u" < typeof window) return;
            const state = get();
            const config = state.networkBlocker;
            const hasRules = config?.enabled && config?.rules && config?.rules.length > 0;
            if (!hasRules) return;
            blockingConsents = state.consents;
            patchFetch();
            patchXmlHttpRequest();
            isInitialized = true;
        },
        updateNetworkBlockerConsents: ()=>{
            if (!isInitialized) return;
            blockingConsents = get().consents;
        },
        setNetworkBlocker: (config)=>{
            const isEnabled = config?.enabled !== false;
            const shouldEnable = isEnabled && config?.rules && config?.rules.length > 0;
            const partial = {
                networkBlocker: config
            };
            _set(partial);
            if (!shouldEnable) {
                if (!isInitialized) return;
                if ("u" < typeof window) return;
                if (originalFetch) {
                    window.fetch = originalFetch;
                    originalFetch = null;
                }
                if (originalXhrOpen && originalXhrSend) {
                    window.XMLHttpRequest.prototype.open = originalXhrOpen;
                    window.XMLHttpRequest.prototype.send = originalXhrSend;
                    originalXhrOpen = null;
                    originalXhrSend = null;
                }
                blockingConsents = null;
                isInitialized = false;
                return;
            }
            if (!isInitialized) {
                blockingConsents = get().consents;
                patchFetch();
                patchXmlHttpRequest();
                isInitialized = true;
            }
        },
        destroyNetworkBlocker: ()=>{
            if (!isInitialized) return;
            if ("u" < typeof window) return;
            if (originalFetch) {
                window.fetch = originalFetch;
                originalFetch = null;
            }
            if (originalXhrOpen && originalXhrSend) {
                window.XMLHttpRequest.prototype.open = originalXhrOpen;
                window.XMLHttpRequest.prototype.send = originalXhrSend;
                originalXhrOpen = null;
                originalXhrSend = null;
            }
            blockingConsents = null;
            isInitialized = false;
        }
    };
}
function coalesceInFlight(requests, key, createRequest) {
    const existingRequest = requests.get(key);
    if (existingRequest) return existingRequest;
    const request = createRequest().finally(()=>{
        if (requests.get(key) === request) requests.delete(key);
    });
    requests.set(key, request);
    return request;
}
function isLegalDocumentConsentInput(input) {
    return (0, types_namespaceObject.isLegalDocumentType)(input.type);
}
const getStoredConsent = (config)=>{
    if ("u" < typeof window) return null;
    try {
        return getConsentFromStorage(config);
    } catch (e) {
        console.error('Failed to retrieve stored consent:', e);
        return null;
    }
};
const createConsentManagerStore = (manager, options = {})=>{
    const internalOptions = options;
    const { namespace = 'c15tStore', iab, ssrData: _unusedSsrData, initialConsentCategories, initialTranslationConfig: legacyInitialTranslationConfig, initialI18nConfig, enabled = true, debug: _unusedDebug, ...storeConfigOptions } = options;
    const hasInitialTranslationInput = Boolean(legacyInitialTranslationConfig || initialI18nConfig);
    const normalizedInitialTranslationConfig = hasInitialTranslationInput ? (0, translations_namespaceObject.resolveTranslationInput)(legacyInitialTranslationConfig, initialI18nConfig) : void 0;
    setDebugEnabled(true === options.debug);
    const storedConsent = getStoredConsent(options.storageConfig);
    const getInitialConsentState = ()=>{
        if (!enabled) {
            const grantedConsents = consent_types_consentTypes.reduce((acc, consent)=>{
                acc[consent.name] = true;
                return acc;
            }, {});
            return {
                consents: grantedConsents,
                selectedConsents: grantedConsents,
                consentInfo: {
                    time: Date.now()
                },
                activeUI: 'none',
                isLoadingConsentInfo: false
            };
        }
        if (storedConsent) return {
            consents: storedConsent.consents,
            selectedConsents: storedConsent.consents,
            consentInfo: storedConsent.consentInfo,
            user: storedConsent.consentInfo?.externalId ? {
                id: storedConsent.consentInfo.externalId,
                identityProvider: storedConsent.consentInfo.identityProvider
            } : void 0,
            activeUI: 'none',
            isLoadingConsentInfo: false
        };
        return {
            activeUI: 'none',
            isLoadingConsentInfo: true
        };
    };
    const consentChangeListeners = new Set();
    const inFlightConsentSaves = new Map();
    const inFlightPolicyConsents = new Map();
    const store = (0, vanilla_namespaceObject.createStore)((set, get)=>({
            ...initial_state_initialState,
            ...storeConfigOptions,
            namespace,
            iab: null,
            ...initialConsentCategories && {
                consentCategories: initialConsentCategories
            },
            ...getInitialConsentState(),
            setActiveUI: (ui, options = {})=>{
                if ('none' === ui || 'dialog' === ui) return void set({
                    activeUI: ui
                });
                if (options.force) return void set({
                    activeUI: 'banner'
                });
                const state = get();
                const stored = getStoredConsent();
                if (!stored && !state.consentInfo && !state.isLoadingConsentInfo) set({
                    activeUI: 'banner'
                });
            },
            setSelectedConsent: (name, value)=>{
                set((state)=>{
                    const consentType = state.consentTypes.find((type)=>type.name === name);
                    if (consentType?.disabled) return state;
                    return {
                        selectedConsents: {
                            ...state.selectedConsents,
                            [name]: value
                        }
                    };
                });
            },
            saveConsents: (type, options)=>{
                const requestKey = JSON.stringify([
                    type,
                    options?.uiSource ?? null,
                    'custom' === type ? get().selectedConsents : null
                ]);
                return coalesceInFlight(inFlightConsentSaves, requestKey, ()=>saveConsents({
                        manager,
                        type,
                        get,
                        set,
                        options,
                        emitConsentChanged: (payload)=>{
                            get().callbacks.onConsentChanged?.(payload);
                            for (const listener of consentChangeListeners)listener(payload);
                        }
                    }));
            },
            setConsent: (name, value)=>{
                set((state)=>{
                    const consentType = state.consentTypes.find((type)=>type.name === name);
                    if (consentType?.disabled) return state;
                    const newConsents = {
                        ...state.consents,
                        [name]: value
                    };
                    return {
                        selectedConsents: newConsents
                    };
                });
                get().saveConsents('custom');
            },
            resetConsents: ()=>{
                set(()=>{
                    const consents = consent_types_consentTypes.reduce((acc, consent)=>{
                        acc[consent.name] = consent.defaultValue;
                        return acc;
                    }, {});
                    const resetState = {
                        consents,
                        selectedConsents: consents,
                        consentInfo: null
                    };
                    deleteConsentFromStorage(void 0, options.storageConfig);
                    return resetState;
                });
            },
            setConsentCategories: (types)=>set(()=>{
                    const { policyCategories, policyScopeMode } = get();
                    if (shouldEnforcePolicyCategoryScope(policyCategories, policyScopeMode)) return {
                        consentCategories: filterConsentCategoriesByPolicy(types, policyCategories)
                    };
                    return {
                        consentCategories: Array.from(new Set(types))
                    };
                }),
            setCallback: (name, callback)=>{
                const currentState = get();
                set((state)=>({
                        callbacks: {
                            ...state.callbacks,
                            [name]: callback
                        }
                    }));
                if ('onConsentSet' === name && callback && 'function' == typeof callback) callback?.({
                    preferences: currentState.consents
                });
                if ('onBannerFetched' === name && currentState.hasFetchedBanner && currentState.lastBannerFetchData && callback && 'function' == typeof callback) {
                    const { lastBannerFetchData } = currentState;
                    const jurisdictionCode = lastBannerFetchData.jurisdiction ?? 'NONE';
                    callback?.({
                        jurisdiction: {
                            code: jurisdictionCode,
                            message: ''
                        },
                        location: {
                            countryCode: lastBannerFetchData.location.countryCode ?? null,
                            regionCode: lastBannerFetchData.location.regionCode ?? null
                        },
                        translations: {
                            language: lastBannerFetchData.translations.language,
                            translations: lastBannerFetchData.translations.translations
                        }
                    });
                }
            },
            subscribeToConsentChanges: (listener)=>{
                consentChangeListeners.add(listener);
                return ()=>{
                    consentChangeListeners.delete(listener);
                };
            },
            setLocationInfo: (location)=>set({
                    locationInfo: location
                }),
            initConsentManager: ()=>{
                if (!enabled) return Promise.resolve(void 0);
                return initConsentManager({
                    manager,
                    ssrData: options.ssrData,
                    backendURL: internalOptions.__internal?.backendURL,
                    requestCredentials: internalOptions.__internal?.requestCredentials,
                    initialTranslationConfig: normalizedInitialTranslationConfig,
                    iabConfig: iab,
                    get,
                    set
                });
            },
            getDisplayedConsents: ()=>{
                const { consentCategories, consentTypes } = get();
                return consentTypes.filter((consent)=>consentCategories.includes(consent.name));
            },
            hasConsented: ()=>{
                const { consentInfo } = get();
                return null != consentInfo;
            },
            has: (condition)=>{
                const { consents, policyCategories, policyScopeMode } = get();
                return has(condition, consents, {
                    policyCategories,
                    policyScopeMode
                });
            },
            setTranslationConfig: (config)=>{
                set({
                    translationConfig: config
                });
            },
            updateConsentCategories: (newCategories)=>{
                const { consentCategories: currentConsentCategories, policyCategories, policyScopeMode } = get();
                const allCategoriesSet = new Set([
                    ...currentConsentCategories,
                    ...newCategories
                ]);
                let consentCategories;
                consentCategories = shouldEnforcePolicyCategoryScope(policyCategories, policyScopeMode) ? filterConsentCategoriesByPolicy(Array.from(allCategoriesSet), policyCategories) : Array.from(allCategoriesSet);
                set({
                    consentCategories
                });
            },
            identifyUser: async (user)=>{
                const currentInfo = get().consentInfo;
                const subjectId = currentInfo?.subjectId;
                set({
                    user
                });
                if (!subjectId) return;
                if (String(currentInfo?.externalId) === String(user.id) && currentInfo?.identityProvider === user.identityProvider) return;
                await manager.identifyUser({
                    body: {
                        subjectId,
                        externalId: user.id,
                        identityProvider: user.identityProvider
                    }
                });
                set({
                    consentInfo: {
                        ...currentInfo,
                        time: currentInfo?.time || Date.now(),
                        subjectId,
                        externalId: user.id,
                        identityProvider: user.identityProvider
                    }
                });
            },
            unstable_acceptPolicyConsent: (input)=>{
                const requestKey = JSON.stringify([
                    get().consentInfo?.subjectId ?? null,
                    input
                ]);
                return coalesceInFlight(inFlightPolicyConsents, requestKey, async ()=>{
                    const currentState = get();
                    const currentInfo = currentState.consentInfo;
                    const subjectId = currentInfo?.subjectId ?? generateSubjectId();
                    const storedIdentifiers = sanitizeSubjectIdentifiers({
                        externalId: currentInfo?.externalId,
                        identityProvider: currentInfo?.identityProvider
                    });
                    const userIdentifiers = sanitizeSubjectIdentifiers({
                        externalId: currentState.user?.id,
                        identityProvider: currentState.user?.identityProvider
                    });
                    const inputIdentifiers = sanitizeSubjectIdentifiers({
                        externalId: input.externalId,
                        identityProvider: input.identityProvider
                    });
                    const externalId = inputIdentifiers.externalId ?? storedIdentifiers.externalId ?? userIdentifiers.externalId;
                    const identityProvider = inputIdentifiers.identityProvider ?? storedIdentifiers.identityProvider ?? userIdentifiers.identityProvider;
                    const domain = input.domain ?? ("u" > typeof window ? window.location.hostname : 'localhost');
                    const legalDocumentConsent = isLegalDocumentConsentInput(input);
                    let legalDocumentFields = {};
                    if (legalDocumentConsent) if (input.documentSnapshotToken) legalDocumentFields = {
                        documentSnapshotToken: input.documentSnapshotToken
                    };
                    else if (input.policyHash) legalDocumentFields = {
                        policyHash: input.policyHash
                    };
                    else if (input.policyId) legalDocumentFields = {
                        policyId: input.policyId
                    };
                    else throw new Error('Legal document consent requires documentSnapshotToken, policyHash, or policyId.');
                    const givenAt = input.givenAt ?? Date.now();
                    const response = await manager.setConsent({
                        body: {
                            type: input.type,
                            subjectId,
                            domain,
                            givenAt,
                            uiSource: input.uiSource ?? 'api',
                            ...legalDocumentFields,
                            ...input.metadata ? {
                                metadata: input.metadata
                            } : {},
                            ...input.preferences ? {
                                preferences: input.preferences
                            } : {},
                            ...externalId ? {
                                externalSubjectId: externalId
                            } : {},
                            ...identityProvider ? {
                                identityProvider
                            } : {}
                        }
                    });
                    if (!response.ok || !response.data) {
                        const errorMsg = response.error?.message ?? 'Failed to accept policy consent';
                        get().callbacks.onError?.({
                            error: errorMsg
                        });
                        const error = new Error(errorMsg);
                        error.code = response.error?.code;
                        error.details = response.error?.details ?? null;
                        error.status = response.error?.status;
                        throw error;
                    }
                    const consent = {
                        ...response.data,
                        givenAt: response.data.givenAt instanceof Date ? response.data.givenAt : new Date(response.data.givenAt)
                    };
                    const latestState = get();
                    const latestInfo = latestState.consentInfo;
                    const nextConsentInfo = {
                        ...latestInfo,
                        time: consent.givenAt.getTime(),
                        subjectId,
                        ...externalId ? {
                            externalId
                        } : {},
                        ...identityProvider ? {
                            identityProvider
                        } : {}
                    };
                    set({
                        consentInfo: nextConsentInfo,
                        ...externalId ? {
                            user: {
                                id: externalId,
                                identityProvider
                            }
                        } : {}
                    });
                    saveConsentToStorage({
                        consents: latestState.consents,
                        consentInfo: nextConsentInfo
                    }, void 0, latestState.storageConfig);
                    return consent;
                });
            },
            setOverrides: async (overrides)=>{
                set({
                    overrides: {
                        ...get().overrides,
                        ...overrides
                    }
                });
                if (!enabled) return;
                return await initConsentManager({
                    manager,
                    backendURL: internalOptions.__internal?.backendURL,
                    requestCredentials: internalOptions.__internal?.requestCredentials,
                    initialTranslationConfig: normalizedInitialTranslationConfig,
                    iabConfig: iab,
                    get,
                    set
                });
            },
            setLanguage: async (language)=>await get().setOverrides({
                    ...get().overrides ?? {},
                    language
                }),
            ...createScriptManager(get, set),
            ...createIframeManager(get, set),
            ...createNetworkBlockerManager(get, set)
        }));
    store.getState().initializeIframeBlocker();
    if (options.networkBlocker) {
        store.setState({
            networkBlocker: options.networkBlocker
        });
        store.getState().initializeNetworkBlocker();
    }
    if (options.scripts && options.scripts.length > 0) store.getState().updateConsentCategories(options.scripts.flatMap((script)=>extractConsentNamesFromCondition(script.category)));
    if ("u" > typeof window) {
        window[namespace] = store;
        store.getState().callbacks.onConsentSet?.({
            preferences: store.getState().consents
        });
        if (options.user) store.getState().identifyUser(options.user);
        if (enabled) store.getState().initConsentManager();
        else store.getState().updateScripts();
    }
    return store;
};
const runtime_DEFAULT_BACKEND_URL = '/api/c15t';
const managerCache = new Map();
const storeCache = new Map();
function normalizeRuntimeMode(mode) {
    if ('offline' === mode || 'custom' === mode) return mode;
    return 'hosted';
}
function generateRuntimeCacheKey(options) {
    const enabledKey = false === options.enabled ? 'disabled' : 'enabled';
    const normalizedMode = normalizeRuntimeMode(options.mode);
    const cacheParts = [
        normalizedMode,
        options.backendURL ?? 'default',
        options.endpointHandlers ? 'custom' : 'none',
        options.storageConfig?.storageKey ?? 'default',
        options.defaultLanguage ?? 'default',
        options.languageSetKey ?? 'default',
        options.offlinePolicyKey ?? 'default',
        options.headersKey ?? 'default',
        enabledKey
    ];
    return cacheParts.join(':');
}
function generateHeadersKey(headers) {
    if (!headers) return;
    const entries = Object.entries(headers).sort(([a], [b])=>a.localeCompare(b));
    if (0 === entries.length) return;
    return entries.map(([key, value])=>`${key}=${value}`).join(',');
}
function getOrCreateConsentRuntime(options, pkgInfo) {
    const optionBag = options;
    const { mode, backendURL, store, i18n, translations, storageConfig, enabled, iab, offlinePolicy, consentCategories, debug, headers, nonce, customFetch: _unusedCustomFetch, retryConfig: _unusedRetryConfig, endpointHandlers: _unusedEndpointHandlers, ...storeOptionOverrides } = optionBag;
    const { initialI18nConfig: _unusedTopLevelInitialI18nConfig, initialTranslationConfig: _unusedTopLevelInitialTranslationConfig, ssrData: topLevelSSRData, config: topLevelConfig, ...cleanStoreOptionOverrides } = storeOptionOverrides;
    const { initialI18nConfig: _unusedStoreInitialI18nConfig, initialTranslationConfig: _unusedStoreInitialTranslationConfig, ssrData: storeSSRData, config: storeConfig, ...storeWithoutTranslationInputs } = store ?? {};
    const preferredLegacyTranslationConfig = translations ?? store?.initialTranslationConfig;
    const preferredI18nConfig = i18n ?? store?.initialI18nConfig;
    const normalizedInitialTranslationConfig = (0, translations_namespaceObject.resolveTranslationInput)(preferredLegacyTranslationConfig, preferredI18nConfig);
    const normalizedI18nConfig = normalizedInitialTranslationConfig ? (0, translations_namespaceObject.normalizeI18nConfig)(normalizedInitialTranslationConfig) : void 0;
    const normalizedLanguageSet = normalizedI18nConfig ? Object.keys(normalizedI18nConfig.messages).sort() : [];
    const resolvedIab = iab ?? storeWithoutTranslationInputs.iab;
    const resolvedOfflinePolicy = offlinePolicy ?? storeWithoutTranslationInputs.offlinePolicy;
    const resolvedStorageConfig = storageConfig ?? storeWithoutTranslationInputs.storageConfig;
    const resolvedEnabled = enabled ?? storeWithoutTranslationInputs.enabled;
    const resolvedNonce = nonce ?? storeWithoutTranslationInputs.nonce;
    const resolvedBackendURL = backendURL || runtime_DEFAULT_BACKEND_URL;
    const explicitSSRData = topLevelSSRData ?? storeSSRData;
    const cacheKey = generateRuntimeCacheKey({
        mode,
        backendURL,
        endpointHandlers: 'endpointHandlers' in options ? options.endpointHandlers : void 0,
        storageConfig: resolvedStorageConfig,
        defaultLanguage: normalizedI18nConfig?.locale,
        languageSetKey: normalizedLanguageSet.length > 0 ? normalizedLanguageSet.join(',') : void 0,
        offlinePolicyKey: resolvedOfflinePolicy ? JSON.stringify(resolvedOfflinePolicy) : void 0,
        headersKey: generateHeadersKey(headers),
        enabled: resolvedEnabled
    });
    let consentManager = managerCache.get(cacheKey);
    if (!consentManager) {
        const normalizedStoreOptions = {
            ...storeWithoutTranslationInputs,
            initialTranslationConfig: normalizedInitialTranslationConfig,
            iab: resolvedIab,
            offlinePolicy: resolvedOfflinePolicy
        };
        consentManager = 'offline' === mode ? configureConsentManager({
            mode: 'offline',
            store: normalizedStoreOptions,
            storageConfig: resolvedStorageConfig
        }) : 'custom' === mode && 'endpointHandlers' in options ? configureConsentManager({
            mode: 'custom',
            endpointHandlers: options.endpointHandlers,
            store: normalizedStoreOptions,
            storageConfig: resolvedStorageConfig
        }) : configureConsentManager({
            mode: 'c15t' === mode ? 'c15t' : 'hosted',
            backendURL: backendURL || runtime_DEFAULT_BACKEND_URL,
            headers,
            store: normalizedStoreOptions,
            storageConfig: resolvedStorageConfig
        });
        managerCache.set(cacheKey, consentManager);
    }
    let consentStore = storeCache.get(cacheKey);
    if (consentStore) {
        if (consentStore.getState().nonce !== resolvedNonce) consentStore.setState({
            nonce: resolvedNonce
        });
    } else {
        const normalizedMode = normalizeRuntimeMode(mode);
        const userConfig = storeConfig ?? topLevelConfig;
        const autoPrefetchedSSRData = 'hosted' !== normalizedMode || "u" < typeof window || explicitSSRData ? void 0 : getMatchingPrefetchedInitialData({
            backendURL: resolvedBackendURL,
            overrides: options.overrides,
            credentials: 'include'
        });
        const resolvedSSRData = explicitSSRData ?? autoPrefetchedSSRData;
        consentStore = createConsentManagerStore(consentManager, {
            config: {
                ...userConfig ?? {},
                pkg: pkgInfo?.pkg || 'c15t',
                version: pkgInfo?.version || "2.2.1",
                mode: normalizedMode,
                meta: {
                    ...userConfig?.meta ?? {},
                    ...'hosted' === normalizedMode ? {
                        backendURL: resolvedBackendURL,
                        requestCredentials: 'include'
                    } : {}
                }
            },
            ...cleanStoreOptionOverrides,
            ...storeWithoutTranslationInputs,
            iab: resolvedIab,
            offlinePolicy: resolvedOfflinePolicy,
            storageConfig: resolvedStorageConfig,
            enabled: resolvedEnabled,
            nonce: resolvedNonce,
            initialTranslationConfig: normalizedInitialTranslationConfig,
            initialConsentCategories: consentCategories,
            ssrData: resolvedSSRData,
            debug,
            __internal: 'hosted' === normalizedMode ? {
                backendURL: resolvedBackendURL,
                requestCredentials: 'include'
            } : void 0
        });
        storeCache.set(cacheKey, consentStore);
    }
    return {
        consentManager,
        consentStore,
        cacheKey
    };
}
function clearConsentRuntimeCache() {
    managerCache.clear();
    storeCache.clear();
    clearClientRegistry();
}
exports.API_ENDPOINTS = __webpack_exports__.API_ENDPOINTS;
exports.C15tClient = __webpack_exports__.C15tClient;
exports.CustomClient = __webpack_exports__.CustomClient;
exports.OfflineClient = __webpack_exports__.OfflineClient;
exports.allConsentNames = __webpack_exports__.allConsentNames;
exports.applyPolicyPurposeAllowlist = __webpack_exports__.applyPolicyPurposeAllowlist;
exports.applyPolicyScopeForRuntimeGating = __webpack_exports__.applyPolicyScopeForRuntimeGating;
exports.buildPrefetchScript = __webpack_exports__.buildPrefetchScript;
exports.clearClientRegistry = __webpack_exports__.clearClientRegistry;
exports.clearConsentRuntimeCache = __webpack_exports__.clearConsentRuntimeCache;
exports.configureConsentManager = __webpack_exports__.configureConsentManager;
exports.consentTypes = __webpack_exports__.consentTypes;
exports.createConsentManagerStore = __webpack_exports__.createConsentManagerStore;
exports.createIframeBlocker = __webpack_exports__.createIframeBlocker;
exports.deepMergeTranslations = __webpack_exports__.deepMergeTranslations;
exports.defaultTranslationConfig = __webpack_exports__.defaultTranslationConfig;
exports.deleteConsentFromStorage = __webpack_exports__.deleteConsentFromStorage;
exports.deleteCookie = __webpack_exports__.deleteCookie;
exports.detectBrowserLanguage = __webpack_exports__.detectBrowserLanguage;
exports.emitScriptDebugEvent = __webpack_exports__.emitScriptDebugEvent;
exports.filterConsentCategoriesByPolicy = __webpack_exports__.filterConsentCategoriesByPolicy;
exports.flattenPolicyActionGroups = __webpack_exports__.flattenPolicyActionGroups;
exports.generateSubjectId = __webpack_exports__.generateSubjectId;
exports.getConsentFromStorage = __webpack_exports__.getConsentFromStorage;
exports.getCookie = __webpack_exports__.getCookie;
exports.getEffectivePolicy = __webpack_exports__.getEffectivePolicy;
exports.getLoadedScriptIds = __webpack_exports__.getLoadedScriptIds;
exports.getOrCreateConsentRuntime = __webpack_exports__.getOrCreateConsentRuntime;
exports.getRootDomain = __webpack_exports__.getRootDomain;
exports.has = __webpack_exports__.has;
exports.hasPolicyHints = __webpack_exports__.hasPolicyHints;
exports.isScriptLoaded = __webpack_exports__.isScriptLoaded;
exports.isValidSubjectId = __webpack_exports__.isValidSubjectId;
exports.loadScripts = __webpack_exports__.loadScripts;
exports.mergeTranslationConfigs = __webpack_exports__.mergeTranslationConfigs;
exports.policyPackPresets = __webpack_exports__.policyPackPresets;
exports.prepareTranslationConfig = __webpack_exports__.prepareTranslationConfig;
exports.resolvePolicyActionGroups = __webpack_exports__.resolvePolicyActionGroups;
exports.resolvePolicyAllowedActions = __webpack_exports__.resolvePolicyAllowedActions;
exports.resolvePolicyDirection = __webpack_exports__.resolvePolicyDirection;
exports.resolvePolicyOrderedActions = __webpack_exports__.resolvePolicyOrderedActions;
exports.resolvePolicyPrimaryActions = __webpack_exports__.resolvePolicyPrimaryActions;
exports.resolvePolicyUiProfile = __webpack_exports__.resolvePolicyUiProfile;
exports.saveConsentToStorage = __webpack_exports__.saveConsentToStorage;
exports.setCookie = __webpack_exports__.setCookie;
exports.shouldFillPolicyActions = __webpack_exports__.shouldFillPolicyActions;
exports.subscribeToScriptDebugEvents = __webpack_exports__.subscribeToScriptDebugEvents;
exports.unloadScripts = __webpack_exports__.unloadScripts;
exports.updateScripts = __webpack_exports__.updateScripts;
exports.validateUIAgainstPolicy = __webpack_exports__.validateUIAgainstPolicy;
for(var __rspack_i in __webpack_exports__)if (-1 === [
    "API_ENDPOINTS",
    "C15tClient",
    "CustomClient",
    "OfflineClient",
    "allConsentNames",
    "applyPolicyPurposeAllowlist",
    "applyPolicyScopeForRuntimeGating",
    "buildPrefetchScript",
    "clearClientRegistry",
    "clearConsentRuntimeCache",
    "configureConsentManager",
    "consentTypes",
    "createConsentManagerStore",
    "createIframeBlocker",
    "deepMergeTranslations",
    "defaultTranslationConfig",
    "deleteConsentFromStorage",
    "deleteCookie",
    "detectBrowserLanguage",
    "emitScriptDebugEvent",
    "filterConsentCategoriesByPolicy",
    "flattenPolicyActionGroups",
    "generateSubjectId",
    "getConsentFromStorage",
    "getCookie",
    "getEffectivePolicy",
    "getLoadedScriptIds",
    "getOrCreateConsentRuntime",
    "getRootDomain",
    "has",
    "hasPolicyHints",
    "isScriptLoaded",
    "isValidSubjectId",
    "loadScripts",
    "mergeTranslationConfigs",
    "policyPackPresets",
    "prepareTranslationConfig",
    "resolvePolicyActionGroups",
    "resolvePolicyAllowedActions",
    "resolvePolicyDirection",
    "resolvePolicyOrderedActions",
    "resolvePolicyPrimaryActions",
    "resolvePolicyUiProfile",
    "saveConsentToStorage",
    "setCookie",
    "shouldFillPolicyActions",
    "subscribeToScriptDebugEvents",
    "unloadScripts",
    "updateScripts",
    "validateUIAgainstPolicy"
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
Object.defineProperty(exports, '__esModule', {
    value: true
});