{"version":3,"sources":["@webhare/env/src/envbackend.ts","@webhare/env/src/init-browser.ts","@webhare/dompack/src/tree.ts","@webhare/std/src/collections.ts","@webhare/std/src/localmutex.ts","@webhare/frontend/src/init.ts","mod::digimetrics/js/bootstrap-core.mjs","mod::digimetrics/js/basic-contract.mjs","mod::digimetrics/js/random-id.mjs","mod::digimetrics/js/basic-tracker.mjs","mod::digimetrics/js/event-contract.mjs","mod::digimetrics/js/tracker.mjs","mod::digimetrics/js/bootstrap.ts","/entrypoint.js"],"sourcesContent":["//We implement the backend version of getWHDebugFlags so bridge can access us without going through a recursive dep\n\nimport type { DTAPStage } from \"./concepts\";\n\n/// List global polyfills currently active. This may be needed to align TypeScript hosts configuration\nexport const globalPolyfills: string[] = [];\n\n/// An object with string keys and typed values\nexport interface WellKnownFlags {\n  /** Log RPcs */\n  rpc?: boolean;\n  /** Log web traffic */\n  wrq?: boolean;\n  /** Autoprofile */\n  apr?: boolean;\n  /** IPC */\n  ipc?: boolean;\n  /** async */\n  async?: boolean;\n}\nexport type DebugFlags = WellKnownFlags & { [key: string]: boolean | undefined };\n\nexport type DebugConfig = {\n  tags: readonly string[];\n  outputsession: string;\n  context: string;\n};\n\n/// Empty or no parameter lang is get, otherwise it's a set\nexport type GetSetAssetBase = (assetBase?: string | null) => string | null;\n\nexport type EnvHooks = {\n  currentAssetBase: GetSetAssetBase;\n};\n\n\nconst settingschangedcallbacks = new Array<() => void>;\n\n/* Global debug flags are set by `wh debug`, local flags are prefilled by environment variables.\n   Edits to the debug flags will be applied to the local flags (unless setDebugFlagsOverrideCB returns\n   override records).\n*/\nconst globalDebugFlags: DebugFlags = {}, localDebugFlags: DebugFlags = {};\n\n/** Returns the flag override records. The first record is examined first, then the second, etc. */\nlet debugFlagsOverridesCB: undefined | (() => DebugFlags[]);\n\n/** Override the debug flag override getter. */\nexport function setDebugFlagsOverrideCB(cb: undefined | (() => DebugFlags[])) {\n  debugFlagsOverridesCB = cb;\n}\n\n/* Proxy handler for the published debug flags. Uses the override records (with the first record\n   examined first, then the second, etc.) to override the flags from baseDebugFlags. Setting to `true` sets\n   the flag, `false` disables it and setting to `undefined` has the same effect as deleting the property in the\n   current top record (exposing any value from a lower record, like the debug settings from `wh debug`).\n*/\nclass DebugFlagsProxyHandler implements ProxyHandler<DebugFlags> {\n  private getRecordList(): DebugFlags[] {\n    return [...debugFlagsOverridesCB?.() ?? [], localDebugFlags, globalDebugFlags];\n  }\n\n  get(target: DebugFlags, p: string) {\n    for (const record of this.getRecordList())\n      if (p in record && typeof record[p] !== \"undefined\")\n        return record[p];\n    return undefined;\n  }\n  has(target: DebugFlags, p: string): boolean {\n    return this.get(target, p) !== undefined;\n  }\n  ownKeys(target: DebugFlags): Array<string | symbol> {\n    const keys = new Array<string | symbol>;\n    for (const record of this.getRecordList())\n      for (const key of Reflect.ownKeys(record))\n        if (typeof key === \"string\" && record[key] !== undefined && !keys.includes(key))\n          keys.push(key);\n    return keys;\n  }\n  set(target: DebugFlags, p: string, newValue: boolean | undefined): boolean {\n    const toModify = this.getRecordList()[0];\n    if (typeof newValue === \"boolean\")\n      toModify[p] = newValue;\n    else\n      delete toModify[p];\n\n    runSettingsCallbacks();\n    return true;\n  }\n  deleteProperty(target: DebugFlags, p: string): boolean {\n    const toModify = this.getRecordList()[0];\n    delete toModify[p];\n\n    runSettingsCallbacks();\n    return true;\n  }\n  getOwnPropertyDescriptor(target: DebugFlags, p: string): PropertyDescriptor | undefined {\n    const value = this.get(target, p);\n    return value !== undefined ? { enumerable: true, value, configurable: true } : undefined;\n  }\n}\n\nexport const debugFlags = new Proxy<DebugFlags>({\n  [Symbol.for('nodejs.util.inspect.custom')]: formatForConsoleLogs\n}, new DebugFlagsProxyHandler());\n\nfunction formatForConsoleLogs() {\n  return `DebugFlags [${[...Object.keys(debugFlags)].filter(key => debugFlags[key]).join(\", \")}]`;\n}\n\nfunction runSettingsCallbacks() {\n  for (const cb of [...settingschangedcallbacks]) {\n    try {\n      cb();\n    } catch (e) {\n      console.error(\"Error invoking settings change callback\", cb?.name, e);\n      //ignore, debugFlags can change due to external updates so they're basically signal handlers and there's no real point in crashing whatever was really running\n    }\n  }\n}\n\n/** Update the debugconfig as present in the system configuration record\n    @param settings - debugconfig cell of the system configuration record\n*/\nexport function updateDebugConfig(settings: DebugConfig | null) {\n  const oldenabledflags = Object.keys(globalDebugFlags).sort();\n  const newenabledflags = settings?.tags ? [...settings.tags].sort() : [];\n\n  if (oldenabledflags.join(\",\") !== newenabledflags.join(\",\")) {\n    for (const flag of newenabledflags)\n      globalDebugFlags[flag] = true;\n    for (const flag of oldenabledflags)\n      if (!newenabledflags.includes(flag))\n        delete globalDebugFlags[flag];\n\n    runSettingsCallbacks();\n  }\n  if (debugFlags.async && Error.stackTraceLimit < 100)\n    Error.stackTraceLimit = 100;\n}\n\nexport function registerDebugConfigChangedCallback(cb: () => void) {\n  settingschangedcallbacks.push(cb);\n}\n\nexport function updateLocalDebugFlags(mode: \"enable\" | \"disable\" | \"clear\", flags: string[]): DebugFlags {\n  switch (mode) {\n    case \"enable\":\n    case \"disable\":\n      for (const flag of flags)\n        localDebugFlags[flag] = mode === \"enable\";\n      break;\n    case \"clear\":\n      for (const flag of Object.keys(localDebugFlags))\n        delete localDebugFlags[flag];\n  }\n  runSettingsCallbacks();\n  return { ...globalDebugFlags, ...localDebugFlags };\n}\n\n/** DTAP stage set for this WebHare */\nlet dtapStage: DTAPStage = \"production\";\n\n/** @deprecated We now recommend checking dtapStage against production/acceptance Explicitly */\nlet isLive: boolean = dtapStage === \"production\" || dtapStage === \"acceptance\";\n\n/** The backend base URL. Used for eg. autoconfiguring JSON/RPC */\nlet backendBase = \"\";\n\n/** The global assetbase */\nlet assetBase: string | null = null;\n\n//deprecated variants\n/** @deprecated For WH5.4 and up use 'dtapStage' */\nlet dtapstage: DTAPStage = dtapStage;\n/** @deprecated For WH5.4 and up compare 'dtapStage' for production or acceptance */\nlet islive: boolean = isLive;\n\nlet hooks: EnvHooks | undefined;\nlet hookFactory: (() => EnvHooks) | undefined;\nlet gotHooks = false;\n\nexport function initEnv(setDtapStage: DTAPStage, setBackendBase: string) {\n  dtapStage = setDtapStage;\n  isLive = dtapStage === \"production\" || dtapStage === \"acceptance\";\n  backendBase = setBackendBase;\n\n  dtapstage = dtapStage;\n  islive = isLive;\n}\n\nexport function setEnvHooksFactory(newHookFactory: () => EnvHooks) {\n  if (gotHooks)\n    throw new Error(`The call to setEnvHooksFactory was too late - hooks have already been retrieved once`);\n  hookFactory = newHookFactory;\n}\n\nexport function getEnvHooks() {\n  gotHooks = true;\n  return hookFactory?.();\n}\n\nfunction ensureHooks(): EnvHooks {\n  return hooks ??= getEnvHooks?.() ?? {\n    currentAssetBase: (newAssetBase) => {\n      if (newAssetBase !== undefined)\n        assetBase = newAssetBase;\n      return assetBase;\n    }\n  };\n}\n\n/** Get the base url for assets. This may point towards eg. a CDN\n * @returns The base url for assets, ending with a '/'. null if not set\n */\nexport function getAssetBase(): string | null {\n  return ensureHooks().currentAssetBase();\n}\n\n/** Get the base url for a module's public assets (those located in the module's `public` folder)\n */\nexport function getModulePublicAssetBase(module: string) {\n  return `${getAssetBase() || \"/\"}.wh/mod/${encodeURIComponent(module)}/public/`;\n}\n\n/** Set the base url for assets */\nexport function setAssetBase(base: string | null): void {\n  if (base && !base.endsWith(\"/\"))\n    throw new Error(`Asset base must end with a '/'`);\n\n  ensureHooks().currentAssetBase(base);\n}\n\nexport { dtapStage, isLive, backendBase, localDebugFlags };\nexport { dtapstage, islive }; //deprecated variants\n","\n//Note that @webhare/env does not invoke this API itself. In WebHare @webhare/frontend/src/init uses this to initialize\nexport function getBrowserDebugFlags(varname: string): string[] {\n  const flags = [];\n  const urldebugvar = new URL(location.href).searchParams.get(varname);\n  if (urldebugvar)\n    flags.push(...urldebugvar.split(','));\n\n  //not importing getCookie to solve some import ordering issues\n  if (typeof document !== \"undefined\") { //'document' is undefined in a worker but assetpacks compiled for a ServiceWorker will also load us\n    const debugcookie = document.cookie.match(`(?:^|;)\\\\s*${varname}=([^;]*)`); //TODO escape varname\n    if (debugcookie) {\n      const debugcookievalue = decodeURIComponent(debugcookie[1]);\n      if (debugcookievalue)\n        flags.push(... (debugcookievalue.split('.').filter(flag => !flag.startsWith('sig='))));\n    }\n  }\n\n  if (typeof sessionStorage !== \"undefined\") {\n    const sessionDebug = sessionStorage.getItem(varname);\n    if (sessionDebug)\n      flags.push(...sessionDebug.split(','));\n  }\n\n  return flags;\n}\n","/** Rect describing an elements position */\nexport type Rect = {\n  top: number;\n  bottom: number;\n  left: number;\n  right: number;\n  width: number;\n  height: number;\n};\n\n/** Elements you can set a value on and would have to trigger change and/or input events */\nexport type FormControlElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n\n/** Types that support querySelector(All) */\ntype QuerySelectorAble = ParentNode | ShadowRoot;\n\nexport function qS<E extends Element = HTMLElement>(startnode: QuerySelectorAble, selector: string): E | null;\nexport function qS<E extends Element = HTMLElement>(selector: string): E | null;\n\n/** Match the first element using a CSS selector\n * @param node_or_selector - The starting node or selector\n * @param selector - The selector to match if the starting node was specified\n * @returns The first matching element or null\n */\nexport function qS<E extends Element>(node_or_selector: QuerySelectorAble | string, selector?: string): E | null {\n  if (typeof node_or_selector === 'string')\n    return document.querySelector<E>(node_or_selector);\n  else if (selector)\n    return node_or_selector.querySelector<E>(selector);\n  return null;\n}\n\n\nexport function qR<E extends Element = HTMLElement>(startnode: QuerySelectorAble, selector: string): E;\nexport function qR<E extends Element = HTMLElement>(selector: string): E;\n\n/** Match a specific element using a CSS selector, requiring it to exist and be unique\n * @param node_or_selector - The starting node or selector\n * @param selector - The selector to match if the starting node was specified\n * @returns The requested element. Throw it the selector doesn't match exactly one element\n */\nexport function qR<E extends Element>(node_or_selector: QuerySelectorAble | string, selector?: string): E {\n  const matches = qSA<E>(node_or_selector as QuerySelectorAble, selector as string);\n  if (matches.length === 1)\n    return matches[0];\n\n  if (typeof node_or_selector !== 'string') {\n    console.error(`${matches.length} elements match selector \\`${selector}\\` with startingpoint`, node_or_selector, matches);\n    throw new Error(`${matches.length} elements match selector \\`${selector}\\` given startingpoint '${node_or_selector.nodeName}'`);\n  } else {\n    console.error(`${matches.length} elements match selector \\`${node_or_selector}\\` in the document`, matches);\n    throw new Error(`${matches.length} elements match selector \\`${node_or_selector}\\` in the document`);\n  }\n}\n\nexport function qSA<E extends Element = HTMLElement>(startnode: QuerySelectorAble, selector: string): E[];\nexport function qSA<E extends Element = HTMLElement>(selector: string): E[];\n\n/** Find multiple elements using a CSS selector\n * @param node_or_selector - The starting node or selector\n * @param selector - The selector to match if the starting node was specified\n * @returns The requested elements.\n */\nexport function qSA<E extends Element>(node_or_selector: QuerySelectorAble | string, selector?: string): E[] {\n  if (typeof node_or_selector === 'string')\n    return Array.from(document.querySelectorAll(node_or_selector));\n  else if (selector)\n    return Array.from(node_or_selector.querySelectorAll(selector));\n\n  return [];\n}\n\n/** Return whether the passed element is a FormControlElement */\nexport function isFormControl(field: Element): field is FormControlElement {\n  return isHTMLElement(field) && [\"INPUT\", \"SELECT\", \"TEXTAREA\"].includes(field.tagName);\n}\n\n/** Return whether the passed element is an editable text field */\nexport function isEditControl(field: Element): field is HTMLElement {\n  return isHTMLElement(field) && ([\"INPUT\", \"TEXTAREA\"].includes(field.tagName) || field.isContentEditable);\n}\n\n/** Test whether node is an Element, even if it's in a different iframe */\nexport function isElement(node: unknown): node is Element {\n  //TODO What is actually going on if defaultView is missing?\n  if (!node || typeof node !== \"object\")\n    return false;\n\n  /* Getting the proto doesn't always work:\n  const proto = (node as Element).ownerDocument.defaultView?.Element;\n  (because our iframes derive off about? not sure) so until someone finds the real answer, we'll do a heuristic\n  */\n\n  /** Analyzing node.constructor.name doesn't work because custom elements don't necessarily have their constructor's name ending in Element\n  return Boolean(\"ownerDocument\" in node && node.constructor.name.match(/Element$/));\n  */\n\n  return Boolean(\"ownerDocument\" in node && (node as Element).nodeType === 1);\n\n}\n\n/** Test whether node is a HTMLElement, even if it's in a different iframe */\nexport function isHTMLElement(node: unknown): node is HTMLElement {\n  return isElement(node) && \"accessKey\" in node;\n}\n\n/**\n * get the relative bound difference between two elements, and return a writable copy\n *\n * @param node - The node for which you need coordinates\n * @param relativeto - Optional reference point. If not set, you just get a 'normal' coordinate object\n */\nexport function getRelativeBounds(node: Element, relativeto?: Element): Rect {\n  if (!relativeto)\n    relativeto = node.ownerDocument.documentElement;\n\n  const nodecoords = node.getBoundingClientRect();\n  const relcoords = relativeto.getBoundingClientRect();\n  return {\n    top: nodecoords.top - relcoords.top,\n    left: nodecoords.left - relcoords.left,\n    right: nodecoords.right - relcoords.left,\n    bottom: nodecoords.bottom - relcoords.top,\n    width: nodecoords.width,\n    height: nodecoords.height\n  };\n}\n\nexport type ParsedLanguageTag = {\n  /** The full tag, eg en-US */\n  tag: string;\n  /** The language code, eg 'en' */\n  language: string;\n  region?: string;\n  /** The script, eg 'Hant' */\n  script?: string;\n};\n\n/** Parse a BCP47 language tag */\nexport function parseLanguageTag(languageTag: string): ParsedLanguageTag {\n  /* https://datatracker.ietf.org/doc/html/rfc5646#section-2.1\n     langtag       = language\n                 [\"-\" script]\n                 [\"-\" region]\n                 *(\"-\" variant)\n                 *(\"-\" extension)\n                 [\"-\" privateuse]\n     BUT: we're limiting ourselves to language, script and region for now\n\n     language      = 2*3ALPHA           ; shortest ISO 639 code\n                    [\"-\" extlang]       ; sometimes followed by\n                                          extended language subtags\n\n                                           extlang       = 3ALPHA              ; selected ISO 639 codes\n                 *2(\"-\" 3ALPHA)      ; permanently reserved\n\n      script        = 4ALPHA              ; ISO 15924 code\n\n      region        = 2ALPHA              ; ISO 3166-1 code\n                    / 3DIGIT              ; UN M.49 code\n\n     Note that we're not yet fully implementing the spec, just the parts we expect to encounter in practice\n  */\n  const match = languageTag.match(/^([a-z]{2,}(-[a-z]{3})?)(-[A-Za-z]{4,})?(-[A-Z]{2}|-\\d{3})?$/);\n  if (!match)\n    throw new Error(`Invalid language tag: ${languageTag}`);\n\n  return {\n    tag: languageTag,\n    language: match[1],\n    ...(match[3] ? { script: match[3].substring(1) } : {}),\n    ...(match[4] ? { region: match[4].substring(1) } : {})\n  };\n}\n\n/** Get the effective language for an element (or the document)\n * @param node - The element for which to get the effective language. If not specified, the documentElement and finally the browser is used\n * @returns The language code, eg. \"nl\" or \"en-GB\"\n */\nexport function getLang(node?: Element): ParsedLanguageTag {\n  if (!node && typeof document !== \"undefined\")\n    node = document.documentElement;\n  const tag = (node?.closest('[lang]')?.getAttribute(\"lang\") || navigator.language || \"en\");\n  return parseLanguageTag(tag);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any -- Cannot specify this without using any */\n\nexport interface EmplaceHandler<ValueType> {\n  insert?: () => ValueType;\n  update?: (current: ValueType) => ValueType;\n}\n\nfunction binarySearchImpl<A, K>(compareFn: (element: A, key: K) => number, contents: A[], searchfor: K, upper_bound: boolean): { present: boolean; index: number } {\n  let first = 0;\n  let len = contents.length;\n  let present = false;\n\n  const cmpbound = upper_bound ? 1 : 0;\n  let unsorted_cmp = 0; // if this is non-0 and cmp is this value, we have an unsorted list\n  while (len > 0) {\n    const half = Math.floor(len / 2);\n    const middle = first + half;\n    const cmp = compareFn(contents[middle], searchfor);\n    if (cmp === 0) {\n      present = true;\n      unsorted_cmp = upper_bound ? -1 : 1;\n    } else if (cmp === unsorted_cmp)\n      throw new Error(`The provided array was not properly sorted!`);\n\n    if (cmp < cmpbound) {\n      first = middle + 1;\n      len -= half;\n      --len;\n    } else {\n      len = half;\n    }\n  }\n  return { present, index: first };\n}\n\n//emplace is based on https://github.com/tc39/proposal-upsert (a Map.prototype.emplace)\n/** Place a value into a Map\n * @param map - The map to place the value into\n * @param key - The key to add/replace\n * @param handler - Callbacks for inserting or updating the value\n * @returns The value that was placed into the map.\n * @throws If the key is not found and no insert handler is provided\n */\nexport function emplace<T extends Map<any, any> | WeakMap<any, any>>(\n  map: T,\n  key: T extends Map<infer K, any> ? K : T extends WeakMap<infer K, any> ? K : never,\n  handler?: T extends Map<any, infer V> ? EmplaceHandler<V> : T extends WeakMap<any, infer V> ? EmplaceHandler<V> : never):\n  T extends Map<any, infer V> ? V : T extends WeakMap<any, infer V> ? V : never {\n  let current = map.get(key);\n  if (current !== undefined) {\n    if (handler?.update) {\n      current = handler.update(current);\n      map.set(key, current);\n    }\n    return current;\n  }\n\n  if (!handler?.insert)\n    throw new Error(\"Key not found and no insert handler provided\");\n\n  const setvalue = handler.insert();\n  map.set(key, setvalue);\n  return setvalue;\n}\n\n// the `| keyof X` is needed to be able to use a `keyof X` type as key parameter in DistributedPick or DistributedOmit in generics\nexport type DistributedKeys<X extends object> = (X extends object ? keyof X : never) | keyof X;\n\n/** Applies Pick to all types in a union. Allows all keys that are present in any object in the union. Warning: You might not be\n    able to use all keys of the union if TypeScript has narrowed the union to a specific type. Eg:\n```typescript\ntype A = { x: number; t: \"a\"; a: number } | { x: number; t: \"b\"; b: number };\nconst a: A = { t: \"a\", a: 1 };\nconst b = pick(a, [\"t\", \"a\", \"b\"]); // No overload matches this call. <snip> Type '\"b\"' is not assignable to type '\"a\" | \"t\" | \"d\"'.\n```\n    @typeParam T - Type of the supplied object\n    @typeParam K - Type of the property keys to return\n    @returns Type with only the specified keys (distributed over the union if present)\n*/\nexport type DistributedPick<X extends object, Y extends DistributedKeys<X>> = X extends object ? Pick<X, keyof X & Y> : never;\n\n/** Applies Omit to all types in a union. Allows all keys that are not present in any object in the union. Warning: You might not be\n    able to use all keys of the union if TypeScript has narrowed the union to a specific type. Eg:\n```typescript\ntype A = { x: number; t: \"a\"; a: number } | { x: number; t: \"b\"; b: number };\nconst a: A = { t: \"a\", a: 1 };\nconst b = omit(a, [\"b\"]); // No overload matches this call. <snip> Type '\"b\"' is not assignable to type '\"a\" | \"t\" | \"d\"'.\n```\n    @typeParam T - Type of the supplied object\n    @typeParam K - Type of the property keys to leave out\n    @returns Type with only the specified keys left out (distributed over the union if present)\n*/\nexport type DistributedOmit<X extends object, Y extends DistributedKeys<X>> = X extends object ? Omit<X, keyof X & Y> : never;\n\n/** Returns an object with a selection of properties\n    @typeParam T - Type of the supplied object\n    @typeParam K - Type of the property keys to return\n    @param obj - Object to pick properties out of\n    @param keys - Names of the properties to pick\n    @returns Resulting object\n*/\nexport function pick<T extends object, K extends string & NoInfer<DistributedKeys<T>>>(obj: T, keys: readonly K[]): DistributedPick<T, K>;\n\n/** Returns an array with a selection of properties\n    @typeParam T - Type of the supplied array\n    @typeParam K - Type of the property keys to return\n    @param arr - Array to pick properties out of\n    @param keys - Names of the properties to pick\n    @returns Resulting array\n*/\nexport function pick<T extends object, K extends string & NoInfer<DistributedKeys<T>>>(arr: T[], keys: readonly K[]): Array<DistributedPick<T, K>>;\n\nexport function pick<T extends object, K extends string & NoInfer<DistributedKeys<T>>>(value: T | T[], keys: readonly K[]): DistributedPick<T, K> | Array<DistributedPick<T, K>> {\n  if (Array.isArray(value))\n    return value.map((elt: T) => pick(elt, keys));\n  const ret = {} as T;\n  keys.forEach((key: K) => {\n    if (key in value)\n      ret[key] = value[key];\n  });\n  return ret as object as DistributedPick<T, K>;\n}\n\n/** Returns an object with a selection of properties left out\n    @typeParam T - Type of the supplied object\n    @typeParam K - Type of the property keys to leave out\n    @param obj - Object to leave properties out of\n    @param keys - Names of the properties to remove\n    @returns Resulting object\n*/\nexport function omit<T extends object, K extends string & NoInfer<DistributedKeys<T>>>(obj: T, keys: readonly K[]): DistributedOmit<T, K>;\n\n/** Returns an array with a selection of properties left out\n    @typeParam T - Type of the supplied array\n    @typeParam K - Type of the property keys to leave out\n    @param arr - Array to leave properties out of\n    @param keys - Names of the properties to leave out\n    @returns Resulting array\n*/\nexport function omit<T extends object, K extends string & NoInfer<DistributedKeys<T>>>(arr: T[], keys: readonly K[]): Array<DistributedOmit<T, K>>;\n\nexport function omit<T extends object, K extends string & NoInfer<DistributedKeys<T>>>(value: T | T[], keys: readonly K[]): DistributedOmit<T, K> | Array<DistributedOmit<T, K>> {\n  if (Array.isArray(value))\n    return value.map((elt: T) => omit(elt, keys));\n  const ret = {} as T;\n  for (const [key, val] of Object.entries(value)) {\n    if (!keys.includes(key as K))\n      ret[key as K] = val;\n  }\n  return ret as object as DistributedOmit<T, K>;\n}\n\n/** Shuffle an array in-place\n * @param array - Array to shuffle\n * @returns The shuffled array\n*/\nexport function shuffle<T>(array: T[]): T[] {\n  for (let i = array.length - 1; i > 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [array[i], array[j]] = [array[j], array[i]];\n  }\n  return array;\n}\n\n/** Returns (and TypeScript-asserts) that the specified function is truthy. Handy for adjusting the type of an array when\n * filtering out falsy values\n * @example\n * const myarray: Array&lt;number | null&gt; = [0, null];\n * const filtered: number[] = myarray.filter(isTruthy);\n **/\nexport function isTruthy<T>(a: T): a is (T & {}) {\n  return Boolean(a);\n}\n\n/** Append to array, without overflowing the stack (eg V8 overflows at more than 32K entries)\n * @param array - Array to append to\n * @param values - Values to append\n*/\nexport function appendToArray<T>(array: T[], values: ReadonlyArray<NoInfer<T>>): void {\n  if (values.length < 1000)\n    array.push(...values); //push should be safe enough\n  else for (const value of values) //performance wise this appears just as fast as tricks with pushing blocks of slices\n    array.push(value);\n\n  //not returning the original array to make it clear we're not creating a new one\n}\n\ntype TypedEntriesInternal<T extends object, K extends keyof T> = K extends keyof T ? [K, T[K]] : never;\n\n/** Returns a union of [ key, value ] types for an object */\nexport type TypedEntries<T extends object> = T extends object ? TypedEntriesInternal<T, keyof T & string> : never;\n\n/** Returns an array of key/values of the enumerable own properties of an object, with exact types. Use when\n * no extra properties are expected on the object. Exists because Object.entries returns always string as key type.\n * @param obj - Object that contains the properties and methods\n */\nexport function typedEntries<T extends object>(obj: T): Array<TypedEntries<T>> {\n  return Object.entries(obj) as Array<TypedEntries<T>>;\n}\n\n/** Returns an array of keys of the enumerable own properties of an object, with exact types. Use when\n * no extra properties are expected on the object. Exists because Object.keys returns always string as key type.\n * @param obj - Object that contains the properties and methods\n */\nexport function typedKeys<T extends object>(obj: T): Array<keyof T & string> {\n  return Object.keys(obj) as Array<keyof T & string>;\n}\n\n/** Given a union of [key, value] types, returns the object constructed from those pairs. Exists because\n *  Object.fromEntries does not take the type of the keys and values into account.\n * @typeParam T - Union of [key, value] pairs\n */\nexport type TypedFromEntries<T extends [string, unknown]> = { [C in T as C[0]]: C[1] };\n\n/** Returns an object from an iterable of [key, value] pairs, with exact types. Exists because Object.fromEntries\n * doesn't take the type of the keys and values into account.\n * @param entries - Iterable of [key, value] pairs\n * @returns An object with the same keys and values as the input\n */\nexport function typedFromEntries<T extends [string, unknown]>(entries: Iterable<T>): TypedFromEntries<T> {\n  return Object.fromEntries(entries) as TypedFromEntries<T>;\n}\n\n\nexport class SortedMultiSet<V> {\n  private contents: V[] = [];\n  private compareFn;\n\n  constructor(compareFn: (lhs: V, rhs: V) => number, contents?: V[]) {\n    this.compareFn = compareFn;\n    if (contents)\n      this.addMultiple(contents);\n  }\n\n  get size() {\n    return this.contents.length;\n  }\n\n  at(index: number): V | undefined {\n    return this.contents.at(index);\n  }\n\n  add(value: V): number {\n    const pos = this.upperBound(value);\n    this.contents.splice(pos, 0, value);\n    return pos;\n  }\n\n  addMultiple(values: V[]): void {\n    for (const value of values) {\n      this.add(value);\n    }\n  }\n\n  delete(key: V): void {\n    const [start, limit] = this.range(key);\n    this.contents.splice(start, limit - start);\n  }\n\n  clear() {\n    this.contents.splice(0, this.contents.length);\n  }\n\n  lowerBound(key: Readonly<V>): { present: boolean; index: number } {\n    return binarySearchImpl(this.compareFn, this.contents, key, false);\n  }\n\n  upperBound(key: Readonly<V>): number {\n    return binarySearchImpl(this.compareFn, this.contents, key, true).index;\n  }\n\n  range(key: Readonly<V>): [number, number] {\n    return [this.lowerBound(key).index, this.upperBound(key)];\n  }\n\n  slice(start: number, limit: number): V[] {\n    return this.contents.slice(start, limit);\n  }\n\n  *#sliceIterator(start: number, limit: number): Generator<V, void> {\n    for (let idx = start; idx < limit; ++idx)\n      yield this.contents[idx];\n  }\n\n  sliceRange(key: Readonly<V>): V[] {\n    const [start, limit] = this.range(key);\n    return this.slice(start, limit);\n  }\n\n  rangeIterator(key: Readonly<V>): Iterable<V> {\n    const [start, limit] = this.range(key);\n    return this.#sliceIterator(start, limit);\n  }\n}\n\nexport class SortedMultiMap<K, V> {\n  private compareFn;\n  private contents: Array<[K, V]> = [];\n\n  constructor(compareFn: (lhs: K, rhs: K) => number, contents?: Array<[K, V]>) {\n    this.compareFn = (element: [K, V], key: K) => compareFn(element[0], key);\n    if (contents)\n      this.addMultiple(contents);\n  }\n\n  get size() {\n    return this.contents.length;\n  }\n\n  at(index: number): [K, V] | undefined {\n    return this.contents.at(index);\n  }\n\n  add(key: K, value: V): number {\n    const pos = this.upperBound(key);\n    this.contents.splice(pos, 0, [key, value]);\n    return pos;\n  }\n\n  addMultiple(values: Array<[K, V]>) {\n    for (const [key, value] of values) {\n      this.add(key, value);\n    }\n  }\n\n  delete(key: K): void {\n    const [start, limit] = this.range(key);\n    this.contents.splice(start, limit - start);\n  }\n\n  clear() {\n    this.contents.splice(0, this.contents.length);\n  }\n\n  lowerBound(key: Readonly<K>): { present: boolean; index: number } {\n    return binarySearchImpl(this.compareFn, this.contents, key, false);\n  }\n\n  upperBound(key: Readonly<K>): number {\n    return binarySearchImpl(this.compareFn, this.contents, key, true).index;\n  }\n\n  range(key: Readonly<K>): [number, number] {\n    return [this.lowerBound(key).index, this.upperBound(key)];\n  }\n\n  slice(start: number, limit: number): Array<[K, V]> {\n    return this.contents.slice(start, limit);\n  }\n\n  *#sliceIterator(start: number, limit: number): Generator<[K, V], void> {\n    for (let idx = start; idx < limit; ++idx)\n      yield this.contents[idx];\n  }\n\n  sliceRange(key: Readonly<K>): Array<[K, V]> {\n    const [start, limit] = this.range(key);\n    return this.slice(start, limit);\n  }\n\n  rangeIterator(key: Readonly<K>): Iterable<[K, V]> {\n    const [start, limit] = this.range(key);\n    return this.#sliceIterator(start, limit);\n  }\n}\n","const unlock = Symbol(\"unlock\");\n\n/** A mutex which is only visible in the current JavaScript VM\n\n    @example\n```ts\nconst mutex = new LocalMutex;\n\nusing lock = await mutex.lock();\nlock.release();\n\n// If you'll be relying on automatic release\nusing lock = await mutex.lock();\nvoid(lock);\n```\n\n*/\nexport class LocalMutex {\n  private locked = false;\n  private unlockList = new Array<() => void>;\n\n  /** Lock this mutex\n   * @returns Lock object. Use with `using` to ensure automatic unlock\n   */\n  async lock() {\n    if (this.locked) {\n      const defer = Promise.withResolvers<void>();\n      this.unlockList.push(() => defer.resolve());\n      await defer.promise;\n    } else {\n      this.locked = true;\n    }\n    return new LocalLock(this);\n  }\n\n  [unlock](): void {\n    if (this.unlockList.length > 0)\n      (this.unlockList.shift()!)(); //we're fair... unlock longest waiter\n    else\n      this.locked = false;\n  }\n}\n\n/** Instance of a LocalMutex lock */\nclass LocalLock implements Disposable {\n  private mutex: LocalMutex | null;\n\n  constructor(mutex: LocalMutex) {\n    this.mutex = mutex;\n  }\n  /** Explicitly release the lock\n   * @throws Error if the lock is already released\n  */\n  release() {\n    if (!this.mutex)\n      throw new Error(\"Lock already released\");\n\n    this.mutex[unlock]();\n    this.mutex = null;\n  }\n  [Symbol.dispose]() {\n    this.mutex?.[unlock]();\n  }\n}\n\nexport type { LocalLock };\n","/* frontend-config parses the wh-config object in the browser and mocks any missing data. @webhare/env does not actually expose this config, @webhare/frontend does\n   The frontend configuration is built in PageBuildRequest's 'frontendConfig' member */\n\nimport type { DTAPStage } from \"@webhare/env/src/concepts\";\nimport { debugFlags, initEnv } from \"@webhare/env/src/envbackend\";\nimport { getBrowserDebugFlags } from \"@webhare/env/src/init-browser\";\nimport { getLang } from \"@webhare/dompack/src/tree\";\nimport type { FrontendDataTypes } from \"@webhare/frontend\";\nimport { omit } from \"@webhare/std\";\n\n\n/** The format of the <script id=\"wh-config\"> object  */\nexport type WHConfigScriptData = {\n  //NOTE: existing frontend code doesn't expect site/obj to ever be null. not sure if 'object' provides the best interface or whether we need some sort of 'unknown but an existing object'\n  /** Page (targetobject) specific settings\n   *  @deprecated Use setFrontendData for type-safe settings\n  */\n  obj: { [key: string]: unknown };\n  /** Site specific settings\n   *  @deprecated Use setFrontendData for type-safe settings\n   */\n  site: { [key: string]: unknown };\n\n  /** Numeric server version number (eg 5.02.24 = 50224)\n   *  @deprecated Interpreting numbers (or version strings) is dangerous. Feature flags/testing or limiting your entire module to compatible versions is safer\n  */\n  server: number;\n  /** Root URL of this site */\n  siteRoot: string;\n} & {\n  ///Plugins may add keys at this level\n  [key in keyof FrontendDataTypes]?: FrontendDataTypes[key];\n};\n\nexport type WHConfigScriptData_FromServer = WHConfigScriptData & { dtapStage: DTAPStage };\n\n//names fields can still have when not yet republished\nexport interface WHConfigScriptData_OldPublishFields {\n  islive: boolean;\n  dtapstage: DTAPStage;\n  siteroot: string;\n}\n\n//fallback names with deprecation warnings\nexport interface WHConfigScriptData_LegacyFields {\n  /** @deprecated Use dtapStage in WH5.4+ */\n  islive: boolean;\n  /** @deprecated Use `dtapStage` from \"\\@webhare/env\"; in WH5.4+ */\n  dtapstage: DTAPStage;\n  /** @deprecated Use `getSiteRoot` from \"\\@webhare/frontend\"; in WH5.7+ */\n  siteroot: string;\n}\n\nlet config: WHConfigScriptData_FromServer | undefined;\nlet siteroot;\nlet dtapStage: DTAPStage = \"production\";\n\n//if document is undefined, we're serverside or in a worker\nconst whconfigel = typeof document !== \"undefined\" ? document.querySelector('script#wh-config') : null;\nif (whconfigel?.textContent) {\n  const parsedConfig: WHConfigScriptData_FromServer & WHConfigScriptData_OldPublishFields = JSON.parse(whconfigel.textContent);\n  config = omit(parsedConfig, [\"siteroot\", \"dtapstage\", \"islive\"]);\n\n  //Fallbacks for pages last published with WH5.3 *and* pages published from HareScript which still emit lowercase props\n  siteroot = parsedConfig.siteRoot ?? parsedConfig.siteroot!;\n  dtapStage = parsedConfig.dtapStage ?? parsedConfig.dtapstage;\n}\n\ninitEnv(dtapStage, '/');\n\nif (typeof location !== \"undefined\")\n  for (const flag of getBrowserDebugFlags('wh-debug'))\n    debugFlags[flag] = true;\n\n\n/** @deprecated frontendConfig has been deprecated. Switch to the getFrontendData system */\n// Make sure we have obj/site as some sort of object, to prevent crashes on naive 'if ($wh.config.obj.x)' tests'\nexport const frontendConfig: WHConfigScriptData & WHConfigScriptData_LegacyFields = {\n  server: 0,\n  ...config,\n  obj: config?.obj || {},\n  site: config?.site || {},\n  siteRoot: siteroot || \"\",\n  dtapstage: dtapStage,\n  islive: dtapStage === \"production\" || dtapStage === \"acceptance\",\n  siteroot: siteroot || \"\",\n};\n\nif (typeof document !== \"undefined\") {\n  //@ts-expect-error -- locale isn't supposed to exist - but some old code is still referring to it\n  frontendConfig.locale = getLang().tag;\n}\n\nif (dtapStage === \"development\") { //WH6.0: it's time to hard phase-out the old fields\n  for (const prop of [\"islive\", \"dtapstage\", \"siteroot\", \"locale\"] as const)\n    Object.defineProperty(frontendConfig, prop, {\n      get() { throw new Error(`frontendConfig.${prop} will be removed`); }\n    });\n}\n\n//NOTE: These APIs need to live in init.ts so eg gtm.ts can access us without triggering a CSS reset through frontend.ts. When frontend.ts stops auto-resetting we might move it back\n\nexport function getFrontendData<Type extends keyof FrontendDataTypes>(type: Type, options: { allowMissing: true }): FrontendDataTypes[Type] | null;\nexport function getFrontendData<Type extends keyof FrontendDataTypes>(type: Type, options?: { allowMissing: boolean }): FrontendDataTypes[Type];\n\n/** Get data exported by the response\n * @typeParam Type - The type of data to get\n * @param dataObject - The data object of data to get\n * @param allowMissing - If true, return null if the data object is missing. Otherwise throw an error\n * @example\n```\n  declare module \"@webhare/frontend\" {\n    interface FrontendDataTypes {\n      \"mymodule:type\": {\n        test: number;\n      };\n    }\n  }\n\n  const data = getFrontendData(\"mymodule:type\");\n```\n*/\nexport function getFrontendData<Type extends keyof FrontendDataTypes>(dataObject: Type, { allowMissing = false } = {}): FrontendDataTypes[Type] | null {\n  const retval = config?.[dataObject] as FrontendDataTypes[Type];\n  if (!retval)\n    if (allowMissing)\n      return null;\n    else\n      throw new Error(`Missing frontend data object: ${dataObject}`);\n\n  return retval;\n}\n\n/** Get the current site root\n *\n * @returns The site root URL (ending with a slash)\n*/\nexport function getSiteRoot() { //now an API to improve treeshaking\n  return frontendConfig.siteRoot;\n}\n","/**\n * Document-level key under which DigiConsent (>= 0.4.1) publishes its latest\n * frozen consent snapshot. A `Symbol.for` key is shared by every bundle in the\n * page, unlike module state inside a bundled copy of WebHare's consenthandler.\n */\nexport const DIGICONSENT_SNAPSHOT_KEY = \"digismederij.digiconsent.snapshot.v1\";\n\nconst decisions = new Set([\"unknown\", \"implicit\", \"explicit\"]);\n\nfunction legacyScopes(consent) {\n  // WW's accept/decline cookiewall uses the explicit tag \"all\" instead of\n  // granular tags. Keep that tag and include its analytics/marketing grants.\n  return consent?.includes(\"all\") ? [...new Set([...consent, \"analytics\", \"marketing\"])] : consent ?? [];\n}\n\nexport function mapWebHareConsent(settings) {\n  const scopes = legacyScopes(settings.consent);\n  return {\n    decision: settings.isdefault ? \"implicit\" : settings.consent ? \"explicit\" : \"unknown\",\n    scopes,\n    marketing: scopes.includes(\"marketing\"),\n  };\n}\n\n/** Maps a DigiConsent snapshot (envelope version 1) to the tracker's consent state. */\nexport function mapDigiConsentSnapshot(snapshot) {\n  if (!snapshot || typeof snapshot !== \"object\" || snapshot.version !== 1 ||\n      !decisions.has(snapshot.decision) || !snapshot.grants || typeof snapshot.grants !== \"object\")\n    return undefined;\n  const scopes = Object.keys(snapshot.grants).filter(scope => snapshot.grants[scope] === true);\n  return { decision: snapshot.decision, scopes, marketing: snapshot.grants.marketing === true };\n}\n\n/**\n * Maps WebHare's documented `<html data-wh-consent>` mirror (\"unknown\",\n * \"denied\" or space-separated tags). It cannot tell implicit defaults apart,\n * so it is only a fallback for sites without DigiConsent (e.g. legacy MSO\n * cookiewalls, which configure no default consent).\n */\nexport function mapDocumentConsent(value) {\n  if (value === \"unknown\")\n    return { decision: \"unknown\", scopes: [], marketing: false };\n  if (typeof value !== \"string\" || !value.trim())\n    return undefined;\n  if (value === \"denied\")\n    return { decision: \"explicit\", scopes: [], marketing: false };\n  const scopes = legacyScopes(value.split(/\\s+/).filter(Boolean));\n  return { decision: \"explicit\", scopes, marketing: scopes.includes(\"marketing\") };\n}\n\nexport function resolveInitialConsent({ sharedSnapshot, documentConsent }) {\n  return mapDigiConsentSnapshot(sharedSnapshot) ?? mapDocumentConsent(documentConsent);\n}\n\n/**\n * Connects a tracker to the page's consent state independent of script order:\n * it applies the state that was established before this bundle ran and then\n * follows WebHare's window-level `wh:consent-changed` event, which every\n * bundled consenthandler copy dispatches.\n */\nexport function connectSharedConsent({ target, readSharedSnapshot, readDocumentConsent, observeDocumentConsent, apply }) {\n  const initial = resolveInitialConsent({\n    sharedSnapshot: readSharedSnapshot(),\n    documentConsent: readDocumentConsent(),\n  });\n  const listener = event => {\n    if (event?.detail && typeof event.detail === \"object\")\n      apply({ ...mapWebHareConsent(event.detail), forgetIdentifiers: true });\n  };\n  target.addEventListener(\"wh:consent-changed\", listener);\n  // Native WebHare does not dispatch consent-changed for an unknown decision.\n  // Follow its DOM mirror as well, without wrapping or replacing whResetConsent.\n  const stopObserving = observeDocumentConsent?.(() => {\n    const documentConsent = readDocumentConsent();\n    const state = documentConsent === \"unknown\" ? mapDocumentConsent(documentConsent)\n      : resolveInitialConsent({ sharedSnapshot: readSharedSnapshot(), documentConsent });\n    if (state)\n      apply({ ...state, forgetIdentifiers: true });\n  });\n  if (initial)\n    apply({ ...initial, forgetIdentifiers: true });\n  return () => {\n    target.removeEventListener(\"wh:consent-changed\", listener);\n    stopObserving?.();\n  };\n}\n\n/**\n * Keeps collection on the page's own origin. The plugin renders the endpoint\n * beneath the site's canonical webroot; a page served on an alias host\n * (www vs. bare domain) would otherwise post cross-origin and be refused by\n * ingest. Only the path is kept, so subdirectory sites stay on their root.\n */\nexport function sameOriginEndpoint(endpoint, location) {\n  return new URL(new URL(endpoint, location.href).pathname, location.origin).href;\n}\n","const code = /^[a-z][a-z0-9_-]{0,63}$/;\nexport function normalizeBasicConfig(input) {\n  if (!input || typeof input !== 'object' || typeof input.enabled !== 'boolean'\n      || JSON.stringify(input).length > 4096\n      || !Array.isArray(input.pages) || !Array.isArray(input.conversions)\n      || input.pages.length > 100 || input.conversions.length > 100\n      || [...input.pages, ...input.conversions].some(value => typeof value !== 'string' || !code.test(value)))\n    throw new Error('Invalid basic measurement configuration');\n  return { enabled: input.enabled, pages: [...new Set(input.pages)], conversions: [...new Set(input.conversions)] };\n}\nexport function normalizeBasicEvent(input) {\n  if (!input || typeof input !== 'object' || Array.isArray(input)\n      || Object.keys(input).some(key => !['v', 'id', 'page', 'event'].includes(key))\n      || input.v !== 1 || typeof input.id !== 'string'\n      || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(input.id)\n      || typeof input.page !== 'string' || !code.test(input.page)\n      || typeof input.event !== 'string'\n      || !(input.event === 'page_view' || /^conversion:[a-z][a-z0-9_-]{0,63}$/.test(input.event)))\n    throw new Error('Invalid basic event');\n  return Object.freeze({ v: 1, id: input.id.toLowerCase(), page: input.page, event: input.event });\n}\nexport function authorizeBasicEvent(config, event) {\n  return config.enabled && config.pages.includes(event.page)\n    && (event.event === 'page_view' || config.conversions.includes(event.event.slice(11)));\n}\n","/** crypto.randomUUID only exists in secure contexts; plain-HTTP aliases and previews need a fallback. */\nexport function randomIdentifier(cryptoImpl = globalThis.crypto) {\n  if (typeof cryptoImpl?.randomUUID === \"function\")\n    return cryptoImpl.randomUUID();\n  const bytes = new Uint8Array(16);\n  cryptoImpl.getRandomValues(bytes);\n  bytes[6] = (bytes[6] & 0x0f) | 0x40;\n  bytes[8] = (bytes[8] & 0x3f) | 0x80;\n  const hex = Array.from(bytes, byte => byte.toString(16).padStart(2, \"0\")).join(\"\");\n  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","import { normalizeBasicEvent } from './basic-contract.mjs';\nimport { randomIdentifier } from './random-id.mjs';\n\n// Never use sendBeacon: it includes credentials. No referrer or cookies leave\n// this transport, and only the validated four-field event enters the body.\nexport function basicTransport(endpoint, payload) {\n  return fetch(endpoint, { method: 'POST', body: payload,\n    headers: { 'Content-Type': 'text/plain;charset=UTF-8' },\n    credentials: 'omit', referrerPolicy: 'no-referrer', mode: 'same-origin',\n    cache: 'no-store', keepalive: true }).catch(() => undefined);\n}\nexport function createBasicTracker(options, environment = {}) {\n  const transport = environment.basicTransport ?? basicTransport;\n  const randomId = environment.randomId ?? (() => randomIdentifier());\n  function send(event) {\n    const payload = normalizeBasicEvent({ v: 1, id: randomId(), page: options.page, event });\n    void transport(options.endpoint, JSON.stringify(payload));\n    return true;\n  }\n  return Object.freeze({\n    pageView: () => send('page_view'),\n    conversion: name => options.conversions.includes(name) ? send(`conversion:${name}`) : false,\n  });\n}\n","export const METRICS_EVENT_VERSION = 1;\n\nconst allowedFields = new Set([\n  \"v\",\n  \"id\",\n  \"tenant\",\n  \"event\",\n  \"session\",\n  \"visitor\",\n  \"visit\",\n  \"page\",\n  \"seq\",\n  \"path\",\n  \"consent\",\n  \"referrerHost\",\n  \"source\",\n  \"medium\",\n  \"campaign\",\n  \"value\",\n  \"currency\",\n]);\n\nconst identifierPattern = /^[A-Za-z0-9_-]{8,64}$/;\nconst tenantPattern = /^[a-z0-9][a-z0-9_-]{0,63}$/;\nconst eventPattern = /^[a-z][a-z0-9_.:-]{0,79}$/;\nconst scopePattern = /^[a-z][a-z0-9_.:-]{0,63}$/;\n\nexport class MetricsEventValidationError extends Error {\n  constructor(message) {\n    super(message);\n    this.name = \"MetricsEventValidationError\";\n  }\n}\n\nfunction expectRecord(input) {\n  if (!input || typeof input !== \"object\" || Array.isArray(input))\n    throw new MetricsEventValidationError(\"Event must be a JSON object\");\n\n  for (const key of Object.keys(input))\n    if (!allowedFields.has(key))\n      throw new MetricsEventValidationError(`Unknown event field '${key}'`);\n\n  return input;\n}\n\nfunction expectString(value, field, maxLength, pattern) {\n  if (typeof value !== \"string\" || !value || value.length > maxLength)\n    throw new MetricsEventValidationError(`${field} must be a non-empty string of at most ${maxLength} characters`);\n  if (pattern && !pattern.test(value))\n    throw new MetricsEventValidationError(`${field} has an invalid format`);\n  return value;\n}\n\nfunction optionalString(value, field, maxLength) {\n  return value === undefined ? undefined : expectString(value, field, maxLength);\n}\n\nfunction normalizePath(value) {\n  const path = expectString(value, \"path\", 1024);\n  if (!path.startsWith(\"/\"))\n    throw new MetricsEventValidationError(\"path must start with '/'\");\n\n  const query = path.indexOf(\"?\");\n  const fragment = path.indexOf(\"#\");\n  const end = Math.min(query < 0 ? path.length : query, fragment < 0 ? path.length : fragment, 512);\n  return path.substring(0, end) || \"/\";\n}\n\nexport function normalizeMetricsEvent(input) {\n  const value = expectRecord(input);\n  if (value.v !== METRICS_EVENT_VERSION)\n    throw new MetricsEventValidationError(`Unsupported event version '${value.v}'`);\n\n  if (!Number.isSafeInteger(value.seq) || value.seq < 1 || value.seq > 1_000_000)\n    throw new MetricsEventValidationError(\"seq must be a positive safe integer\");\n  const normalized = {\n    v: METRICS_EVENT_VERSION,\n    id: expectString(value.id, \"id\", 64, identifierPattern),\n    event: expectString(value.event, \"event\", 80, eventPattern),\n    session: expectString(value.session, \"session\", 64, identifierPattern),\n    page: expectString(value.page, \"page\", 64, identifierPattern),\n    seq: value.seq,\n    path: normalizePath(value.path),\n    consent: expectString(value.consent, \"consent\", 64, scopePattern),\n  };\n\n  if (value.visitor !== undefined || value.visit !== undefined) {\n    normalized.visitor = expectString(value.visitor, \"visitor\", 64, identifierPattern);\n    if (!Number.isSafeInteger(value.visit) || value.visit < 1 || value.visit > 1_000_000)\n      throw new MetricsEventValidationError(\"visit must be a positive safe integer\");\n    normalized.visit = value.visit;\n  }\n\n  if (value.tenant !== undefined)\n    normalized.tenant = expectString(value.tenant, \"tenant\", 64, tenantPattern);\n\n  const referrerHost = optionalString(value.referrerHost, \"referrerHost\", 255);\n  const source = optionalString(value.source, \"source\", 100);\n  const medium = optionalString(value.medium, \"medium\", 100);\n  const campaign = optionalString(value.campaign, \"campaign\", 160);\n  if (referrerHost !== undefined)\n    normalized.referrerHost = referrerHost.toLowerCase();\n  if (source !== undefined)\n    normalized.source = source;\n  if (medium !== undefined)\n    normalized.medium = medium;\n  if (campaign !== undefined)\n    normalized.campaign = campaign;\n\n  if (value.value !== undefined) {\n    if (typeof value.value !== \"number\" || !Number.isFinite(value.value))\n      throw new MetricsEventValidationError(\"value must be a finite number\");\n    normalized.value = value.value;\n  }\n  if (value.currency !== undefined)\n    normalized.currency = expectString(value.currency, \"currency\", 3, /^[A-Z]{3}$/);\n\n  return Object.freeze(normalized);\n}\n","import { createBasicTracker } from \"./basic-tracker.mjs\";\nimport { normalizeMetricsEvent } from \"./event-contract.mjs\";\nimport { randomIdentifier } from \"./random-id.mjs\";\n\nconst DEFAULT_ENDPOINT = \"/_i/e\";\nconst DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1000;\nconst DEFAULT_VISITOR_RETENTION = 30 * 24 * 60 * 60 * 1000;\nconst SESSION_STORAGE_KEY = \"__dm_s1\";\nconst VISITOR_STORAGE_KEY = \"__dm_v1\";\nconst identifierPattern = /^[A-Za-z0-9_-]{8,64}$/;\n\nfunction defaultTransport(endpoint, payload) {\n  if (navigator.sendBeacon?.(endpoint, payload))\n    return;\n\n  void fetch(endpoint, {\n    method: \"POST\",\n    body: payload,\n    headers: { \"Content-Type\": \"text/plain;charset=UTF-8\" },\n    credentials: \"same-origin\",\n    cache: \"no-store\",\n    keepalive: true,\n  }).catch(error => console.error(\"[digimetrics] Failed to send event\", error));\n}\n\nfunction defaultEnvironment() {\n  return {\n    now: () => Date.now(),\n    randomId: () => randomIdentifier(),\n    getLocation: () => window.location,\n    getReferrer: () => document.referrer,\n    getSessionStorage: () => {\n      try {\n        return window.sessionStorage;\n      } catch {\n        return null;\n      }\n    },\n    getLocalStorage: () => {\n      try {\n        return window.localStorage;\n      } catch {\n        return null;\n      }\n    },\n    transport: defaultTransport,\n  };\n}\n\nfunction readCampaign(search) {\n  const params = new URLSearchParams(search);\n  return {\n    source: params.get(\"utm_source\")?.substring(0, 100) || undefined,\n    medium: params.get(\"utm_medium\")?.substring(0, 100) || undefined,\n    campaign: params.get(\"utm_campaign\")?.substring(0, 160) || undefined,\n  };\n}\n\nfunction getReferrerHost(referrer, currentHost) {\n  if (!referrer)\n    return undefined;\n  try {\n    const hostname = new URL(referrer).hostname.toLowerCase();\n    return hostname && hostname !== currentHost.toLowerCase() ? hostname.substring(0, 255) : undefined;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction captureLanding(environment) {\n  const location = environment.getLocation();\n  const params = new URLSearchParams(location.search);\n  return Object.freeze({\n    path: location.pathname.substring(0, 1024) || \"/\",\n    referrerHost: getReferrerHost(environment.getReferrer(), location.hostname),\n    campaign: Object.freeze(readCampaign(location.search)),\n    hasGoogleClickId: params.has(\"gclid\") || params.has(\"gbraid\") || params.has(\"wbraid\"),\n  });\n}\n\nfunction resolveAttribution(landing, marketing) {\n  const campaign = { ...landing.campaign };\n\n  if (marketing && !campaign.source && landing.hasGoogleClickId) {\n    campaign.source = \"google\";\n    campaign.medium = \"cpc\";\n  }\n  if (!campaign.source && landing.referrerHost) {\n    campaign.source = landing.referrerHost;\n    campaign.medium = \"referral\";\n  }\n  return { referrerHost: landing.referrerHost, ...campaign };\n}\n\nfunction validStoredSession(value, now, timeout) {\n  return value &&\n    typeof value === \"object\" &&\n    identifierPattern.test(value.id) &&\n    Number.isFinite(value.lastSeen) &&\n    now - value.lastSeen >= 0 &&\n    now - value.lastSeen <= timeout &&\n    identifierPattern.test(value.visitor) &&\n    Number.isSafeInteger(value.visit) && value.visit >= 1 &&\n    value.attribution &&\n    typeof value.attribution === \"object\";\n}\n\nfunction validStoredVisitor(value, now) {\n  return value && typeof value === \"object\" && identifierPattern.test(value.id) &&\n    Number.isSafeInteger(value.visits) && value.visits >= 1 &&\n    Number.isFinite(value.expiresAt) && value.expiresAt > now;\n}\n\nexport function createMetricsTracker(options, overrides = {}) {\n  if (!options)\n    throw new Error(\"DigiMetrics options are required\");\n  if (options.consentScope !== undefined && !/^[a-z][a-z0-9_.:-]{0,63}$/.test(options.consentScope))\n    throw new Error(\"DigiMetrics consentScope has an invalid format\");\n  if (options.sessionTimeoutMs !== undefined && (!Number.isFinite(options.sessionTimeoutMs) || options.sessionTimeoutMs <= 0))\n    throw new Error(\"DigiMetrics sessionTimeoutMs must be a positive number\");\n  if (options.visitorRetentionMs !== undefined && (!Number.isFinite(options.visitorRetentionMs) || options.visitorRetentionMs <= 0))\n    throw new Error(\"DigiMetrics visitorRetentionMs must be a positive number\");\n\n  const environment = { ...defaultEnvironment(), ...overrides };\n  const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;\n  const consentScope = options.consentScope ?? \"analytics\";\n  const sessionTimeout = options.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT;\n  const visitorRetention = options.visitorRetentionMs ?? DEFAULT_VISITOR_RETENTION;\n  const pageId = environment.randomId();\n  // Capture attribution only when consent is granted; never replay prior navigation.\n  let initialLanding;\n  let enabled = false;\n  let marketing = false;\n  let sequence = 0;\n  let session;\n  const basic = options.basic ? createBasicTracker(options.basic, environment) : undefined;\n  if (basic && (options.autoPageView ?? true))\n    basic.pageView();\n\n  function loadVisitor() {\n    const now = environment.now();\n    const storage = environment.getLocalStorage();\n    if (storage) {\n      try {\n        const parsed = JSON.parse(storage.getItem(VISITOR_STORAGE_KEY) || \"null\");\n        if (validStoredVisitor(parsed, now))\n          return { id: parsed.id, visits: parsed.visits + 1, expiresAt: now + visitorRetention };\n      } catch {\n        // A corrupt or blocked visitor store starts a fresh pseudonymous visitor.\n      }\n    }\n    return { id: environment.randomId(), visits: 1, expiresAt: now + visitorRetention };\n  }\n\n  function persistVisitor(visitor) {\n    const storage = environment.getLocalStorage();\n    if (!storage)\n      return;\n    try {\n      storage.setItem(VISITOR_STORAGE_KEY, JSON.stringify(visitor));\n    } catch {\n      // Metrics keep working without cross-session recognition.\n    }\n  }\n\n  function loadSession() {\n    const now = environment.now();\n    const storage = environment.getSessionStorage();\n    if (storage) {\n      try {\n        const parsed = JSON.parse(storage.getItem(SESSION_STORAGE_KEY) || \"null\");\n        if (validStoredSession(parsed, now, sessionTimeout))\n          return { ...parsed, lastSeen: now };\n      } catch {\n        // A corrupt or blocked session store simply starts a new session.\n      }\n    }\n    const visitor = loadVisitor();\n    persistVisitor(visitor);\n    return {\n      id: environment.randomId(),\n      lastSeen: now,\n      attribution: resolveAttribution(initialLanding, marketing),\n      visitor: visitor.id,\n      visit: visitor.visits,\n    };\n  }\n\n  function persistSession() {\n    const storage = environment.getSessionStorage();\n    if (!storage || !session)\n      return;\n    try {\n      storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));\n    } catch {\n      // Collection still works in privacy modes without sessionStorage.\n    }\n  }\n\n  function send(event, extra = {}) {\n    if (!enabled)\n      return false;\n\n    session ??= loadSession();\n    session.lastSeen = environment.now();\n    persistSession();\n    const payload = normalizeMetricsEvent({\n      v: 1,\n      id: environment.randomId(),\n      event,\n      session: session.id,\n      visitor: session.visitor,\n      visit: session.visit,\n      page: pageId,\n      seq: ++sequence,\n      path: environment.getLocation().pathname,\n      consent: consentScope,\n      referrerHost: session.attribution.referrerHost,\n      source: session.attribution.source,\n      medium: session.attribution.medium,\n      campaign: session.attribution.campaign,\n      ...extra,\n    });\n    environment.transport(endpoint, JSON.stringify(payload));\n    return true;\n  }\n\n  function setConsent(state) {\n    const isExplicit = state?.decision === \"explicit\";\n    const granted = Array.isArray(state?.scopes) ? state.scopes.includes(consentScope) : Boolean(state?.[consentScope]);\n    const shouldEnable = isExplicit && granted;\n    marketing = isExplicit && Boolean(state?.marketing);\n    if (!shouldEnable) {\n      const wasEnabled = enabled || Boolean(session);\n      enabled = false;\n      session = undefined;\n      if (wasEnabled || state?.forgetIdentifiers === true)\n        for (const [getStorage, key] of [[environment.getSessionStorage, SESSION_STORAGE_KEY], [environment.getLocalStorage, VISITOR_STORAGE_KEY]]) {\n          // Cleanup only: never read or renew identifiers without consent, and\n          // do not remove storage owned by the host webdesign or other modules.\n          try { getStorage()?.removeItem(key); } catch { /* Storage may be blocked. */ }\n        }\n      return;\n    }\n    if (enabled)\n      return;\n\n    initialLanding = captureLanding(environment);\n    enabled = true;\n    session = loadSession();\n    persistSession();\n    if (options.autoPageView ?? true)\n      send(\"page_view\", { path: initialLanding.path });\n  }\n\n  return Object.freeze({\n    setConsent,\n    trackEvent: name => {\n      const basicSent = name === \"page_view\" ? basic?.pageView() ?? false : false;\n      return send(name) || basicSent;\n    },\n    trackConversion: (name, conversion = {}) => {\n      const basicSent = basic?.conversion(name) ?? false;\n      return send(`conversion:${name}`, conversion) || basicSent;\n    },\n    get enabled() {\n      return enabled;\n    },\n  });\n}\n","import { getFrontendData } from \"@webhare/frontend/src/init\";\n// Deliberately no import of @mod-publisher/js/analytics/consenthandler: a bundled\n// copy has its own (never set up) state and would miss consent established by\n// another bundle before this one ran. See connectSharedConsent.\nimport { connectSharedConsent, DIGICONSENT_SNAPSHOT_KEY, sameOriginEndpoint } from \"./bootstrap-core.mjs\";\nimport { createMetricsTracker, type MetricsTracker } from \"./tracker.mjs\";\n\ninterface DigiMetricsFrontendConfig {\n  endpoint: string;\n  consentscope: string;\n  autopageview: boolean;\n  basicpage?: string;\n  basicendpoint?: string;\n  basicconversions?: string[];\n}\n\ndeclare global {\n  interface Window {\n    digiMetrics?: MetricsTracker;\n  }\n}\n\nconst config = getFrontendData<DigiMetricsFrontendConfig>(\"digimetrics:config\", { allowMissing: true });\n\nif (config) {\n  const tracker = createMetricsTracker({\n    endpoint: sameOriginEndpoint(config.endpoint, window.location),\n    basic: config.basicpage && config.basicendpoint ? {\n      page: config.basicpage,\n      endpoint: sameOriginEndpoint(config.basicendpoint, window.location),\n      // Tokenize(\"\") yields [\"\"] when the attribute is absent.\n      conversions: (config.basicconversions ?? []).filter(Boolean),\n    } : undefined,\n    consentScope: config.consentscope,\n    autoPageView: config.autopageview,\n  });\n\n  window.digiMetrics = tracker;\n  connectSharedConsent({\n    target: window,\n    readSharedSnapshot: () => (window as unknown as Record<symbol, unknown>)[Symbol.for(DIGICONSENT_SNAPSHOT_KEY)],\n    readDocumentConsent: () => document.documentElement.dataset.whConsent,\n    observeDocumentConsent: listener => {\n      const observer = new MutationObserver(listener);\n      observer.observe(document.documentElement, { attributes: true, attributeFilter: [\"data-wh-consent\"] });\n      return () => observer.disconnect();\n    },\n    apply: state => tracker.setConsent(state),\n  });\n  window.dispatchEvent(new CustomEvent(\"digi:metrics-ready\", { detail: tracker }));\n}\n","import \"@webhare/frontend/src/init\";import \"/opt/whdata/installedmodules/digimetrics.20261022T141426.573Z/js/bootstrap.ts\";const aps = globalThis.whAssetPacks ||= {}; aps[\"digimetrics:frontend\"]=\"2026-10-22T14:14:30.999Z\";"],"mappings":"AAoCA,IAAMA,GAA2B,IAAI,MAM/BC,GAA+B,CAAC,EAAGC,GAA8B,CAAC,EAGpEC,GAYJ,IAAMC,EAAN,KAAiE,CACvD,eAA8B,CACpC,MAAO,CAAC,GAAGC,KAAwB,GAAK,CAAC,EAAGC,GAAiBC,EAAgB,CAC/E,CAEA,IAAIC,EAAoBC,EAAW,CACjC,QAAWC,KAAU,KAAK,cAAc,EACtC,GAAID,KAAKC,GAAU,OAAOA,EAAOD,CAAC,EAAM,IACtC,OAAOC,EAAOD,CAAC,CAErB,CACA,IAAID,EAAoBC,EAAoB,CAC1C,OAAO,KAAK,IAAID,EAAQC,CAAC,IAAM,MACjC,CACA,QAAQD,EAA4C,CAClD,IAAMG,EAAO,IAAI,MACjB,QAAWD,KAAU,KAAK,cAAc,EACtC,QAAWE,KAAO,QAAQ,QAAQF,CAAM,EAClC,OAAOE,GAAQ,UAAYF,EAAOE,CAAG,IAAM,QAAa,CAACD,EAAK,SAASC,CAAG,GAC5ED,EAAK,KAAKC,CAAG,EACnB,OAAOD,CACT,CACA,IAAIH,EAAoBC,EAAWI,EAAwC,CACzE,IAAMC,EAAW,KAAK,cAAc,EAAE,CAAC,EACvC,OAAI,OAAOD,GAAa,UACtBC,EAASL,CAAC,EAAII,EAEd,OAAOC,EAASL,CAAC,EAEnBM,EAAqB,EACd,EACT,CACA,eAAeP,EAAoBC,EAAoB,CACrD,IAAMK,EAAW,KAAK,cAAc,EAAE,CAAC,EACvC,cAAOA,EAASL,CAAC,EAEjBM,EAAqB,EACd,EACT,CACA,yBAAyBP,EAAoBC,EAA2C,CACtF,IAAMO,EAAQ,KAAK,IAAIR,EAAQC,CAAC,EAChC,OAAOO,IAAU,OAAY,CAAE,WAAY,GAAM,MAAAA,EAAO,aAAc,EAAK,EAAI,MACjF,CACF,EAEaC,EAAa,IAAI,MAAkB,CAC9C,CAAC,OAAO,IAAI,4BAA4B,CAAC,EAAGC,EAC9C,EAAG,IAAId,CAAwB,EAE/B,SAASc,IAAuB,CAC9B,MAAO,eAAe,CAAC,GAAG,OAAO,KAAKD,CAAU,CAAC,EAAE,OAAOL,GAAOK,EAAWL,CAAG,CAAC,EAAE,KAAK,IAAI,CAAC,GAC9F,CAEA,SAASG,GAAuB,CAC9B,QAAWI,IAAM,CAAC,GAAGC,EAAwB,EAC3C,GAAI,CACFD,EAAG,CACL,OAASE,EAAG,CACV,QAAQ,MAAM,0CAA2CF,GAAI,KAAME,CAAC,CAEtE,CAEJ,CA0CA,IAAIC,EAAuB,aAGvBC,EAAkBD,IAAc,cAAgBA,IAAc,aAG9DE,GAAc,GAOlB,IAAIC,GAAuBC,EAEvBC,GAAkBC,EAMf,SAASC,EAAQC,EAAyBC,EAAwB,CACvEC,EAAYF,EACZG,EAASD,IAAc,cAAgBA,IAAc,aACrDE,GAAcH,EAEdI,GAAYH,EACZI,GAASH,CACX,CC3LO,SAASI,EAAqBC,EAA2B,CAC9D,IAAMC,EAAQ,CAAC,EACTC,EAAc,IAAI,IAAI,SAAS,IAAI,EAAE,aAAa,IAAIF,CAAO,EAKnE,GAJIE,GACFD,EAAM,KAAK,GAAGC,EAAY,MAAM,GAAG,CAAC,EAGlC,OAAO,SAAa,IAAa,CACnC,IAAMC,EAAc,SAAS,OAAO,MAAM,cAAcH,CAAO,UAAU,EACzE,GAAIG,EAAa,CACf,IAAMC,EAAmB,mBAAmBD,EAAY,CAAC,CAAC,EACtDC,GACFH,EAAM,KAAK,GAAKG,EAAiB,MAAM,GAAG,EAAE,OAAOC,GAAQ,CAACA,EAAK,WAAW,MAAM,CAAC,CAAE,CACzF,CACF,CAEA,GAAI,OAAO,eAAmB,IAAa,CACzC,IAAMC,EAAe,eAAe,QAAQN,CAAO,EAC/CM,GACFL,EAAM,KAAK,GAAGK,EAAa,MAAM,GAAG,CAAC,CACzC,CAEA,OAAOL,CACT,CCkHO,SAASM,GAAiBC,EAAwC,CAwBvE,IAAMC,EAAQD,EAAY,MAAM,8DAA8D,EAC9F,GAAI,CAACC,EACH,MAAM,IAAI,MAAM,yBAAyBD,CAAW,EAAE,EAExD,MAAO,CACL,IAAKA,EACL,SAAUC,EAAM,CAAC,EACjB,GAAIA,EAAM,CAAC,EAAI,CAAE,OAAQA,EAAM,CAAC,EAAE,UAAU,CAAC,CAAE,EAAI,CAAC,EACpD,GAAIA,EAAM,CAAC,EAAI,CAAE,OAAQA,EAAM,CAAC,EAAE,UAAU,CAAC,CAAE,EAAI,CAAC,CACtD,CACF,CAMO,SAASC,EAAQC,EAAmC,CACrD,CAACA,GAAQ,OAAO,SAAa,MAC/BA,EAAO,SAAS,iBAClB,IAAMC,EAAOD,GAAM,QAAQ,QAAQ,GAAG,aAAa,MAAM,GAAK,UAAU,UAAY,KACpF,OAAOJ,GAAiBK,CAAG,CAC7B,CC3CO,SAASC,EAAuEC,EAAgBC,EAA0E,CAC/K,GAAI,MAAM,QAAQD,CAAK,EACrB,OAAOA,EAAM,IAAKE,GAAWH,EAAKG,EAAKD,CAAI,CAAC,EAC9C,IAAME,EAAM,CAAC,EACb,OAAW,CAACC,EAAKC,CAAG,IAAK,OAAO,QAAQL,CAAK,EACtCC,EAAK,SAASG,CAAQ,IACzBD,EAAIC,CAAQ,EAAIC,GAEpB,OAAOF,CACT,CCtJA,IAAMG,EAAS,OAAO,QAAQ,EAiBjBC,EAAN,KAAiB,CACd,OAAS,GACT,WAAa,IAAI,MAKzB,MAAM,MAAO,CACX,GAAI,KAAK,OAAQ,CACf,IAAMC,EAAQ,QAAQ,cAAoB,EAC1C,KAAK,WAAW,KAAK,IAAMA,EAAM,QAAQ,CAAC,EAC1C,MAAMA,EAAM,OACd,MACE,KAAK,OAAS,GAEhB,OAAO,IAAIC,EAAU,IAAI,CAC3B,CAEA,CAACH,CAAM,GAAU,CACX,KAAK,WAAW,OAAS,EAC1B,KAAK,WAAW,MAAM,EAAI,EAE3B,KAAK,OAAS,EAClB,CACF,EAGMG,EAAN,KAAsC,CAC5B,MAER,YAAYC,EAAmB,CAC7B,KAAK,MAAQA,CACf,CAIA,SAAU,CACR,GAAI,CAAC,KAAK,MACR,MAAM,IAAI,MAAM,uBAAuB,EAEzC,KAAK,MAAMJ,CAAM,EAAE,EACnB,KAAK,MAAQ,IACf,CACA,CAAC,OAAO,OAAO,GAAI,CACjB,KAAK,QAAQA,CAAM,EAAE,CACvB,CACF,ECVA,IAAIK,EACAC,EACAC,EAAuB,aAGrBC,EAAa,OAAO,SAAa,IAAc,SAAS,cAAc,kBAAkB,EAAI,KAClG,GAAIA,GAAY,YAAa,CAC3B,IAAMC,EAAoF,KAAK,MAAMD,EAAW,WAAW,EAC3HH,EAASK,EAAKD,EAAc,CAAC,WAAY,YAAa,QAAQ,CAAC,EAG/DH,EAAWG,EAAa,UAAYA,EAAa,SACjDF,EAAYE,EAAa,WAAaA,EAAa,SACrD,CAEAE,EAAQJ,EAAW,GAAG,EAEtB,GAAI,OAAO,SAAa,IACtB,QAAWK,KAAQC,EAAqB,UAAU,EAChDC,EAAWF,CAAI,EAAI,GAKhB,IAAMG,EAAuE,CAClF,OAAQ,EACR,GAAGV,EACH,IAAKA,GAAQ,KAAO,CAAC,EACrB,KAAMA,GAAQ,MAAQ,CAAC,EACvB,SAAUC,GAAY,GACtB,UAAWC,EACX,OAAQA,IAAc,cAAgBA,IAAc,aACpD,SAAUD,GAAY,EACxB,EAEI,OAAO,SAAa,MAEtBS,EAAe,OAASC,EAAQ,EAAE,KAGpC,GAAIT,IAAc,cAChB,QAAWU,IAAQ,CAAC,SAAU,YAAa,WAAY,QAAQ,EAC7D,OAAO,eAAeF,EAAgBE,EAAM,CAC1C,KAAM,CAAE,MAAM,IAAI,MAAM,kBAAkBA,CAAI,kBAAkB,CAAG,CACrE,CAAC,EAyBE,SAASC,EAAsDC,EAAkB,CAAE,aAAAC,EAAe,EAAM,EAAI,CAAC,EAAmC,CACrJ,IAAMC,EAAShB,IAASc,CAAU,EAClC,GAAI,CAACE,EACH,IAAID,EACF,OAAO,KAEP,MAAM,IAAI,MAAM,iCAAiCD,CAAU,EAAE,EAEjE,OAAOE,CACT,CC9HO,IAAMC,GAA2B,uCAElCC,GAAY,IAAI,IAAI,CAAC,UAAW,WAAY,UAAU,CAAC,EAE7D,SAASC,GAAaC,EAAS,CAG7B,OAAOA,GAAS,SAAS,KAAK,EAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAGA,EAAS,YAAa,WAAW,CAAC,CAAC,EAAIA,GAAW,CAAC,CACvG,CAEO,SAASC,GAAkBC,EAAU,CAC1C,IAAMC,EAASJ,GAAaG,EAAS,OAAO,EAC5C,MAAO,CACL,SAAUA,EAAS,UAAY,WAAaA,EAAS,QAAU,WAAa,UAC5E,OAAAC,EACA,UAAWA,EAAO,SAAS,WAAW,CACxC,CACF,CAGO,SAASC,GAAuBC,EAAU,CAC/C,GAAI,CAACA,GAAY,OAAOA,GAAa,UAAYA,EAAS,UAAY,GAClE,CAACP,GAAU,IAAIO,EAAS,QAAQ,GAAK,CAACA,EAAS,QAAU,OAAOA,EAAS,QAAW,SACtF,OACF,IAAMF,EAAS,OAAO,KAAKE,EAAS,MAAM,EAAE,OAAOC,GAASD,EAAS,OAAOC,CAAK,IAAM,EAAI,EAC3F,MAAO,CAAE,SAAUD,EAAS,SAAU,OAAAF,EAAQ,UAAWE,EAAS,OAAO,YAAc,EAAK,CAC9F,CAQO,SAASE,GAAmBC,EAAO,CACxC,GAAIA,IAAU,UACZ,MAAO,CAAE,SAAU,UAAW,OAAQ,CAAC,EAAG,UAAW,EAAM,EAC7D,GAAI,OAAOA,GAAU,UAAY,CAACA,EAAM,KAAK,EAC3C,OACF,GAAIA,IAAU,SACZ,MAAO,CAAE,SAAU,WAAY,OAAQ,CAAC,EAAG,UAAW,EAAM,EAC9D,IAAML,EAASJ,GAAaS,EAAM,MAAM,KAAK,EAAE,OAAO,OAAO,CAAC,EAC9D,MAAO,CAAE,SAAU,WAAY,OAAAL,EAAQ,UAAWA,EAAO,SAAS,WAAW,CAAE,CACjF,CAEO,SAASM,GAAsB,CAAE,eAAAC,EAAgB,gBAAAC,CAAgB,EAAG,CACzE,OAAOP,GAAuBM,CAAc,GAAKH,GAAmBI,CAAe,CACrF,CAQO,SAASC,GAAqB,CAAE,OAAAC,EAAQ,mBAAAC,EAAoB,oBAAAC,EAAqB,uBAAAC,EAAwB,MAAAC,CAAM,EAAG,CACvH,IAAMC,EAAUT,GAAsB,CACpC,eAAgBK,EAAmB,EACnC,gBAAiBC,EAAoB,CACvC,CAAC,EACKI,EAAWC,GAAS,CACpBA,GAAO,QAAU,OAAOA,EAAM,QAAW,UAC3CH,EAAM,CAAE,GAAGhB,GAAkBmB,EAAM,MAAM,EAAG,kBAAmB,EAAK,CAAC,CACzE,EACAP,EAAO,iBAAiB,qBAAsBM,CAAQ,EAGtD,IAAME,EAAgBL,IAAyB,IAAM,CACnD,IAAML,EAAkBI,EAAoB,EACtCO,EAAQX,IAAoB,UAAYJ,GAAmBI,CAAe,EAC5EF,GAAsB,CAAE,eAAgBK,EAAmB,EAAG,gBAAAH,CAAgB,CAAC,EAC/EW,GACFL,EAAM,CAAE,GAAGK,EAAO,kBAAmB,EAAK,CAAC,CAC/C,CAAC,EACD,OAAIJ,GACFD,EAAM,CAAE,GAAGC,EAAS,kBAAmB,EAAK,CAAC,EACxC,IAAM,CACXL,EAAO,oBAAoB,qBAAsBM,CAAQ,EACzDE,IAAgB,CAClB,CACF,CAQO,SAASE,EAAmBC,EAAUC,EAAU,CACrD,OAAO,IAAI,IAAI,IAAI,IAAID,EAAUC,EAAS,IAAI,EAAE,SAAUA,EAAS,MAAM,EAAE,IAC7E,CC/FA,IAAMC,GAAO,0BAUN,SAASC,GAAoBC,EAAO,CACzC,GAAI,CAACA,GAAS,OAAOA,GAAU,UAAY,MAAM,QAAQA,CAAK,GACvD,OAAO,KAAKA,CAAK,EAAE,KAAKC,GAAO,CAAC,CAAC,IAAK,KAAM,OAAQ,OAAO,EAAE,SAASA,CAAG,CAAC,GAC1ED,EAAM,IAAM,GAAK,OAAOA,EAAM,IAAO,UACrC,CAAC,yEAAyE,KAAKA,EAAM,EAAE,GACvF,OAAOA,EAAM,MAAS,UAAY,CAACE,GAAK,KAAKF,EAAM,IAAI,GACvD,OAAOA,EAAM,OAAU,UACvB,EAAEA,EAAM,QAAU,aAAe,qCAAqC,KAAKA,EAAM,KAAK,GAC3F,MAAM,IAAI,MAAM,qBAAqB,EACvC,OAAO,OAAO,OAAO,CAAE,EAAG,EAAG,GAAIA,EAAM,GAAG,YAAY,EAAG,KAAMA,EAAM,KAAM,MAAOA,EAAM,KAAM,CAAC,CACjG,CCnBO,SAASG,EAAiBC,EAAa,WAAW,OAAQ,CAC/D,GAAI,OAAOA,GAAY,YAAe,WACpC,OAAOA,EAAW,WAAW,EAC/B,IAAMC,EAAQ,IAAI,WAAW,EAAE,EAC/BD,EAAW,gBAAgBC,CAAK,EAChCA,EAAM,CAAC,EAAKA,EAAM,CAAC,EAAI,GAAQ,GAC/BA,EAAM,CAAC,EAAKA,EAAM,CAAC,EAAI,GAAQ,IAC/B,IAAMC,EAAM,MAAM,KAAKD,EAAOE,GAAQA,EAAK,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,EACjF,MAAO,GAAGD,EAAI,MAAM,EAAG,CAAC,CAAC,IAAIA,EAAI,MAAM,EAAG,EAAE,CAAC,IAAIA,EAAI,MAAM,GAAI,EAAE,CAAC,IAAIA,EAAI,MAAM,GAAI,EAAE,CAAC,IAAIA,EAAI,MAAM,EAAE,CAAC,EAC1G,CCLO,SAASE,GAAeC,EAAUC,EAAS,CAChD,OAAO,MAAMD,EAAU,CAAE,OAAQ,OAAQ,KAAMC,EAC7C,QAAS,CAAE,eAAgB,0BAA2B,EACtD,YAAa,OAAQ,eAAgB,cAAe,KAAM,cAC1D,MAAO,WAAY,UAAW,EAAK,CAAC,EAAE,MAAM,IAAG,EAAY,CAC/D,CACO,SAASC,GAAmBC,EAASC,EAAc,CAAC,EAAG,CAC5D,IAAMC,EAAYD,EAAY,gBAAkBL,GAC1CO,EAAWF,EAAY,WAAa,IAAMG,EAAiB,GACjE,SAASC,EAAKC,EAAO,CACnB,IAAMR,EAAUS,GAAoB,CAAE,EAAG,EAAG,GAAIJ,EAAS,EAAG,KAAMH,EAAQ,KAAM,MAAAM,CAAM,CAAC,EACvF,OAAKJ,EAAUF,EAAQ,SAAU,KAAK,UAAUF,CAAO,CAAC,EACjD,EACT,CACA,OAAO,OAAO,OAAO,CACnB,SAAU,IAAMO,EAAK,WAAW,EAChC,WAAYG,GAAQR,EAAQ,YAAY,SAASQ,CAAI,EAAIH,EAAK,cAAcG,CAAI,EAAE,EAAI,EACxF,CAAC,CACH,CCrBA,IAAMC,GAAgB,IAAI,IAAI,CAC5B,IACA,KACA,SACA,QACA,UACA,UACA,QACA,OACA,MACA,OACA,UACA,eACA,SACA,SACA,WACA,QACA,UACF,CAAC,EAEKC,EAAoB,wBACpBC,GAAgB,6BAChBC,GAAe,4BACfC,GAAe,4BAERC,EAAN,cAA0C,KAAM,CACrD,YAAYC,EAAS,CACnB,MAAMA,CAAO,EACb,KAAK,KAAO,6BACd,CACF,EAEA,SAASC,GAAaC,EAAO,CAC3B,GAAI,CAACA,GAAS,OAAOA,GAAU,UAAY,MAAM,QAAQA,CAAK,EAC5D,MAAM,IAAIH,EAA4B,6BAA6B,EAErE,QAAWI,KAAO,OAAO,KAAKD,CAAK,EACjC,GAAI,CAACR,GAAc,IAAIS,CAAG,EACxB,MAAM,IAAIJ,EAA4B,wBAAwBI,CAAG,GAAG,EAExE,OAAOD,CACT,CAEA,SAASE,EAAaC,EAAOC,EAAOC,EAAWC,EAAS,CACtD,GAAI,OAAOH,GAAU,UAAY,CAACA,GAASA,EAAM,OAASE,EACxD,MAAM,IAAIR,EAA4B,GAAGO,CAAK,0CAA0CC,CAAS,aAAa,EAChH,GAAIC,GAAW,CAACA,EAAQ,KAAKH,CAAK,EAChC,MAAM,IAAIN,EAA4B,GAAGO,CAAK,wBAAwB,EACxE,OAAOD,CACT,CAEA,SAASI,EAAeJ,EAAOC,EAAOC,EAAW,CAC/C,OAAOF,IAAU,OAAY,OAAYD,EAAaC,EAAOC,EAAOC,CAAS,CAC/E,CAEA,SAASG,GAAcL,EAAO,CAC5B,IAAMM,EAAOP,EAAaC,EAAO,OAAQ,IAAI,EAC7C,GAAI,CAACM,EAAK,WAAW,GAAG,EACtB,MAAM,IAAIZ,EAA4B,0BAA0B,EAElE,IAAMa,EAAQD,EAAK,QAAQ,GAAG,EACxBE,EAAWF,EAAK,QAAQ,GAAG,EAC3BG,EAAM,KAAK,IAAIF,EAAQ,EAAID,EAAK,OAASC,EAAOC,EAAW,EAAIF,EAAK,OAASE,EAAU,GAAG,EAChG,OAAOF,EAAK,UAAU,EAAGG,CAAG,GAAK,GACnC,CAEO,SAASC,GAAsBb,EAAO,CAC3C,IAAMG,EAAQJ,GAAaC,CAAK,EAChC,GAAIG,EAAM,IAAM,EACd,MAAM,IAAIN,EAA4B,8BAA8BM,EAAM,CAAC,GAAG,EAEhF,GAAI,CAAC,OAAO,cAAcA,EAAM,GAAG,GAAKA,EAAM,IAAM,GAAKA,EAAM,IAAM,IACnE,MAAM,IAAIN,EAA4B,qCAAqC,EAC7E,IAAMiB,EAAa,CACjB,EAAG,EACH,GAAIZ,EAAaC,EAAM,GAAI,KAAM,GAAIV,CAAiB,EACtD,MAAOS,EAAaC,EAAM,MAAO,QAAS,GAAIR,EAAY,EAC1D,QAASO,EAAaC,EAAM,QAAS,UAAW,GAAIV,CAAiB,EACrE,KAAMS,EAAaC,EAAM,KAAM,OAAQ,GAAIV,CAAiB,EAC5D,IAAKU,EAAM,IACX,KAAMK,GAAcL,EAAM,IAAI,EAC9B,QAASD,EAAaC,EAAM,QAAS,UAAW,GAAIP,EAAY,CAClE,EAEA,GAAIO,EAAM,UAAY,QAAaA,EAAM,QAAU,OAAW,CAE5D,GADAW,EAAW,QAAUZ,EAAaC,EAAM,QAAS,UAAW,GAAIV,CAAiB,EAC7E,CAAC,OAAO,cAAcU,EAAM,KAAK,GAAKA,EAAM,MAAQ,GAAKA,EAAM,MAAQ,IACzE,MAAM,IAAIN,EAA4B,uCAAuC,EAC/EiB,EAAW,MAAQX,EAAM,KAC3B,CAEIA,EAAM,SAAW,SACnBW,EAAW,OAASZ,EAAaC,EAAM,OAAQ,SAAU,GAAIT,EAAa,GAE5E,IAAMqB,EAAeR,EAAeJ,EAAM,aAAc,eAAgB,GAAG,EACrEa,EAAST,EAAeJ,EAAM,OAAQ,SAAU,GAAG,EACnDc,EAASV,EAAeJ,EAAM,OAAQ,SAAU,GAAG,EACnDe,EAAWX,EAAeJ,EAAM,SAAU,WAAY,GAAG,EAU/D,GATIY,IAAiB,SACnBD,EAAW,aAAeC,EAAa,YAAY,GACjDC,IAAW,SACbF,EAAW,OAASE,GAClBC,IAAW,SACbH,EAAW,OAASG,GAClBC,IAAa,SACfJ,EAAW,SAAWI,GAEpBf,EAAM,QAAU,OAAW,CAC7B,GAAI,OAAOA,EAAM,OAAU,UAAY,CAAC,OAAO,SAASA,EAAM,KAAK,EACjE,MAAM,IAAIN,EAA4B,+BAA+B,EACvEiB,EAAW,MAAQX,EAAM,KAC3B,CACA,OAAIA,EAAM,WAAa,SACrBW,EAAW,SAAWZ,EAAaC,EAAM,SAAU,WAAY,EAAG,YAAY,GAEzE,OAAO,OAAOW,CAAU,CACjC,CClHA,IAAMK,GAAmB,QACnBC,GAA0B,KAAU,IACpCC,GAA4B,IAAU,GAAK,GAAK,IAChDC,EAAsB,UACtBC,EAAsB,UACtBC,EAAoB,wBAE1B,SAASC,GAAiBC,EAAUC,EAAS,CACvC,UAAU,aAAaD,EAAUC,CAAO,GAGvC,MAAMD,EAAU,CACnB,OAAQ,OACR,KAAMC,EACN,QAAS,CAAE,eAAgB,0BAA2B,EACtD,YAAa,cACb,MAAO,WACP,UAAW,EACb,CAAC,EAAE,MAAMC,GAAS,QAAQ,MAAM,qCAAsCA,CAAK,CAAC,CAC9E,CAEA,SAASC,IAAqB,CAC5B,MAAO,CACL,IAAK,IAAM,KAAK,IAAI,EACpB,SAAU,IAAMC,EAAiB,EACjC,YAAa,IAAM,OAAO,SAC1B,YAAa,IAAM,SAAS,SAC5B,kBAAmB,IAAM,CACvB,GAAI,CACF,OAAO,OAAO,cAChB,MAAQ,CACN,OAAO,IACT,CACF,EACA,gBAAiB,IAAM,CACrB,GAAI,CACF,OAAO,OAAO,YAChB,MAAQ,CACN,OAAO,IACT,CACF,EACA,UAAWL,EACb,CACF,CAEA,SAASM,GAAaC,EAAQ,CAC5B,IAAMC,EAAS,IAAI,gBAAgBD,CAAM,EACzC,MAAO,CACL,OAAQC,EAAO,IAAI,YAAY,GAAG,UAAU,EAAG,GAAG,GAAK,OACvD,OAAQA,EAAO,IAAI,YAAY,GAAG,UAAU,EAAG,GAAG,GAAK,OACvD,SAAUA,EAAO,IAAI,cAAc,GAAG,UAAU,EAAG,GAAG,GAAK,MAC7D,CACF,CAEA,SAASC,GAAgBC,EAAUC,EAAa,CAC9C,GAAKD,EAEL,GAAI,CACF,IAAME,EAAW,IAAI,IAAIF,CAAQ,EAAE,SAAS,YAAY,EACxD,OAAOE,GAAYA,IAAaD,EAAY,YAAY,EAAIC,EAAS,UAAU,EAAG,GAAG,EAAI,MAC3F,MAAQ,CACN,MACF,CACF,CAEA,SAASC,GAAeC,EAAa,CACnC,IAAMC,EAAWD,EAAY,YAAY,EACnCN,EAAS,IAAI,gBAAgBO,EAAS,MAAM,EAClD,OAAO,OAAO,OAAO,CACnB,KAAMA,EAAS,SAAS,UAAU,EAAG,IAAI,GAAK,IAC9C,aAAcN,GAAgBK,EAAY,YAAY,EAAGC,EAAS,QAAQ,EAC1E,SAAU,OAAO,OAAOT,GAAaS,EAAS,MAAM,CAAC,EACrD,iBAAkBP,EAAO,IAAI,OAAO,GAAKA,EAAO,IAAI,QAAQ,GAAKA,EAAO,IAAI,QAAQ,CACtF,CAAC,CACH,CAEA,SAASQ,GAAmBC,EAASC,EAAW,CAC9C,IAAMC,EAAW,CAAE,GAAGF,EAAQ,QAAS,EAEvC,OAAIC,GAAa,CAACC,EAAS,QAAUF,EAAQ,mBAC3CE,EAAS,OAAS,SAClBA,EAAS,OAAS,OAEhB,CAACA,EAAS,QAAUF,EAAQ,eAC9BE,EAAS,OAASF,EAAQ,aAC1BE,EAAS,OAAS,YAEb,CAAE,aAAcF,EAAQ,aAAc,GAAGE,CAAS,CAC3D,CAEA,SAASC,GAAmBC,EAAOC,EAAKC,EAAS,CAC/C,OAAOF,GACL,OAAOA,GAAU,UACjBtB,EAAkB,KAAKsB,EAAM,EAAE,GAC/B,OAAO,SAASA,EAAM,QAAQ,GAC9BC,EAAMD,EAAM,UAAY,GACxBC,EAAMD,EAAM,UAAYE,GACxBxB,EAAkB,KAAKsB,EAAM,OAAO,GACpC,OAAO,cAAcA,EAAM,KAAK,GAAKA,EAAM,OAAS,GACpDA,EAAM,aACN,OAAOA,EAAM,aAAgB,QACjC,CAEA,SAASG,GAAmBH,EAAOC,EAAK,CACtC,OAAOD,GAAS,OAAOA,GAAU,UAAYtB,EAAkB,KAAKsB,EAAM,EAAE,GAC1E,OAAO,cAAcA,EAAM,MAAM,GAAKA,EAAM,QAAU,GACtD,OAAO,SAASA,EAAM,SAAS,GAAKA,EAAM,UAAYC,CAC1D,CAEO,SAASG,GAAqBC,EAASC,EAAY,CAAC,EAAG,CAC5D,GAAI,CAACD,EACH,MAAM,IAAI,MAAM,kCAAkC,EACpD,GAAIA,EAAQ,eAAiB,QAAa,CAAC,4BAA4B,KAAKA,EAAQ,YAAY,EAC9F,MAAM,IAAI,MAAM,gDAAgD,EAClE,GAAIA,EAAQ,mBAAqB,SAAc,CAAC,OAAO,SAASA,EAAQ,gBAAgB,GAAKA,EAAQ,kBAAoB,GACvH,MAAM,IAAI,MAAM,wDAAwD,EAC1E,GAAIA,EAAQ,qBAAuB,SAAc,CAAC,OAAO,SAASA,EAAQ,kBAAkB,GAAKA,EAAQ,oBAAsB,GAC7H,MAAM,IAAI,MAAM,0DAA0D,EAE5E,IAAMZ,EAAc,CAAE,GAAGV,GAAmB,EAAG,GAAGuB,CAAU,EACtD1B,EAAWyB,EAAQ,UAAYhC,GAC/BkC,EAAeF,EAAQ,cAAgB,YACvCG,EAAiBH,EAAQ,kBAAoB/B,GAC7CmC,EAAmBJ,EAAQ,oBAAsB9B,GACjDmC,EAASjB,EAAY,SAAS,EAEhCkB,EACAC,EAAU,GACVf,EAAY,GACZgB,GAAW,EACXC,EACEC,EAAQV,EAAQ,MAAQW,GAAmBX,EAAQ,MAAOZ,CAAW,EAAI,OAC3EsB,IAAUV,EAAQ,cAAgB,KACpCU,EAAM,SAAS,EAEjB,SAASE,IAAc,CACrB,IAAMhB,EAAMR,EAAY,IAAI,EACtByB,EAAUzB,EAAY,gBAAgB,EAC5C,GAAIyB,EACF,GAAI,CACF,IAAMC,EAAS,KAAK,MAAMD,EAAQ,QAAQzC,CAAmB,GAAK,MAAM,EACxE,GAAI0B,GAAmBgB,EAAQlB,CAAG,EAChC,MAAO,CAAE,GAAIkB,EAAO,GAAI,OAAQA,EAAO,OAAS,EAAG,UAAWlB,EAAMQ,CAAiB,CACzF,MAAQ,CAER,CAEF,MAAO,CAAE,GAAIhB,EAAY,SAAS,EAAG,OAAQ,EAAG,UAAWQ,EAAMQ,CAAiB,CACpF,CAEA,SAASW,GAAeC,EAAS,CAC/B,IAAMH,EAAUzB,EAAY,gBAAgB,EAC5C,GAAKyB,EAEL,GAAI,CACFA,EAAQ,QAAQzC,EAAqB,KAAK,UAAU4C,CAAO,CAAC,CAC9D,MAAQ,CAER,CACF,CAEA,SAASC,GAAc,CACrB,IAAMrB,EAAMR,EAAY,IAAI,EACtByB,EAAUzB,EAAY,kBAAkB,EAC9C,GAAIyB,EACF,GAAI,CACF,IAAMC,EAAS,KAAK,MAAMD,EAAQ,QAAQ1C,CAAmB,GAAK,MAAM,EACxE,GAAIuB,GAAmBoB,EAAQlB,EAAKO,CAAc,EAChD,MAAO,CAAE,GAAGW,EAAQ,SAAUlB,CAAI,CACtC,MAAQ,CAER,CAEF,IAAMoB,EAAUJ,GAAY,EAC5B,OAAAG,GAAeC,CAAO,EACf,CACL,GAAI5B,EAAY,SAAS,EACzB,SAAUQ,EACV,YAAaN,GAAmBgB,EAAgBd,CAAS,EACzD,QAASwB,EAAQ,GACjB,MAAOA,EAAQ,MACjB,CACF,CAEA,SAASE,GAAiB,CACxB,IAAML,EAAUzB,EAAY,kBAAkB,EAC9C,GAAI,GAACyB,GAAW,CAACJ,GAEjB,GAAI,CACFI,EAAQ,QAAQ1C,EAAqB,KAAK,UAAUsC,CAAO,CAAC,CAC9D,MAAQ,CAER,CACF,CAEA,SAASU,EAAKC,EAAOC,EAAQ,CAAC,EAAG,CAC/B,GAAI,CAACd,EACH,MAAO,GAETE,IAAYQ,EAAY,EACxBR,EAAQ,SAAWrB,EAAY,IAAI,EACnC8B,EAAe,EACf,IAAM1C,EAAU8C,GAAsB,CACpC,EAAG,EACH,GAAIlC,EAAY,SAAS,EACzB,MAAAgC,EACA,QAASX,EAAQ,GACjB,QAASA,EAAQ,QACjB,MAAOA,EAAQ,MACf,KAAMJ,EACN,IAAK,EAAEG,GACP,KAAMpB,EAAY,YAAY,EAAE,SAChC,QAASc,EACT,aAAcO,EAAQ,YAAY,aAClC,OAAQA,EAAQ,YAAY,OAC5B,OAAQA,EAAQ,YAAY,OAC5B,SAAUA,EAAQ,YAAY,SAC9B,GAAGY,CACL,CAAC,EACD,OAAAjC,EAAY,UAAUb,EAAU,KAAK,UAAUC,CAAO,CAAC,EAChD,EACT,CAEA,SAAS+C,GAAWC,EAAO,CACzB,IAAMC,EAAaD,GAAO,WAAa,WACjCE,EAAU,MAAM,QAAQF,GAAO,MAAM,EAAIA,EAAM,OAAO,SAAStB,CAAY,EAAI,EAAQsB,IAAQtB,CAAY,EAC3GyB,EAAeF,GAAcC,EAEnC,GADAlC,EAAYiC,GAAc,EAAQD,GAAO,UACrC,CAACG,EAAc,CACjB,IAAMC,GAAarB,GAAW,EAAQE,EAGtC,GAFAF,EAAU,GACVE,EAAU,OACNmB,IAAcJ,GAAO,oBAAsB,GAC7C,OAAW,CAACK,GAAYC,EAAG,GAAK,CAAC,CAAC1C,EAAY,kBAAmBjB,CAAmB,EAAG,CAACiB,EAAY,gBAAiBhB,CAAmB,CAAC,EAGvI,GAAI,CAAEyD,GAAW,GAAG,WAAWC,EAAG,CAAG,MAAQ,CAAgC,CAEjF,MACF,CACIvB,IAGJD,EAAiBnB,GAAeC,CAAW,EAC3CmB,EAAU,GACVE,EAAUQ,EAAY,EACtBC,EAAe,GACXlB,EAAQ,cAAgB,KAC1BmB,EAAK,YAAa,CAAE,KAAMb,EAAe,IAAK,CAAC,EACnD,CAEA,OAAO,OAAO,OAAO,CACnB,WAAAiB,GACA,WAAYQ,GAAQ,CAClB,IAAMC,EAAYD,IAAS,YAAcrB,GAAO,SAAS,GAAK,GAAQ,GACtE,OAAOS,EAAKY,CAAI,GAAKC,CACvB,EACA,gBAAiB,CAACD,EAAME,EAAa,CAAC,IAAM,CAC1C,IAAMD,EAAYtB,GAAO,WAAWqB,CAAI,GAAK,GAC7C,OAAOZ,EAAK,cAAcY,CAAI,GAAIE,CAAU,GAAKD,CACnD,EACA,IAAI,SAAU,CACZ,OAAOzB,CACT,CACF,CAAC,CACH,CCvPA,IAAM2B,EAASC,EAA2C,qBAAsB,CAAE,aAAc,EAAK,CAAC,EAEtG,GAAID,EAAQ,CACV,IAAME,EAAUC,GAAqB,CACnC,SAAUC,EAAmBJ,EAAO,SAAU,OAAO,QAAQ,EAC7D,MAAOA,EAAO,WAAaA,EAAO,cAAgB,CAChD,KAAMA,EAAO,UACb,SAAUI,EAAmBJ,EAAO,cAAe,OAAO,QAAQ,EAElE,aAAcA,EAAO,kBAAoB,CAAC,GAAG,OAAO,OAAO,CAC7D,EAAI,OACJ,aAAcA,EAAO,aACrB,aAAcA,EAAO,YACvB,CAAC,EAED,OAAO,YAAcE,EACrBG,GAAqB,CACnB,OAAQ,OACR,mBAAoB,IAAO,OAA8C,OAAO,IAAIC,EAAwB,CAAC,EAC7G,oBAAqB,IAAM,SAAS,gBAAgB,QAAQ,UAC5D,uBAAwBC,GAAY,CAClC,IAAMC,EAAW,IAAI,iBAAiBD,CAAQ,EAC9C,OAAAC,EAAS,QAAQ,SAAS,gBAAiB,CAAE,WAAY,GAAM,gBAAiB,CAAC,iBAAiB,CAAE,CAAC,EAC9F,IAAMA,EAAS,WAAW,CACnC,EACA,MAAOC,GAASP,EAAQ,WAAWO,CAAK,CAC1C,CAAC,EACD,OAAO,cAAc,IAAI,YAAY,qBAAsB,CAAE,OAAQP,CAAQ,CAAC,CAAC,CACjF,CClD2H,IAAMQ,GAAM,WAAW,eAAiB,CAAC,EAAGA,GAAI,sBAAsB,EAAE","names":["settingschangedcallbacks","globalDebugFlags","localDebugFlags","debugFlagsOverridesCB","DebugFlagsProxyHandler","debugFlagsOverridesCB","localDebugFlags","globalDebugFlags","target","p","record","keys","key","newValue","toModify","runSettingsCallbacks","value","debugFlags","formatForConsoleLogs","cb","settingschangedcallbacks","e","dtapStage","isLive","backendBase","dtapstage","dtapStage","islive","isLive","initEnv","setDtapStage","setBackendBase","dtapStage","isLive","backendBase","dtapstage","islive","getBrowserDebugFlags","varname","flags","urldebugvar","debugcookie","debugcookievalue","flag","sessionDebug","parseLanguageTag","languageTag","match","getLang","node","tag","omit","value","keys","elt","ret","key","val","unlock","LocalMutex","defer","LocalLock","mutex","config","siteroot","dtapStage","whconfigel","parsedConfig","omit","initEnv","flag","getBrowserDebugFlags","debugFlags","frontendConfig","getLang","prop","getFrontendData","dataObject","allowMissing","retval","DIGICONSENT_SNAPSHOT_KEY","decisions","legacyScopes","consent","mapWebHareConsent","settings","scopes","mapDigiConsentSnapshot","snapshot","scope","mapDocumentConsent","value","resolveInitialConsent","sharedSnapshot","documentConsent","connectSharedConsent","target","readSharedSnapshot","readDocumentConsent","observeDocumentConsent","apply","initial","listener","event","stopObserving","state","sameOriginEndpoint","endpoint","location","code","normalizeBasicEvent","input","key","code","randomIdentifier","cryptoImpl","bytes","hex","byte","basicTransport","endpoint","payload","createBasicTracker","options","environment","transport","randomId","randomIdentifier","send","event","normalizeBasicEvent","name","allowedFields","identifierPattern","tenantPattern","eventPattern","scopePattern","MetricsEventValidationError","message","expectRecord","input","key","expectString","value","field","maxLength","pattern","optionalString","normalizePath","path","query","fragment","end","normalizeMetricsEvent","normalized","referrerHost","source","medium","campaign","DEFAULT_ENDPOINT","DEFAULT_SESSION_TIMEOUT","DEFAULT_VISITOR_RETENTION","SESSION_STORAGE_KEY","VISITOR_STORAGE_KEY","identifierPattern","defaultTransport","endpoint","payload","error","defaultEnvironment","randomIdentifier","readCampaign","search","params","getReferrerHost","referrer","currentHost","hostname","captureLanding","environment","location","resolveAttribution","landing","marketing","campaign","validStoredSession","value","now","timeout","validStoredVisitor","createMetricsTracker","options","overrides","consentScope","sessionTimeout","visitorRetention","pageId","initialLanding","enabled","sequence","session","basic","createBasicTracker","loadVisitor","storage","parsed","persistVisitor","visitor","loadSession","persistSession","send","event","extra","normalizeMetricsEvent","setConsent","state","isExplicit","granted","shouldEnable","wasEnabled","getStorage","key","name","basicSent","conversion","config","getFrontendData","tracker","createMetricsTracker","sameOriginEndpoint","connectSharedConsent","DIGICONSENT_SNAPSHOT_KEY","listener","observer","state","aps"]}