{"version":3,"sources":["../src/consent-coexistence.ts"],"sourcesContent":["/**\n * Consent co-existence — \"defer, never double up\" (CD-185, PART 1).\n *\n * Crossdeck Consent is a branded banner bundled into the injected SDK. It must\n * NEVER render a second consent banner on a site that already manages consent —\n * two banners is a poor-experience marketplace auto-reject. On init we detect any\n * existing consent mechanism; if one is present we do NOT render our banner and\n * instead READ its signal and gate autocapture off it.\n *\n * Detection order (first match wins → defer & read):\n *   1. Explicit site-owner config  — \"I use my own CMP\" → read the configured source.\n *   2. GPC  — navigator.globalPrivacyControl; a legally-binding opt-out in several\n *             US states → ALWAYS honour (force marketing + analytics OFF).\n *   3. IAB TCF v2.2  — window.__tcfapi → subscribe, map purpose consents.\n *   4. IAB GPP  — window.__gpp (supersedes US Privacy __uspapi) → read US signals.\n *   5. Google Consent Mode v2  — analytics_storage / ad_storage / ad_user_data in\n *             the dataLayer → read.\n *   6. Known CMP plugins  — Cookiebot, OneTrust, CookieYes, Osano, Termly.\n *   7. Platform-native  — Webflow / Wix / Squarespace cookie banners.\n *\n * DESIGN CONTRACT (mirrors trust.ts):\n *  - ISOLATED — every global / DOM / postMessage touch is wrapped in `safe()`; a\n *    stumble in a detector can never throw into the host page or the rest of the SDK.\n *  - CONSERVATIVE — external purposes map to our {analytics, marketing} categories\n *    \"when in doubt, deny.\" A detected-but-unreadable CMP defers (no banner) AND\n *    keeps capture OFF until we can positively read a grant.\n *  - SUBSCRIBE, DON'T SNAPSHOT — where the source emits changes (TCF / GPP /\n *    Consent Mode / Cookiebot / OneTrust) we subscribe and update capture live when\n *    the visitor changes their choice in the OTHER tool. Snapshot-only sources\n *    return a no-op unsubscribe.\n *\n * API-VERIFICATION LEDGER (\"pack your bags\" — confirmed against current docs):\n *  - GPC              CONFIRMED  — https://globalprivacycontrol.github.io/gpc-spec/\n *  - TCF v2.2         CONFIRMED  — IAB Tech Lab CMP API v2 (__tcfapi signature,\n *                                  addEventListener/removeEventListener, eventStatus,\n *                                  purpose.consents):\n *                                  https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md\n *                                  Purpose IDs 1-10: https://support.didomi.io/iab-tcf-v2.2-purposes/features-summary\n *  - Cookiebot        CONFIRMED  — Cookiebot.consent.{statistics,marketing} +\n *                                  CookiebotOnConsentReady/OnAccept/OnDecline events:\n *                                  https://www.cookiebot.com/en/developer/\n *  - OneTrust         CONFIRMED  — window.OnetrustActiveGroups (',C0002,'/',C0004,')\n *                                  + OneTrust.OnConsentChanged:\n *                                  https://developer.onetrust.com/onetrust/docs/javascript-api\n *  - IAB GPP          NEEDS-FINAL-VERIFICATION — __gpp(command,cb,parameter) signature +\n *                                  ping/addEventListener/getSection confirmed\n *                                  (https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md),\n *                                  but the per-section US-state FIELD layouts (uspv1 /\n *                                  usnat / usca) vary — confirm field names before GA.\n *  - Google Consent Mode  NEEDS-FINAL-VERIFICATION — gtag('consent','default'|'update',{...})\n *                                  and the storage keys are confirmed\n *                                  (https://developers.google.com/tag-platform/security/guides/consent),\n *                                  BUT Google publishes NO official read/subscribe API\n *                                  for current consent state. We scan `dataLayer` and\n *                                  chain `dataLayer.push` (non-destructive, reversible).\n *                                  Re-confirm against the gtag reference before GA.\n *  - Osano / CookieYes / Termly  NEEDS-FINAL-VERIFICATION — presence-detected only; we do\n *                                  NOT fabricate a read API, so a detected instance defers\n *                                  and stays conservative-deny until a verified reader lands.\n *  - Webflow / Wix / Squarespace native  NEEDS-FINAL-VERIFICATION — presence-detected only,\n *                                  same conservative-deny handling as above.\n */\n\nimport type { ConsentState } from \"./consent\";\n\n// ============================================================\n// Public types\n// ============================================================\n\n/** The consent mechanisms we can detect and defer to. */\nexport type ConsentMechanism =\n  | \"site-config\"\n  | \"gpc\"\n  | \"tcf-v2\"\n  | \"gpp\"\n  | \"google-consent-mode\"\n  | \"cookiebot\"\n  | \"onetrust\"\n  | \"cookieyes\"\n  | \"osano\"\n  | \"termly\"\n  | \"webflow-native\"\n  | \"wix-native\"\n  | \"squarespace-native\";\n\n/** How confident we are in the read/subscribe wiring for a mechanism. */\nexport type VerificationStatus = \"confirmed\" | \"needs-verification\";\n\n/**\n * A detected existing consent mechanism. If `detectExistingConsent` returns one of\n * these, Crossdeck Consent MUST NOT render its own banner — read `read()` for the\n * current mapped grant and (if `emitsChanges`) call `subscribeToExternalConsent` to\n * follow live changes.\n */\nexport interface ExistingConsentSource {\n  /** Which mechanism was detected. */\n  readonly mechanism: ConsentMechanism;\n  /** Human-readable label for logs / the \"deferring to X\" disclosure. */\n  readonly source: string;\n  /**\n   * Snapshot read of the source, mapped conservatively to our categories. Only the\n   * keys the source speaks to are present; absent keys leave our defaults untouched.\n   * GPC returns { analytics:false, marketing:false }.\n   */\n  read(): Partial<ConsentState>;\n  /** True iff `subscribeToExternalConsent` can deliver live updates for this source. */\n  readonly emitsChanges: boolean;\n  /**\n   * Categories this source FORCES off regardless of anything else (GPC → analytics +\n   * marketing). Enforced on top of `read()` — a legally-binding opt-out cannot be\n   * flipped back on by any later signal.\n   */\n  readonly forcesDeny?: ReadonlyArray<keyof ConsentState>;\n  /** API-confirmation status for this mechanism (see the file-top ledger). */\n  readonly verification: VerificationStatus;\n}\n\n/** Options for {@link detectExistingConsent}. */\nexport interface DetectExistingConsentOptions {\n  /**\n   * The site owner explicitly declared (at install) that they run their own consent\n   * tool (\"I use my own CMP\"). Highest priority — we defer unconditionally.\n   */\n  ownConsentTool?: boolean;\n  /**\n   * Optional reader for the owner's configured source, used only when `ownConsentTool`\n   * is set. Returns their current grant mapped to our categories. If omitted we defer\n   * (render nothing) and stay conservative-deny until the owner wires a reader.\n   */\n  readOwnConsent?: () => Partial<ConsentState>;\n  /**\n   * Global scope to probe. Defaults to the real window. Injectable for tests and for\n   * SSR guards (pass a plain object to probe nothing).\n   */\n  scope?: ConsentGlobals;\n}\n\n// ============================================================\n// Typed views over the third-party globals we probe\n// ============================================================\n\n/** IAB TCF v2.2 CMP API. Signature: __tcfapi(command, version, callback, parameter?). */\ntype TcfApi = (\n  command: string,\n  version: number,\n  callback: (data: unknown, success: boolean) => void,\n  parameter?: unknown,\n) => void;\n\n/** The subset of the TCF `TCData` object we read. */\ninterface TcData {\n  eventStatus?: string;\n  gdprApplies?: boolean;\n  listenerId?: number;\n  purpose?: { consents?: Record<string, boolean> };\n}\n\n/** IAB GPP CMP API. Signature: __gpp(command, callback, parameter?, version?). */\ntype GppApi = (\n  command: string,\n  callback: (data: unknown, success: boolean) => void,\n  parameter?: unknown,\n  version?: number,\n) => void;\n\n/** Cookiebot's window.Cookiebot object (the fields we read). */\ninterface CookiebotGlobal {\n  consent?: {\n    necessary?: boolean;\n    preferences?: boolean;\n    statistics?: boolean;\n    marketing?: boolean;\n  };\n  consented?: boolean;\n}\n\n/** OneTrust's window.OneTrust object (the change hook we use). */\ninterface OneTrustGlobal {\n  OnConsentChanged?: (callback: (event: unknown) => void) => void;\n}\n\n/** A dataLayer that is a real array with a reassignable push (Google Consent Mode). */\ntype DataLayerArray = unknown[] & {\n  push: (...items: unknown[]) => number;\n};\n\n/**\n * The globals we probe. Everything is optional — presence is the detection signal.\n * Kept as one interface so `scope` is fully typed with no `any`.\n */\nexport interface ConsentGlobals {\n  navigator?: Navigator & { globalPrivacyControl?: boolean };\n  __tcfapi?: TcfApi;\n  __gpp?: GppApi;\n  dataLayer?: unknown[];\n  Cookiebot?: CookiebotGlobal;\n  OneTrust?: OneTrustGlobal;\n  OnetrustActiveGroups?: string;\n  OptanonActiveGroups?: string;\n  Osano?: unknown;\n  CookieYes?: unknown;\n  cookieyes?: unknown;\n  getCkyConsent?: unknown;\n  Termly?: unknown;\n  Webflow?: unknown;\n  consentPolicyManager?: unknown; // Wix\n  Static?: unknown; // Squarespace exposes window.Static\n  addEventListener?: Window[\"addEventListener\"];\n  removeEventListener?: Window[\"removeEventListener\"];\n}\n\n// ============================================================\n// Detection — first match wins\n// ============================================================\n\n/**\n * Detect the first existing consent mechanism on the page, in the CD-185 priority\n * order. Returns the source to defer to, or `null` if nothing is present (in which\n * case Crossdeck Consent may render its own banner, subject to Part 3's \"who owns\n * consent\" choice).\n *\n * Guaranteed not to throw — any probe failure is swallowed and treated as \"absent\".\n */\nexport function detectExistingConsent(\n  opts?: DetectExistingConsentOptions,\n): ExistingConsentSource | null {\n  const scope = resolveScope(opts?.scope);\n  if (!scope) return null;\n\n  // 1. Explicit site-owner config — highest priority.\n  if (opts?.ownConsentTool) {\n    const reader = opts.readOwnConsent;\n    return {\n      mechanism: \"site-config\",\n      source: \"Site owner's own consent tool\",\n      emitsChanges: false,\n      verification: \"confirmed\",\n      read: () =>\n        // Their reader wins; without one we defer AND stay conservative-deny so we\n        // never capture on a site whose consent we cannot read.\n        safeRead(() => reader?.(), undefined) ??\n        ({ analytics: false, marketing: false } as Partial<ConsentState>),\n    };\n  }\n\n  // 2. GPC — legally binding, always honoured. Checked before every CMP so it can\n  //    never be overridden by a downstream signal.\n  //    Spec: https://globalprivacycontrol.github.io/gpc-spec/\n  if (safeRead(() => scope.navigator?.globalPrivacyControl === true, false)) {\n    return {\n      mechanism: \"gpc\",\n      source: \"Global Privacy Control (navigator.globalPrivacyControl)\",\n      emitsChanges: false, // GPC is a static per-request signal; no change event.\n      forcesDeny: [\"analytics\", \"marketing\"],\n      verification: \"confirmed\",\n      read: () => ({ analytics: false, marketing: false }),\n    };\n  }\n\n  // 3. IAB TCF v2.2.\n  if (typeof scope.__tcfapi === \"function\") {\n    return {\n      mechanism: \"tcf-v2\",\n      source: \"IAB TCF v2.2 (__tcfapi)\",\n      emitsChanges: true,\n      verification: \"confirmed\",\n      read: () => readTcfSnapshot(scope),\n    };\n  }\n\n  // 4. IAB GPP (supersedes the deprecated US Privacy __uspapi).\n  if (typeof scope.__gpp === \"function\") {\n    return {\n      mechanism: \"gpp\",\n      source: \"IAB GPP (__gpp)\",\n      emitsChanges: true,\n      verification: \"needs-verification\",\n      read: () => readGppSnapshot(scope),\n    };\n  }\n\n  // 5. Google Consent Mode v2 — only if the dataLayer actually carries consent\n  //    signals (a bare GTM dataLayer is NOT a consent mechanism).\n  if (hasConsentModeSignal(scope.dataLayer)) {\n    return {\n      mechanism: \"google-consent-mode\",\n      source: \"Google Consent Mode v2 (dataLayer)\",\n      emitsChanges: true,\n      verification: \"needs-verification\",\n      read: () => readConsentMode(scope.dataLayer),\n    };\n  }\n\n  // 6. Known CMP plugins.\n  if (isObject(scope.Cookiebot)) {\n    return {\n      mechanism: \"cookiebot\",\n      source: \"Cookiebot\",\n      emitsChanges: true,\n      verification: \"confirmed\",\n      read: () => readCookiebot(scope),\n    };\n  }\n  if (\n    isObject(scope.OneTrust) ||\n    typeof scope.OnetrustActiveGroups === \"string\" ||\n    typeof scope.OptanonActiveGroups === \"string\"\n  ) {\n    return {\n      mechanism: \"onetrust\",\n      source: \"OneTrust\",\n      emitsChanges: true,\n      verification: \"confirmed\",\n      read: () => readOneTrust(scope),\n    };\n  }\n  // CookieYes / Osano / Termly — presence-detected only. We do NOT invent a read API,\n  // so we defer (no banner) and stay conservative-deny until a verified reader ships.\n  if (scope.CookieYes != null || scope.cookieyes != null || scope.getCkyConsent != null) {\n    return deferUnread(\"cookieyes\", \"CookieYes\");\n  }\n  if (scope.Osano != null) {\n    return deferUnread(\"osano\", \"Osano\");\n  }\n  if (scope.Termly != null) {\n    return deferUnread(\"termly\", \"Termly\");\n  }\n\n  // 7. Platform-native banners — presence-detected only, same conservative handling.\n  //    (Best-effort heuristics; confirm exact globals per platform before GA.)\n  if (isWebflowCookieConsent(scope)) {\n    return deferUnread(\"webflow-native\", \"Webflow cookie consent\");\n  }\n  if (scope.consentPolicyManager != null) {\n    return deferUnread(\"wix-native\", \"Wix cookie banner\");\n  }\n  if (isSquarespaceCookieBanner(scope)) {\n    return deferUnread(\"squarespace-native\", \"Squarespace cookie banner\");\n  }\n\n  return null;\n}\n\n/**\n * A detected-but-unreadable source: we defer (never double up) and keep every\n * non-essential category OFF until a verified reader for it exists. Conservative by\n * construction — \"when in doubt, deny.\"\n */\nfunction deferUnread(\n  mechanism: ConsentMechanism,\n  label: string,\n): ExistingConsentSource {\n  return {\n    mechanism,\n    source: label + \" (detected; read not yet verified)\",\n    emitsChanges: false,\n    verification: \"needs-verification\",\n    read: () => ({ analytics: false, marketing: false }),\n  };\n}\n\n// ============================================================\n// Subscription — follow live changes in the other tool\n// ============================================================\n\n/**\n * Subscribe to a source that emits changes and forward each new mapped grant to `cb`.\n * Returns an unsubscribe function. Snapshot-only sources (GPC, site-config, and any\n * presence-only `deferUnread` source) return a no-op unsubscribe.\n *\n * Guaranteed not to throw — wiring failures degrade to a no-op unsubscribe.\n */\nexport function subscribeToExternalConsent(\n  source: ExistingConsentSource,\n  cb: (state: Partial<ConsentState>) => void,\n  opts?: { scope?: ConsentGlobals },\n): () => void {\n  const scope = resolveScope(opts?.scope);\n  if (!scope || !source.emitsChanges) return noop;\n\n  switch (source.mechanism) {\n    case \"tcf-v2\":\n      return subscribeTcf(scope, cb);\n    case \"gpp\":\n      return subscribeGpp(scope, cb);\n    case \"google-consent-mode\":\n      return subscribeConsentMode(scope, cb);\n    case \"cookiebot\":\n      return subscribeCookiebot(scope, cb);\n    case \"onetrust\":\n      return subscribeOneTrust(scope, cb);\n    default:\n      return noop;\n  }\n}\n\n// ------------------------------------------------------------\n// TCF v2.2\n// ------------------------------------------------------------\n\n/**\n * Purpose → category mapping (conservative, \"when in doubt deny\").\n *   analytics ← Purpose 1 (store/access info on device) AND Purpose 8 (measure\n *               content performance) — the two purposes first-party product analytics\n *               depends on. Purposes 9/10 (cross-source audience building / product\n *               improvement) are broader and NOT required to grant analytics.\n *   marketing ← Purpose 1 AND Purpose 3 (create a personalised-ads profile) AND\n *               Purpose 4 (select personalised ads) — the core advertising consents.\n * Any required purpose missing → that category is denied.\n * IDs per https://support.didomi.io/iab-tcf-v2.2-purposes/features-summary\n */\nfunction mapTcfPurposes(d: TcData): Partial<ConsentState> {\n  // gdprApplies === false: GDPR does not apply to this user, so TCF imposes no\n  // restriction — do not manufacture a denial.\n  if (d.gdprApplies === false) return { analytics: true, marketing: true };\n  const c = d.purpose?.consents ?? {};\n  const has = (id: number): boolean => c[String(id)] === true;\n  return {\n    analytics: has(1) && has(8),\n    marketing: has(1) && has(3) && has(4),\n  };\n}\n\nfunction readTcfSnapshot(scope: ConsentGlobals): Partial<ConsentState> {\n  const api = scope.__tcfapi;\n  if (typeof api !== \"function\") return {};\n  let out: Partial<ConsentState> = {};\n  // getTCData resolves synchronously when the CMP is loaded; if it hasn't, the\n  // callback simply doesn't fire and we keep {} (defaults untouched) until the\n  // subscription delivers the first `tcloaded`.\n  safe(() =>\n    api(\"getTCData\", 2, (data: unknown, success: boolean) => {\n      if (success && isObject(data)) out = mapTcfPurposes(data as TcData);\n    }),\n  );\n  return out;\n}\n\nfunction subscribeTcf(\n  scope: ConsentGlobals,\n  cb: (state: Partial<ConsentState>) => void,\n): () => void {\n  const api = scope.__tcfapi;\n  if (typeof api !== \"function\") return noop;\n  let listenerId: number | null = null;\n\n  const handler = (data: unknown, success: boolean): void => {\n    if (!success || !isObject(data)) return;\n    const d = data as TcData;\n    if (typeof d.listenerId === \"number\") listenerId = d.listenerId;\n    // Map only on states that carry a settled consent snapshot.\n    if (d.eventStatus === \"tcloaded\" || d.eventStatus === \"useractioncomplete\") {\n      safe(() => cb(mapTcfPurposes(d)));\n    }\n  };\n\n  safe(() => api(\"addEventListener\", 2, handler));\n\n  return () => {\n    if (listenerId == null) return;\n    const id = listenerId;\n    safe(() =>\n      api(\n        \"removeEventListener\",\n        2,\n        () => {\n          /* removal ack — nothing to do */\n        },\n        id,\n      ),\n    );\n  };\n}\n\n// ------------------------------------------------------------\n// IAB GPP  (NEEDS-FINAL-VERIFICATION: per-section US-state field layouts)\n// ------------------------------------------------------------\n\n/** The subset of GPP `PingReturn` we read. */\ninterface GppPing {\n  signalStatus?: string;\n  applicableSections?: unknown;\n  parsedSections?: Record<string, unknown>;\n}\n\n/** GPP addEventListener event object. */\ninterface GppEvent {\n  eventName?: string;\n  data?: unknown;\n  pingData?: GppPing;\n}\n\n/**\n * Map GPP US-state signals conservatively. We read the (legacy but widely present)\n * US Privacy section `uspv1`, whose string's 3rd char = \"opt-out of sale\": 'Y' → the\n * user opted out → deny marketing. Analytics is not gated by US Privacy, so we leave\n * it untouched (no key emitted). The newer usnat/usca sections carry richer opt-outs\n * (targeted advertising, sale, sharing) but their FIELD names vary by version — hence\n * this mechanism is flagged needs-verification; wire those fields once confirmed.\n */\nfunction mapGppPing(ping: GppPing): Partial<ConsentState> {\n  const parsed = ping.parsedSections;\n  if (!isObject(parsed)) return {};\n  const usp = (parsed as Record<string, unknown>)[\"uspv1\"];\n  const uspString = extractUspString(usp);\n  if (uspString && uspString.length >= 3) {\n    // char[2]: 'Y' opted out of sale, 'N' did not, '-' not applicable.\n    if (uspString.charAt(2) === \"Y\") return { marketing: false };\n    if (uspString.charAt(2) === \"N\") return { marketing: true };\n  }\n  return {};\n}\n\n/** uspv1 may be parsed to a string or an object carrying the raw string. */\nfunction extractUspString(usp: unknown): string | null {\n  if (typeof usp === \"string\") return usp;\n  if (isObject(usp)) {\n    const rec = usp as Record<string, unknown>;\n    for (const key of [\"Value\", \"value\", \"uspString\", \"String\"]) {\n      if (typeof rec[key] === \"string\") return rec[key] as string;\n    }\n  }\n  return null;\n}\n\nfunction readGppSnapshot(scope: ConsentGlobals): Partial<ConsentState> {\n  const api = scope.__gpp;\n  if (typeof api !== \"function\") return {};\n  let out: Partial<ConsentState> = {};\n  safe(() =>\n    api(\"ping\", (data: unknown, success: boolean) => {\n      if (success && isObject(data)) out = mapGppPing(data as GppPing);\n    }),\n  );\n  return out;\n}\n\nfunction subscribeGpp(\n  scope: ConsentGlobals,\n  cb: (state: Partial<ConsentState>) => void,\n): () => void {\n  const api = scope.__gpp;\n  if (typeof api !== \"function\") return noop;\n  let listenerId: number | null = null;\n\n  const handler = (evt: unknown, success: boolean): void => {\n    if (!success || !isObject(evt)) return;\n    const e = evt as GppEvent & { listenerId?: number };\n    if (typeof e.listenerId === \"number\") listenerId = e.listenerId;\n    const ping = e.pingData;\n    if (isObject(ping) && (ping as GppPing).signalStatus === \"ready\") {\n      safe(() => cb(mapGppPing(ping as GppPing)));\n    }\n  };\n\n  safe(() => api(\"addEventListener\", handler));\n\n  return () => {\n    if (listenerId == null) return;\n    const id = listenerId;\n    safe(() =>\n      api(\n        \"removeEventListener\",\n        () => {\n          /* removal ack */\n        },\n        id,\n      ),\n    );\n  };\n}\n\n// ------------------------------------------------------------\n// Google Consent Mode v2  (NEEDS-FINAL-VERIFICATION: no official read/subscribe API)\n// ------------------------------------------------------------\n\n/** True iff the dataLayer carries at least one gtag('consent', …) entry. */\nfunction hasConsentModeSignal(dataLayer: unknown): boolean {\n  if (!Array.isArray(dataLayer)) return false;\n  for (const entry of dataLayer) {\n    const e = asIndexed(entry);\n    if (e && e[0] === \"consent\") return true;\n  }\n  return false;\n}\n\n/**\n * Fold every consent 'default'/'update' entry in dataLayer, last-write-wins, into our\n * categories. gtag pushes an arguments-like object `{0:'consent',1:'update',2:{…}}`;\n * we also accept plain arrays. Values are 'granted' | 'denied'; anything else → denied.\n *   analytics ← analytics_storage === 'granted'\n *   marketing ← ad_storage === 'granted'  (require the ad-cookie grant; ad_user_data /\n *               ad_personalization only narrow it further, never widen it)\n */\nfunction readConsentMode(dataLayer: unknown): Partial<ConsentState> {\n  if (!Array.isArray(dataLayer)) return {};\n  let analyticsStorage: string | undefined;\n  let adStorage: string | undefined;\n  for (const entry of dataLayer) {\n    const e = asIndexed(entry);\n    if (!e || e[0] !== \"consent\") continue;\n    const mode = e[1];\n    if (mode !== \"default\" && mode !== \"update\") continue;\n    const vals = e[2];\n    if (!isObject(vals)) continue;\n    const v = vals as Record<string, unknown>;\n    if (typeof v.analytics_storage === \"string\") analyticsStorage = v.analytics_storage;\n    if (typeof v.ad_storage === \"string\") adStorage = v.ad_storage;\n  }\n  const out: Partial<ConsentState> = {};\n  if (analyticsStorage !== undefined) out.analytics = analyticsStorage === \"granted\";\n  if (adStorage !== undefined) out.marketing = adStorage === \"granted\";\n  return out;\n}\n\n/**\n * Subscribe by CHAINING dataLayer.push. Google exposes no consent read/subscribe API,\n * so this is the pragmatic industry approach: wrap `push` to observe new consent\n * entries, always calling the original first (non-destructive), and restore the\n * original on unsubscribe (fully reversible). This wraps ONLY the customer's own\n * dataLayer array — it is not host-global fetch/XHR/history monkey-patching.\n * NEEDS-FINAL-VERIFICATION against the current gtag reference before GA.\n */\nfunction subscribeConsentMode(\n  scope: ConsentGlobals,\n  cb: (state: Partial<ConsentState>) => void,\n): () => void {\n  const dl = scope.dataLayer;\n  if (!Array.isArray(dl)) return noop;\n  const arr = dl as DataLayerArray;\n  const original = arr.push;\n  if (typeof original !== \"function\") return noop;\n  const originalBound = original.bind(arr) as DataLayerArray[\"push\"];\n  let active = true;\n\n  const wrapped: DataLayerArray[\"push\"] = (...items: unknown[]): number => {\n    const result = originalBound(...items);\n    if (active) {\n      for (const item of items) {\n        const e = asIndexed(item);\n        if (e && e[0] === \"consent\" && (e[1] === \"default\" || e[1] === \"update\")) {\n          safe(() => cb(readConsentMode(arr)));\n          break;\n        }\n      }\n    }\n    return result;\n  };\n\n  const installed = safeRead(() => {\n    arr.push = wrapped;\n    return true;\n  }, false);\n  if (!installed) return noop;\n\n  return () => {\n    active = false;\n    // Only restore if nothing else re-wrapped push after us.\n    safe(() => {\n      if (arr.push === wrapped) arr.push = original;\n    });\n  };\n}\n\n// ------------------------------------------------------------\n// Cookiebot  (CONFIRMED)\n// ------------------------------------------------------------\n\n/** Cookiebot.consent.statistics → analytics; .marketing → marketing. */\nfunction readCookiebot(scope: ConsentGlobals): Partial<ConsentState> {\n  const c = scope.Cookiebot?.consent;\n  if (!isObject(c)) return {};\n  const out: Partial<ConsentState> = {};\n  if (typeof c.statistics === \"boolean\") out.analytics = c.statistics;\n  if (typeof c.marketing === \"boolean\") out.marketing = c.marketing;\n  return out;\n}\n\n/** Confirmed events: CookiebotOnConsentReady / CookiebotOnAccept / CookiebotOnDecline. */\nconst COOKIEBOT_EVENTS = [\n  \"CookiebotOnConsentReady\",\n  \"CookiebotOnAccept\",\n  \"CookiebotOnDecline\",\n] as const;\n\nfunction subscribeCookiebot(\n  scope: ConsentGlobals,\n  cb: (state: Partial<ConsentState>) => void,\n): () => void {\n  const add = scope.addEventListener;\n  const remove = scope.removeEventListener;\n  if (typeof add !== \"function\") return noop;\n  const handler = (): void => safe(() => cb(readCookiebot(scope)));\n  for (const name of COOKIEBOT_EVENTS) {\n    safe(() => add.call(scope, name, handler as EventListener, false));\n  }\n  return () => {\n    if (typeof remove !== \"function\") return;\n    for (const name of COOKIEBOT_EVENTS) {\n      safe(() => remove.call(scope, name, handler as EventListener, false));\n    }\n  };\n}\n\n// ------------------------------------------------------------\n// OneTrust  (CONFIRMED)\n// ------------------------------------------------------------\n\n/**\n * OneTrust exposes active category IDs as a comma-wrapped string in\n * window.OnetrustActiveGroups, e.g. ',C0001,C0002,C0004,'. Default taxonomy:\n *   C0001 strictly necessary · C0002 performance/analytics · C0003 functional ·\n *   C0004 targeting/advertising · C0005 social media.\n *   analytics ← contains ',C0002,'   marketing ← contains ',C0004,'\n */\nfunction readOneTrust(scope: ConsentGlobals): Partial<ConsentState> {\n  const groups =\n    (typeof scope.OnetrustActiveGroups === \"string\" && scope.OnetrustActiveGroups) ||\n    (typeof scope.OptanonActiveGroups === \"string\" && scope.OptanonActiveGroups) ||\n    \"\";\n  if (!groups) return {};\n  return {\n    analytics: groups.includes(\",C0002,\"),\n    marketing: groups.includes(\",C0004,\"),\n  };\n}\n\nfunction subscribeOneTrust(\n  scope: ConsentGlobals,\n  cb: (state: Partial<ConsentState>) => void,\n): () => void {\n  const ot = scope.OneTrust;\n  if (!isObject(ot) || typeof ot.OnConsentChanged !== \"function\") return noop;\n  // Guarded by the typeof check above; cast to the checked call signature.\n  const onConsentChanged = ot.OnConsentChanged as (cb: () => void) => void;\n  // OnConsentChanged re-reads the (freshly updated) global string; the event detail\n  // format varies across OneTrust versions, so we always re-read OnetrustActiveGroups\n  // rather than trusting the event payload.\n  safe(() => onConsentChanged(() => safe(() => cb(readOneTrust(scope)))));\n  // OneTrust's OnConsentChanged provides no documented de-registration handle; the\n  // callback simply forwards reads. There is nothing to tear down.\n  return noop;\n}\n\n// ------------------------------------------------------------\n// Platform-native best-effort presence heuristics\n// ------------------------------------------------------------\n\n/** Webflow sites expose window.Webflow; a cookie-consent module lives under it. */\nfunction isWebflowCookieConsent(scope: ConsentGlobals): boolean {\n  if (!isObject(scope.Webflow)) return false;\n  // Presence of the cc/cookie-consent require entry is the signal; exact API varies,\n  // so we only detect (then defer conservative-deny). Confirm the read before GA.\n  return safeRead(() => {\n    const wf = scope.Webflow as { require?: (name: string) => unknown };\n    return typeof wf.require === \"function\";\n  }, false);\n}\n\n/** Squarespace exposes window.Static.SQUARESPACE_CONTEXT; the cookie banner is site-config driven. */\nfunction isSquarespaceCookieBanner(scope: ConsentGlobals): boolean {\n  if (!isObject(scope.Static)) return false;\n  return safeRead(() => {\n    const s = scope.Static as { SQUARESPACE_CONTEXT?: unknown };\n    return s.SQUARESPACE_CONTEXT != null;\n  }, false);\n}\n\n// ============================================================\n// Shared helpers\n// ============================================================\n\nconst noop = (): void => {\n  /* snapshot-only source, or nothing to tear down */\n};\n\n/**\n * Resolve the global scope to probe. Returns null in non-browser contexts (SSR) when\n * no explicit scope is supplied, so every detector short-circuits to \"absent\".\n */\nfunction resolveScope(explicit?: ConsentGlobals): ConsentGlobals | null {\n  if (explicit) return explicit;\n  const g = globalThis as unknown as { window?: ConsentGlobals };\n  if (typeof g.window !== \"undefined\" && g.window) return g.window;\n  return null;\n}\n\n/** Index an arguments-like or array entry (gtag pushes arguments objects). */\nfunction asIndexed(entry: unknown): { [k: number]: unknown } | null {\n  if (entry != null && typeof entry === \"object\") {\n    return entry as { [k: number]: unknown };\n  }\n  return null;\n}\n\n/** Narrow to a non-null plain-ish object. */\nfunction isObject(v: unknown): v is Record<string, unknown> {\n  return v != null && typeof v === \"object\";\n}\n\n/**\n * Run `fn` for side effects; swallow any throw. Isolation guarantee — a stumble in a\n * third-party global probe must never escape into the host app or the SDK.\n */\nfunction safe(fn: () => void): void {\n  try {\n    fn();\n  } catch {\n    /* isolation: probing foreign globals must never throw into the host */\n  }\n}\n\n/** Run `fn` and return its value, or `fallback` if it throws or returns undefined. */\nfunction safeRead<T>(fn: () => T, fallback: T): T {\n  try {\n    const v = fn();\n    return v === undefined ? fallback : v;\n  } catch {\n    return fallback;\n  }\n}\n"],"mappings":"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","names":[]}