@sentientui/core 0.21.3 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-2RH7I6AP.mjs +2 -0
- package/dist/chunk-2RH7I6AP.mjs.map +1 -0
- package/dist/chunk-EWP6FTHE.mjs +2 -0
- package/dist/chunk-EWP6FTHE.mjs.map +1 -0
- package/dist/chunk-KIP52DUJ.mjs +2 -0
- package/dist/chunk-KIP52DUJ.mjs.map +1 -0
- package/dist/classify-DYlSjkFP.d.cts +47 -0
- package/dist/classify-DYlSjkFP.d.ts +47 -0
- package/dist/{index-BcRtGYVH.d.ts → index-BbrtAtrY.d.ts} +11 -4
- package/dist/{index-D3_vlZ3z.d.cts → index-CXxvWxCB.d.cts} +11 -4
- package/dist/index-engagement.d.cts +3 -28
- package/dist/index-engagement.d.ts +3 -28
- package/dist/index-engagement.js +1 -1
- package/dist/index-engagement.js.map +1 -1
- package/dist/index-engagement.mjs +1 -1
- package/dist/index-engagement.mjs.map +1 -1
- package/dist/index-graph.d.cts +15 -5
- package/dist/index-graph.d.ts +15 -5
- package/dist/index-graph.js +1 -1
- package/dist/index-graph.js.map +1 -1
- package/dist/index-graph.mjs +1 -1
- package/dist/index-graph.mjs.map +1 -1
- package/dist/index-local.d.cts +1 -1
- package/dist/index-local.d.ts +1 -1
- package/dist/index-topics.d.cts +21 -0
- package/dist/index-topics.d.ts +21 -0
- package/dist/index-topics.js +2 -0
- package/dist/index-topics.js.map +1 -0
- package/dist/index-topics.mjs +2 -0
- package/dist/index-topics.mjs.map +1 -0
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +7 -2
- package/dist/chunk-CD2A55US.mjs +0 -2
- package/dist/chunk-CD2A55US.mjs.map +0 -1
- package/dist/chunk-Q252FDO2.mjs +0 -2
- package/dist/chunk-Q252FDO2.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engagement/capture.ts"],"sourcesContent":["import { classifySection, SEMANTIC_TYPES, type SemanticType } from './classify';\nimport { isDoNotTrackEnabled } from '../index.js';\nimport { attachMicroSignalDetectors } from '../micro-signals.js';\n\n// Shared engagement capture (spec 2026-07-22-persona-signal-capture). Detects\n// semantic sections, registers them via /v1/section-map, and records per-section\n// dwell/scroll via IntersectionObserver — emitting the same 'dwell' events the\n// persona pipeline consumes. Used by the React provider (default on) and the\n// no-code snippet. Defense-in-depth: checks DNT internally even though callers\n// gate on consent/DNT too; a missing IntersectionObserver → no-op.\n\ntype CaptureClient = {\n track(event: { projectId: string; componentId: string; eventType: string; payload: Record<string, unknown> }): void;\n};\n\nexport type EngagementCaptureOptions = {\n apiKey: string;\n /** API base, no trailing slash. Defaults to the hosted API. */\n apiBase?: string;\n doc?: Document;\n /**\n * Also attach per-section micro-signal detectors (rage click, text copy,\n * scroll hesitation, tab loss), attributed to the section's `nc-<type>`\n * component. For the no-code snippet, whose pages have no `<Adaptive>`\n * components carrying their own detectors. Default false — the React SDK\n * keeps its per-component detectors and must not double-attach.\n */\n microSignals?: boolean;\n /**\n * Server-served section-map lookup (persona-coverage auto-classification):\n * consulted after explicit `data-sentient-type` markup, before the local\n * heuristic. Return null when the element has no served label.\n */\n typeOf?: (el: Element) => SemanticType | null;\n};\n\nconst SECTION_SELECTOR = 'section, header, footer, nav, main > div, [data-sentient-section]';\n\n/** Bank cadence for visible dwell. Dwell used to leave the page only on\n * visibilitychange/pagehide, and in production that path delivered for ~5-8%\n * of sessions (Bodyshop audit 2026-08-30): a visitor who reads and closes the\n * tab races the unload pipeline, and mobile browsers can kill a page with no\n * lifecycle event at all. The heartbeat caps the loss at one interval. */\nconst HEARTBEAT_MS = 20_000;\n\n/**\n * Pick the elements to observe. Two rules, in order:\n * 1. A candidate that CONTAINS two or more other candidates is a layout\n * wrapper, not a section — drop it. Pages built from bare divs match\n * `main > div` with their page-wide content wrapper; keeping that outer\n * match swallowed every real <section> inside it, collapsing the whole page\n * into one nc-generic component whose intersectionRatio could never exceed\n * viewport-height / page-height (a constant ~0.05 scroll_depth on the\n * audited site). A candidate with exactly one nested candidate (header >\n * nav) is NOT a wrapper — rule 2 keeps the outer one, as before.\n * 2. Of what remains, skip a section nested inside another kept section\n * (avoid double count).\n */\nfunction selectSections(doc: Document): Element[] {\n const candidates = Array.from(doc.querySelectorAll(SECTION_SELECTOR));\n const kept = candidates.filter(\n (el) => candidates.filter((c) => c !== el && el.contains(c)).length < 2,\n );\n return kept.filter((el) => !kept.some((k) => k !== el && k.contains(el)));\n}\n\nfunction registerSections(\n apiKey: string,\n apiBase: string,\n pageUrl: string,\n sections: Array<{ componentId: string; semanticType: SemanticType; source: 'markup' | 'auto' }>,\n): void {\n try {\n void fetch(`${apiBase}/v1/section-map`, {\n method: 'POST',\n keepalive: true,\n headers: { 'content-type': 'application/json', authorization: `Bearer ${apiKey}` },\n body: JSON.stringify({ pageUrl, sections }),\n }).catch(() => undefined);\n } catch {\n /* fail-safe */\n }\n}\n\nconst NOOP = (): void => undefined;\n\nexport function startEngagementCapture(\n client: CaptureClient,\n opts: EngagementCaptureOptions,\n): () => void {\n const doc = opts.doc ?? (typeof document !== 'undefined' ? document : undefined);\n if (!doc || typeof IntersectionObserver === 'undefined') return NOOP;\n if (isDoNotTrackEnabled()) return NOOP;\n // Keyless zero-network contract: capture exists to feed the hosted persona\n // pipeline — with no api key there is nothing to feed, and the section-map\n // registration fetch must never fire.\n if (!opts.apiKey) return NOOP;\n // Normalize so both a ROOT base (`https://api.sentient-ui.com`) and a\n // `/v1`-suffixed base resolve to exactly one `/v1/section-map` — some callers\n // pass the versioned base, which would otherwise produce `/v1/v1/section-map`\n // (a silent 404). Strip trailing slashes, then a single trailing `/v1`.\n const apiBase = (opts.apiBase ?? 'https://api.sentient-ui.com')\n .replace(/\\/+$/, '')\n .replace(/\\/v1$/, '');\n\n const els = selectSections(doc);\n if (els.length === 0) return NOOP;\n\n // Collapse to one component per semantic type per page (the matrix aggregates\n // by semantic type anyway). Per-element precedence: explicit data-sentient-type\n // markup → served section map (opts.typeOf) → local heuristic.\n const componentOf = new Map<Element, string>();\n const types = new Map<string, SemanticType>();\n const sources = new Map<string, 'markup' | 'auto'>();\n for (const el of els) {\n const explicit = el.getAttribute('data-sentient-type');\n const markup = explicit && (SEMANTIC_TYPES as readonly string[]).includes(explicit)\n ? (explicit as SemanticType)\n : null;\n const type = markup ?? opts.typeOf?.(el) ?? classifySection(el);\n const componentId = `nc-${type}`;\n componentOf.set(el, componentId);\n types.set(componentId, type);\n // Markup wins if the same collapsed component gets both provenances.\n if (markup) sources.set(componentId, 'markup');\n else if (!sources.has(componentId)) sources.set(componentId, 'auto');\n }\n\n const pageUrl = (doc.defaultView ?? (typeof window !== 'undefined' ? window : undefined))?.location?.pathname ?? '/';\n registerSections(opts.apiKey, apiBase, pageUrl, [...types.entries()].map(([componentId, semanticType]) => ({\n componentId, semanticType, source: sources.get(componentId) ?? 'auto',\n })));\n\n // Accumulate visible dwell (ms) + max scroll ratio per component. `intersecting`\n // tracks in-viewport state independently of `enterAt` (the running clock) so a\n // tab-hide can pause the clock and a tab-show can resume it for still-visible\n // sections — IntersectionObserver does not re-fire on visibilitychange.\n const state = new Map<string, { ms: number; scroll: number; enterAt: number | null; intersecting: boolean }>();\n const get = (id: string) => {\n let s = state.get(id);\n if (!s) { s = { ms: 0, scroll: 0, enterAt: null, intersecting: false }; state.set(id, s); }\n return s;\n };\n\n const observer = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n const id = componentOf.get(entry.target);\n if (!id) continue;\n const s = get(id);\n if (entry.isIntersecting) {\n s.intersecting = true;\n s.enterAt = Date.now();\n if (entry.intersectionRatio > s.scroll) s.scroll = entry.intersectionRatio;\n } else {\n s.intersecting = false;\n if (s.enterAt != null) { s.ms += Date.now() - s.enterAt; s.enterAt = null; }\n }\n }\n }, { threshold: [0, 0.25, 0.5, 0.75, 1] });\n for (const el of componentOf.keys()) observer.observe(el);\n\n // Bank accumulated dwell and RESET the accumulators (so a later emit can't\n // double-count) WITHOUT disconnecting — a visitor who hides/re-shows the tab\n // or tab-switches keeps being measured. Pauses the running clock; the tab-show\n // handler restarts it for still-visible sections so hidden time isn't counted.\n const emit = (): void => {\n const now = Date.now();\n for (const [id, s] of state) {\n if (s.enterAt != null) { s.ms += now - s.enterAt; s.enterAt = null; }\n if (s.ms <= 0) continue;\n try {\n client.track({\n projectId: opts.apiKey, // SDK convention: server derives the real project from the key\n componentId: id,\n eventType: 'dwell',\n payload: { dwell_time: Math.round(s.ms), scroll_depth: Number(s.scroll.toFixed(2)) },\n });\n } catch {\n /* fail-safe */\n }\n s.ms = 0;\n }\n };\n\n const onVisibility = (): void => {\n if (doc.hidden) {\n emit(); // bank + pause\n } else {\n const now = Date.now(); // resume the clock for sections still on screen\n for (const s of state.values()) if (s.intersecting) s.enterAt = now;\n }\n };\n // A page can be FROZEN into the bfcache rather than torn down. Timers keep\n // firing on restore, and `intersecting` still holds whatever it held at\n // pagehide — so without this the heartbeat kept banking dwell for sections the\n // visitor had scrolled far past, forever, while the observer that could have\n // corrected them had been disconnected. Freeze the clocks instead, and only\n // tear down for real when the page is genuinely going away.\n let frozen = false;\n const onPageHide = (event?: { persisted?: boolean }): void => {\n emit(); // bank whatever is measured either way\n if (event?.persisted) {\n frozen = true; // bfcache: keep the observer, stop counting\n return;\n }\n try { observer.disconnect(); } catch { /* ignore */ }\n };\n const onPageShow = (event?: { persisted?: boolean }): void => {\n if (!event?.persisted || !frozen) return;\n frozen = false;\n // The observer stayed connected, so it will correct `intersecting` for\n // anything that moved. Restart clocks only for what is on screen NOW.\n const now = Date.now();\n for (const s of state.values()) s.enterAt = s.intersecting && !doc.hidden ? now : null;\n };\n doc.addEventListener('visibilitychange', onVisibility);\n const win = doc.defaultView ?? (typeof window !== 'undefined' ? window : undefined);\n win?.addEventListener('pagehide', onPageHide);\n win?.addEventListener('pageshow', onPageShow);\n\n // See HEARTBEAT_MS: bank visible dwell periodically so a hard close (or a\n // mobile page kill) loses at most one interval instead of the whole visit.\n // Hidden tabs skip the emit — their clock is already paused, and an empty\n // state map makes emit a no-op anyway.\n const heartbeat = setInterval(() => {\n if (doc.hidden || frozen) return;\n emit();\n // emit() pauses every running clock and only the tab-show handler restarts\n // them — here the page never went hidden, so restart the clock ourselves\n // or accumulation silently stops after the first heartbeat.\n const now = Date.now();\n for (const s of state.values()) if (s.intersecting) s.enterAt = now;\n }, HEARTBEAT_MS);\n\n // Per-section micro-signal detectors (opt-in; see EngagementCaptureOptions).\n // Attributed to the section's nc-<type> id with no variant — they feed the\n // persona attention fallback and auto-discovery, never rewards.\n const detectorCleanups: Array<() => void> = [];\n if (opts.microSignals) {\n // tab_loss is a single document-level `visibilitychange` signal, so enabling\n // it on every section detector would emit one tab_loss per nc-<type> section\n // on a single tab-hide — attributing one page-level exit to every section\n // (audit M5). Enable it on only the first section so the exit is recorded\n // once, mirroring the per-option path in slot-signals.ts ({ tabLoss: index === 0 }).\n [...componentOf.entries()].forEach(([el, componentId], i) => {\n detectorCleanups.push(\n attachMicroSignalDetectors((signalType, extra = {}) => {\n try {\n client.track({\n projectId: opts.apiKey,\n componentId,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n } catch {\n /* fail-safe */\n }\n }, el, undefined, { tabLoss: i === 0 }),\n );\n });\n }\n\n // Cleanup: bank any remaining dwell, then detach everything (provider unmount\n // / consent re-init must not leak observers or listeners).\n return () => {\n emit();\n clearInterval(heartbeat);\n doc.removeEventListener('visibilitychange', onVisibility);\n win?.removeEventListener('pagehide', onPageHide);\n win?.removeEventListener('pageshow', onPageShow);\n for (const c of detectorCleanups) c();\n try { observer.disconnect(); } catch { /* ignore */ }\n };\n}\n"],"mappings":"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","names":["SECTION_SELECTOR","HEARTBEAT_MS","selectSections","doc","candidates","kept","el","k","registerSections","apiKey","apiBase","pageUrl","sections","e","NOOP","startEngagementCapture","client","opts","_a","_b","_c","_d","_e","_f","_g","_h","_i","isDoNotTrackEnabled","els","componentOf","types","sources","explicit","markup","SEMANTIC_TYPES","type","classifySection","componentId","semanticType","state","get","id","s","observer","entries","entry","emit","now","onVisibility","frozen","onPageHide","event","onPageShow","win","heartbeat","detectorCleanups","i","attachMicroSignalDetectors","signalType","extra","__spreadValues","c"]}
|
|
1
|
+
{"version":3,"sources":["../src/engagement/capture.ts"],"sourcesContent":["import { classifySection, SEMANTIC_TYPES, type SemanticType } from './classify';\nimport { isDoNotTrackEnabled } from '../index.js';\nimport { attachMicroSignalDetectors } from '../micro-signals.js';\nimport { locatorFromElement } from '../locator-from-dom.js';\n\n// Shared engagement capture (spec 2026-07-22-persona-signal-capture). Detects\n// semantic sections, registers them via /v1/section-map, and records per-section\n// dwell/scroll via IntersectionObserver — emitting the same 'dwell' events the\n// persona pipeline consumes. Used by the React provider (default on) and the\n// no-code snippet. Defense-in-depth: checks DNT internally even though callers\n// gate on consent/DNT too; a missing IntersectionObserver → no-op.\n\ntype CaptureClient = {\n track(event: { projectId: string; componentId: string; eventType: string; payload: Record<string, unknown> }): void;\n};\n\nexport type EngagementCaptureOptions = {\n apiKey: string;\n /** API base, no trailing slash. Defaults to the hosted API. */\n apiBase?: string;\n doc?: Document;\n /**\n * Also attach per-section micro-signal detectors (rage click, text copy,\n * scroll hesitation, tab loss), attributed to the section's `nc-<type>`\n * component. For the no-code snippet, whose pages have no `<Adaptive>`\n * components carrying their own detectors. Default false — the React SDK\n * keeps its per-component detectors and must not double-attach.\n */\n microSignals?: boolean;\n /**\n * Server-served section-map lookup (persona-coverage auto-classification):\n * consulted after explicit `data-sentient-type` markup, before the local\n * heuristic. Return null when the element has no served label.\n */\n typeOf?: (el: Element) => SemanticType | null;\n};\n\nconst SECTION_SELECTOR = 'section, header, footer, nav, main > div, [data-sentient-section]';\n\n/** Bank cadence for visible dwell. Dwell used to leave the page only on\n * visibilitychange/pagehide, and in production that path delivered for ~5-8%\n * of sessions (Bodyshop audit 2026-08-30): a visitor who reads and closes the\n * tab races the unload pipeline, and mobile browsers can kill a page with no\n * lifecycle event at all. The heartbeat caps the loss at one interval. */\nconst HEARTBEAT_MS = 20_000;\n\n/**\n * Pick the elements to observe. Two rules, in order:\n * 1. A candidate that CONTAINS two or more other candidates is a layout\n * wrapper, not a section — drop it. Pages built from bare divs match\n * `main > div` with their page-wide content wrapper; keeping that outer\n * match swallowed every real <section> inside it, collapsing the whole page\n * into one nc-generic component whose intersectionRatio could never exceed\n * viewport-height / page-height (a constant ~0.05 scroll_depth on the\n * audited site). A candidate with exactly one nested candidate (header >\n * nav) is NOT a wrapper — rule 2 keeps the outer one, as before.\n * 2. Of what remains, skip a section nested inside another kept section\n * (avoid double count).\n */\nfunction selectSections(doc: Document): Element[] {\n const candidates = Array.from(doc.querySelectorAll(SECTION_SELECTOR));\n const kept = candidates.filter(\n (el) => candidates.filter((c) => c !== el && el.contains(c)).length < 2,\n );\n return kept.filter((el) => !kept.some((k) => k !== el && k.contains(el)));\n}\n\nfunction registerSections(\n apiKey: string,\n apiBase: string,\n pageUrl: string,\n sections: Array<{\n componentId: string;\n semanticType: SemanticType;\n source: 'markup' | 'auto';\n locator?: unknown;\n }>,\n): void {\n try {\n void fetch(`${apiBase}/v1/section-map`, {\n method: 'POST',\n keepalive: true,\n headers: { 'content-type': 'application/json', authorization: `Bearer ${apiKey}` },\n body: JSON.stringify({ pageUrl, sections }),\n }).catch(() => undefined);\n } catch {\n /* fail-safe */\n }\n}\n\nconst NOOP = (): void => undefined;\n\nexport function startEngagementCapture(\n client: CaptureClient,\n opts: EngagementCaptureOptions,\n): () => void {\n const doc = opts.doc ?? (typeof document !== 'undefined' ? document : undefined);\n if (!doc || typeof IntersectionObserver === 'undefined') return NOOP;\n if (isDoNotTrackEnabled()) return NOOP;\n // Keyless zero-network contract: capture exists to feed the hosted persona\n // pipeline — with no api key there is nothing to feed, and the section-map\n // registration fetch must never fire. Same validity rule as init() and the\n // graph entry: this used to check truthiness only, so an invalid non-`pk_`\n // (typo'd) key still fired /v1/section-map registration and dwell events\n // into a client that discards everything.\n if (!opts.apiKey || !opts.apiKey.startsWith('pk_')) return NOOP;\n // Normalize so both a ROOT base (`https://api.sentient-ui.com`) and a\n // `/v1`-suffixed base resolve to exactly one `/v1/section-map` — some callers\n // pass the versioned base, which would otherwise produce `/v1/v1/section-map`\n // (a silent 404). Strip trailing slashes, then a single trailing `/v1`.\n const apiBase = (opts.apiBase ?? 'https://api.sentient-ui.com')\n .replace(/\\/+$/, '')\n .replace(/\\/v1$/, '');\n\n const els = selectSections(doc);\n if (els.length === 0) return NOOP;\n\n // Collapse to one component per semantic type per page (the matrix aggregates\n // by semantic type anyway). Per-element precedence: explicit data-sentient-type\n // markup → served section map (opts.typeOf) → local heuristic.\n const componentOf = new Map<Element, string>();\n // One entry PER ELEMENT for the section map, even though componentId still\n // collapses by type. The server derives a distinct section_key from each\n // locator, so a page whose bands all classify `generic` still gets one\n // identity per band instead of a single nc-generic covering all of them.\n // Dwell keeps keying on the collapsed componentId — that is unchanged here.\n const entries: Array<{\n componentId: string;\n semanticType: SemanticType;\n source: 'markup' | 'auto';\n locator?: unknown;\n }> = [];\n for (const el of els) {\n const explicit = el.getAttribute('data-sentient-type');\n const markup = explicit && (SEMANTIC_TYPES as readonly string[]).includes(explicit)\n ? (explicit as SemanticType)\n : null;\n const type = markup ?? opts.typeOf?.(el) ?? classifySection(el);\n const componentId = `nc-${type}`;\n componentOf.set(el, componentId);\n // `source` is now per ELEMENT, not per collapsed component. Previously,\n // markup on any one element made the whole collapsed component report as\n // 'markup'; with one row per section the server can record each section's\n // real provenance instead of the most-confident of its siblings'.\n const locator = locatorFromElement(el, doc);\n entries.push({\n componentId,\n semanticType: type,\n source: markup ? 'markup' : 'auto',\n ...(locator ? { locator } : {}),\n });\n }\n\n const pageUrl = (doc.defaultView ?? (typeof window !== 'undefined' ? window : undefined))?.location?.pathname ?? '/';\n registerSections(opts.apiKey, apiBase, pageUrl, entries);\n\n // Accumulate visible dwell (ms) + max scroll ratio per component. `intersecting`\n // tracks in-viewport state independently of `enterAt` (the running clock) so a\n // tab-hide can pause the clock and a tab-show can resume it for still-visible\n // sections — IntersectionObserver does not re-fire on visibilitychange.\n const state = new Map<string, { ms: number; scroll: number; enterAt: number | null; intersecting: boolean }>();\n const get = (id: string) => {\n let s = state.get(id);\n if (!s) { s = { ms: 0, scroll: 0, enterAt: null, intersecting: false }; state.set(id, s); }\n return s;\n };\n\n const observer = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n const id = componentOf.get(entry.target);\n if (!id) continue;\n const s = get(id);\n if (entry.isIntersecting) {\n s.intersecting = true;\n s.enterAt = Date.now();\n if (entry.intersectionRatio > s.scroll) s.scroll = entry.intersectionRatio;\n } else {\n s.intersecting = false;\n if (s.enterAt != null) { s.ms += Date.now() - s.enterAt; s.enterAt = null; }\n }\n }\n }, { threshold: [0, 0.25, 0.5, 0.75, 1] });\n for (const el of componentOf.keys()) observer.observe(el);\n\n // Bank accumulated dwell and RESET the accumulators (so a later emit can't\n // double-count) WITHOUT disconnecting — a visitor who hides/re-shows the tab\n // or tab-switches keeps being measured. Pauses the running clock; the tab-show\n // handler restarts it for still-visible sections so hidden time isn't counted.\n const emit = (): void => {\n const now = Date.now();\n for (const [id, s] of state) {\n if (s.enterAt != null) { s.ms += now - s.enterAt; s.enterAt = null; }\n if (s.ms <= 0) continue;\n try {\n client.track({\n projectId: opts.apiKey, // SDK convention: server derives the real project from the key\n componentId: id,\n eventType: 'dwell',\n payload: { dwell_time: Math.round(s.ms), scroll_depth: Number(s.scroll.toFixed(2)) },\n });\n } catch {\n /* fail-safe */\n }\n s.ms = 0;\n }\n };\n\n const onVisibility = (): void => {\n if (doc.hidden) {\n emit(); // bank + pause\n } else {\n const now = Date.now(); // resume the clock for sections still on screen\n for (const s of state.values()) if (s.intersecting) s.enterAt = now;\n }\n };\n // A page can be FROZEN into the bfcache rather than torn down. Timers keep\n // firing on restore, and `intersecting` still holds whatever it held at\n // pagehide — so without this the heartbeat kept banking dwell for sections the\n // visitor had scrolled far past, forever, while the observer that could have\n // corrected them had been disconnected. Freeze the clocks instead, and only\n // tear down for real when the page is genuinely going away.\n let frozen = false;\n const onPageHide = (event?: { persisted?: boolean }): void => {\n emit(); // bank whatever is measured either way\n if (event?.persisted) {\n frozen = true; // bfcache: keep the observer, stop counting\n return;\n }\n try { observer.disconnect(); } catch { /* ignore */ }\n };\n const onPageShow = (event?: { persisted?: boolean }): void => {\n if (!event?.persisted || !frozen) return;\n frozen = false;\n // The observer stayed connected, so it will correct `intersecting` for\n // anything that moved. Restart clocks only for what is on screen NOW.\n const now = Date.now();\n for (const s of state.values()) s.enterAt = s.intersecting && !doc.hidden ? now : null;\n };\n doc.addEventListener('visibilitychange', onVisibility);\n const win = doc.defaultView ?? (typeof window !== 'undefined' ? window : undefined);\n win?.addEventListener('pagehide', onPageHide);\n win?.addEventListener('pageshow', onPageShow);\n\n // See HEARTBEAT_MS: bank visible dwell periodically so a hard close (or a\n // mobile page kill) loses at most one interval instead of the whole visit.\n // Hidden tabs skip the emit — their clock is already paused, and an empty\n // state map makes emit a no-op anyway.\n const heartbeat = setInterval(() => {\n if (doc.hidden || frozen) return;\n emit();\n // emit() pauses every running clock and only the tab-show handler restarts\n // them — here the page never went hidden, so restart the clock ourselves\n // or accumulation silently stops after the first heartbeat.\n const now = Date.now();\n for (const s of state.values()) if (s.intersecting) s.enterAt = now;\n }, HEARTBEAT_MS);\n\n // Per-section micro-signal detectors (opt-in; see EngagementCaptureOptions).\n // Attributed to the section's nc-<type> id with no variant — they feed the\n // persona attention fallback and auto-discovery, never rewards.\n const detectorCleanups: Array<() => void> = [];\n if (opts.microSignals) {\n // tab_loss is a single document-level `visibilitychange` signal, so enabling\n // it on every section detector would emit one tab_loss per nc-<type> section\n // on a single tab-hide — attributing one page-level exit to every section\n // (audit M5). Enable it on only the first section so the exit is recorded\n // once, mirroring the per-option path in slot-signals.ts ({ tabLoss: index === 0 }).\n [...componentOf.entries()].forEach(([el, componentId], i) => {\n detectorCleanups.push(\n attachMicroSignalDetectors((signalType, extra = {}) => {\n try {\n client.track({\n projectId: opts.apiKey,\n componentId,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n } catch {\n /* fail-safe */\n }\n }, el, undefined, { tabLoss: i === 0 }),\n );\n });\n }\n\n // Cleanup: bank any remaining dwell, then detach everything (provider unmount\n // / consent re-init must not leak observers or listeners).\n return () => {\n emit();\n clearInterval(heartbeat);\n doc.removeEventListener('visibilitychange', onVisibility);\n win?.removeEventListener('pagehide', onPageHide);\n win?.removeEventListener('pageshow', onPageShow);\n for (const c of detectorCleanups) c();\n try { observer.disconnect(); } catch { /* ignore */ }\n };\n}\n"],"mappings":"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","names":["SECTION_SELECTOR","HEARTBEAT_MS","selectSections","doc","candidates","kept","el","k","registerSections","apiKey","apiBase","pageUrl","sections","e","NOOP","startEngagementCapture","client","opts","_a","_b","_c","_d","_e","_f","_g","_h","_i","isDoNotTrackEnabled","els","componentOf","entries","explicit","markup","SEMANTIC_TYPES","type","classifySection","componentId","locator","locatorFromElement","__spreadValues","state","get","id","s","observer","entry","emit","now","onVisibility","frozen","onPageHide","event","onPageShow","win","heartbeat","detectorCleanups","i","attachMicroSignalDetectors","signalType","extra","c"]}
|
package/dist/index-graph.d.cts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { a6 as SentientConfig, a5 as SentientClient } from './index-
|
|
2
|
-
export { A as AssignResult, a as Assignment, b as AssignmentCache, I as EventQueue, J as EventType, M as GraphClient, N as GraphConfig, O as GraphSnapshot, a1 as PageNode, a2 as QueueConfig, a7 as SentientEvent, a8 as SessionConfig, a9 as SessionManager, an as sanitizePageUrl } from './index-
|
|
3
|
-
export { j as deriveSessionSegment, k as detectDeviceClass, l as detectTimeOfDay, m as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-BVvq5RBB.cjs';
|
|
4
|
-
|
|
1
|
+
import { E as CompoundLocator, a6 as SentientConfig, a5 as SentientClient } from './index-CXxvWxCB.cjs';
|
|
2
|
+
export { A as AssignResult, a as Assignment, b as AssignmentCache, B as BLOCK_ALIGNS, c as BLOCK_EMPHASES, d as BLOCK_FITS, e as BLOCK_GAPS, f as BLOCK_GRID_COLUMNS, g as BLOCK_HEADING_LEVELS, h as BLOCK_JUSTIFIES, i as BLOCK_RATIOS, j as BLOCK_SIZES, k as BLOCK_TEXT_ALIGNS, l as BLOCK_TONES, m as BLOCK_WEIGHTS, n as BadgeBlock, o as BlockAlign, p as BlockEmphasis, q as BlockFit, r as BlockGap, s as BlockJustify, t as BlockNode, u as BlockRatio, v as BlockSize, w as BlockTextAlign, x as BlockTone, y as BlockWeight, z as ButtonBlock, H as DecisionSnapshot, I as EventQueue, J as EventType, M as GraphClient, N as GraphConfig, O as GraphSnapshot, P as GridBlock, Q as HeadingBlock, R as ImageBlock, S as LEGACY_SESSION_COOKIE_NAME, U as LinkBlock, V as MAX_BLOCK_ARMS, W as MAX_BLOCK_CHILDREN, X as MAX_BLOCK_DEPTH, Y as MAX_BLOCK_NODES, Z as MAX_BLOCK_TEXT_LEN, _ as MicroSignalEmitter, $ as MicroSignalType, a1 as PageNode, a2 as QueueConfig, a3 as SNAPSHOT_STORAGE_KEY_PREFIX, a7 as SentientEvent, a8 as SessionConfig, a9 as SessionManager, aa as SitePalette, ab as SlotConfigEntry, ac as SlotOps, ad as SpacerBlock, ae as StackBlock, af as TextBlock, ai as attachMicroSignalDetectors, aj as grantConsent, al as isDoNotTrackEnabled, am as readSnapshot, an as renderPrePaintScript, ao as sanitizePageUrl, ap as sessionCookieName, aq as writeSnapshot } from './index-CXxvWxCB.cjs';
|
|
3
|
+
export { b as SlotDeclInput, e as armOfResult, f as baselineResultFor, g as baselineSlots, j as deriveSessionSegment, k as detectDeviceClass, l as detectTimeOfDay, m as detectTrafficSource, r as referrerDomainFromReferer, t as toWireSlot } from './session-meta-BVvq5RBB.cjs';
|
|
4
|
+
export { SlotResult } from '@sentientui/policy';
|
|
5
5
|
|
|
6
6
|
/** Reads the rendered DOM to build the page-side context graph. */
|
|
7
|
+
|
|
7
8
|
type ScannedNode = {
|
|
8
9
|
componentId: string;
|
|
9
10
|
semanticType: string;
|
|
@@ -14,6 +15,11 @@ type ScannedNode = {
|
|
|
14
15
|
depth: number;
|
|
15
16
|
reactComponentName?: string;
|
|
16
17
|
dataAttributes: Record<string, string>;
|
|
18
|
+
/** Compound locator for this element. The server hashes it into section_key —
|
|
19
|
+
* the identity the crawler and the snippet resolve to for the same physical
|
|
20
|
+
* section. Undefined when nothing resolves uniquely: the runtime never
|
|
21
|
+
* guesses an identity it could not verify later. */
|
|
22
|
+
locator?: CompoundLocator;
|
|
17
23
|
};
|
|
18
24
|
type StructuralEdge = {
|
|
19
25
|
fromComponentId: string;
|
|
@@ -38,6 +44,10 @@ type DOMScanner = {
|
|
|
38
44
|
destroy(): void;
|
|
39
45
|
};
|
|
40
46
|
|
|
47
|
+
/** Build a compound locator for a live DOM element. Returns null when nothing
|
|
48
|
+
* resolves uniquely — the runtime never guesses an identity. */
|
|
49
|
+
declare function locatorFromElement(el: Element, root: ParentNode): CompoundLocator | null;
|
|
50
|
+
|
|
41
51
|
/**
|
|
42
52
|
* Graph-capable entry point for @sentientui/core.
|
|
43
53
|
*
|
|
@@ -63,4 +73,4 @@ type GraphSentientConfig = SentientConfig & {
|
|
|
63
73
|
};
|
|
64
74
|
declare function init(config: GraphSentientConfig): SentientClient;
|
|
65
75
|
|
|
66
|
-
export { type ContentAddedEvent, type DOMScanner, type GraphSentientConfig, type ScanResult, type ScannedNode, SentientClient, SentientConfig, init };
|
|
76
|
+
export { CompoundLocator, type ContentAddedEvent, type DOMScanner, type GraphSentientConfig, type ScanResult, type ScannedNode, SentientClient, SentientConfig, init, locatorFromElement };
|
package/dist/index-graph.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { a6 as SentientConfig, a5 as SentientClient } from './index-
|
|
2
|
-
export { A as AssignResult, a as Assignment, b as AssignmentCache, I as EventQueue, J as EventType, M as GraphClient, N as GraphConfig, O as GraphSnapshot, a1 as PageNode, a2 as QueueConfig, a7 as SentientEvent, a8 as SessionConfig, a9 as SessionManager, an as sanitizePageUrl } from './index-
|
|
3
|
-
export { j as deriveSessionSegment, k as detectDeviceClass, l as detectTimeOfDay, m as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-BVvq5RBB.js';
|
|
4
|
-
|
|
1
|
+
import { E as CompoundLocator, a6 as SentientConfig, a5 as SentientClient } from './index-BbrtAtrY.js';
|
|
2
|
+
export { A as AssignResult, a as Assignment, b as AssignmentCache, B as BLOCK_ALIGNS, c as BLOCK_EMPHASES, d as BLOCK_FITS, e as BLOCK_GAPS, f as BLOCK_GRID_COLUMNS, g as BLOCK_HEADING_LEVELS, h as BLOCK_JUSTIFIES, i as BLOCK_RATIOS, j as BLOCK_SIZES, k as BLOCK_TEXT_ALIGNS, l as BLOCK_TONES, m as BLOCK_WEIGHTS, n as BadgeBlock, o as BlockAlign, p as BlockEmphasis, q as BlockFit, r as BlockGap, s as BlockJustify, t as BlockNode, u as BlockRatio, v as BlockSize, w as BlockTextAlign, x as BlockTone, y as BlockWeight, z as ButtonBlock, H as DecisionSnapshot, I as EventQueue, J as EventType, M as GraphClient, N as GraphConfig, O as GraphSnapshot, P as GridBlock, Q as HeadingBlock, R as ImageBlock, S as LEGACY_SESSION_COOKIE_NAME, U as LinkBlock, V as MAX_BLOCK_ARMS, W as MAX_BLOCK_CHILDREN, X as MAX_BLOCK_DEPTH, Y as MAX_BLOCK_NODES, Z as MAX_BLOCK_TEXT_LEN, _ as MicroSignalEmitter, $ as MicroSignalType, a1 as PageNode, a2 as QueueConfig, a3 as SNAPSHOT_STORAGE_KEY_PREFIX, a7 as SentientEvent, a8 as SessionConfig, a9 as SessionManager, aa as SitePalette, ab as SlotConfigEntry, ac as SlotOps, ad as SpacerBlock, ae as StackBlock, af as TextBlock, ai as attachMicroSignalDetectors, aj as grantConsent, al as isDoNotTrackEnabled, am as readSnapshot, an as renderPrePaintScript, ao as sanitizePageUrl, ap as sessionCookieName, aq as writeSnapshot } from './index-BbrtAtrY.js';
|
|
3
|
+
export { b as SlotDeclInput, e as armOfResult, f as baselineResultFor, g as baselineSlots, j as deriveSessionSegment, k as detectDeviceClass, l as detectTimeOfDay, m as detectTrafficSource, r as referrerDomainFromReferer, t as toWireSlot } from './session-meta-BVvq5RBB.js';
|
|
4
|
+
export { SlotResult } from '@sentientui/policy';
|
|
5
5
|
|
|
6
6
|
/** Reads the rendered DOM to build the page-side context graph. */
|
|
7
|
+
|
|
7
8
|
type ScannedNode = {
|
|
8
9
|
componentId: string;
|
|
9
10
|
semanticType: string;
|
|
@@ -14,6 +15,11 @@ type ScannedNode = {
|
|
|
14
15
|
depth: number;
|
|
15
16
|
reactComponentName?: string;
|
|
16
17
|
dataAttributes: Record<string, string>;
|
|
18
|
+
/** Compound locator for this element. The server hashes it into section_key —
|
|
19
|
+
* the identity the crawler and the snippet resolve to for the same physical
|
|
20
|
+
* section. Undefined when nothing resolves uniquely: the runtime never
|
|
21
|
+
* guesses an identity it could not verify later. */
|
|
22
|
+
locator?: CompoundLocator;
|
|
17
23
|
};
|
|
18
24
|
type StructuralEdge = {
|
|
19
25
|
fromComponentId: string;
|
|
@@ -38,6 +44,10 @@ type DOMScanner = {
|
|
|
38
44
|
destroy(): void;
|
|
39
45
|
};
|
|
40
46
|
|
|
47
|
+
/** Build a compound locator for a live DOM element. Returns null when nothing
|
|
48
|
+
* resolves uniquely — the runtime never guesses an identity. */
|
|
49
|
+
declare function locatorFromElement(el: Element, root: ParentNode): CompoundLocator | null;
|
|
50
|
+
|
|
41
51
|
/**
|
|
42
52
|
* Graph-capable entry point for @sentientui/core.
|
|
43
53
|
*
|
|
@@ -63,4 +73,4 @@ type GraphSentientConfig = SentientConfig & {
|
|
|
63
73
|
};
|
|
64
74
|
declare function init(config: GraphSentientConfig): SentientClient;
|
|
65
75
|
|
|
66
|
-
export { type ContentAddedEvent, type DOMScanner, type GraphSentientConfig, type ScanResult, type ScannedNode, SentientClient, SentientConfig, init };
|
|
76
|
+
export { CompoundLocator, type ContentAddedEvent, type DOMScanner, type GraphSentientConfig, type ScanResult, type ScannedNode, SentientClient, SentientConfig, init, locatorFromElement };
|
package/dist/index-graph.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var vt=Object.create;var fe=Object.defineProperty,wt=Object.defineProperties,bt=Object.getOwnPropertyDescriptor,It=Object.getOwnPropertyDescriptors,Et=Object.getOwnPropertyNames,je=Object.getOwnPropertySymbols,xt=Object.getPrototypeOf,ze=Object.prototype.hasOwnProperty,Ct=Object.prototype.propertyIsEnumerable;var We=(e,t,n)=>t in e?fe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,I=(e,t)=>{for(var n in t||(t={}))ze.call(t,n)&&We(e,n,t[n]);if(je)for(var n of je(t))Ct.call(t,n)&&We(e,n,t[n]);return e},X=(e,t)=>wt(e,It(t));var At=(e,t)=>{for(var n in t)fe(e,n,{get:t[n],enumerable:!0})},Qe=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let l of Et(t))!ze.call(e,l)&&l!==n&&fe(e,l,{get:()=>t[l],enumerable:!(s=bt(t,l))||s.enumerable});return e};var Tt=(e,t,n)=>(n=e!=null?vt(xt(e)):{},Qe(t||!e||!e.__esModule?fe(n,"default",{value:e,enumerable:!0}):n,e)),kt=e=>Qe(fe({},"__esModule",{value:!0}),e);var On={};At(On,{deriveSessionSegment:()=>Pe,detectDeviceClass:()=>se,detectTimeOfDay:()=>ce,detectTrafficSource:()=>ie,init:()=>_n,referrerDomainFromReferer:()=>ae,sanitizePageUrl:()=>$e});module.exports=kt(On);function he(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}try{if(typeof crypto!="undefined"&&typeof crypto.getRandomValues=="function"){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t="";for(let n=0;n<16;n++)t+=e[n].toString(16).padStart(2,"0"),(n===3||n===5||n===7||n===9)&&(t+="-");return t}}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function ne(e){return e?`_${e.slice(0,12)}`:""}var _e="_snt_uid";function Se(e){return`${_e}${ne(e)}`}var Rt="_snt_uid",_t=365,Oe="_snt_uid";function Ot(){return he()}function qe(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function Dt(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(s){}}function Je(e){try{return localStorage.getItem(e)}catch(t){return null}}function Nt(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function He(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function Pt(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function Mt(e){try{sessionStorage.removeItem(e)}catch(t){}}function Lt(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function Gt(e){try{localStorage.removeItem(e)}catch(t){}}function Kt(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Ut={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function ve(e){var g,m,v,T,A,D,_;if(typeof window=="undefined")return Ut;let t=ne(e==null?void 0:e.apiKey),n=(g=e==null?void 0:e.cookieName)!=null?g:Se(e==null?void 0:e.apiKey),s=`${Oe}${t}`,u=((m=e==null?void 0:e.cookieTTLDays)!=null?m:_t)*24*60*60,a=b=>b&&b.length>0?b:null,d=()=>{var b,N;return t&&!(e!=null&&e.cookieName)?(N=(b=a(qe(Rt)))!=null?b:a(Je(Oe)))!=null?N:a(He(Oe)):null},o=(_=(D=(A=(T=(v=a(qe(n)))!=null?v:a(Je(s)))!=null?T:a(He(s)))!=null?A:d())!=null?D:a(e==null?void 0:e.ssrSessionId))!=null?_:Ot();Dt(n,o,u);let r=Nt(s,o),i=Lt(n),c=r?!1:Pt(s,o),f=!r&&!i&&!c;return{getSessionId:()=>o,isEphemeral:()=>f,destroy:()=>{o=null,Kt(n),Gt(s),Mt(s)}}}function Z(e){return Math.min(6e4,1e3*2**Math.min(e,6))}function oe(e){if(e.ok===!0)return"delivered";let{status:t}=e;return typeof t!="number"?"retry":t>=200&&t<300?"delivered":t>=400&&t<500&&t!==429?"dropped":"retry"}function we(e,t){try{let n=localStorage.getItem(e);if(!n)return[];let s=JSON.parse(n);return Array.isArray(s)?(localStorage.removeItem(e),s.slice(-t)):[]}catch(n){return[]}}function ee(e,t,n){try{let s=(()=>{try{let u=localStorage.getItem(n);if(!u)return[];let a=JSON.parse(u);return Array.isArray(a)?a:[]}catch(u){return[]}})(),l=new Map;for(let u of s)l.set(u.id,u);for(let u of e)l.set(u.id,u);localStorage.setItem(n,JSON.stringify([...l.values()].slice(-t)))}catch(s){}}function be(e,t){try{let n=localStorage.getItem(t);if(!n)return;let s=JSON.parse(n);if(!Array.isArray(s))return;let l=new Set(e),u=s.filter(a=>!l.has(a.id));if(u.length===s.length)return;u.length===0?localStorage.removeItem(t):localStorage.setItem(t,JSON.stringify(u))}catch(n){}}var $t=500,Bt=56*1024;function De(e){return`_snt_retry_${e.slice(0,12)}`}var Ft={push:()=>{},flush:()=>{},destroy:()=>{}};function Ye(e){var J,G,W;if(typeof window=="undefined")return Ft;let t=(J=e.flushIntervalMs)!=null?J:5e3,n=(G=e.maxBatchSize)!=null?G:20,s=(W=e.maxRetrySize)!=null?W:100,l=e.ingestUrl,u=e.apiKey,a=De(u),d=[],o=new Set,r=[],i=h=>{for(let x of h)c.delete(x),!o.has(x)&&(o.add(x),r.push(x));for(;r.length>$t;){let x=r.shift();x&&o.delete(x)}be(h,a)},c=new Set,f=h=>{o.has(h.id)||c.has(h.id)||(c.add(h.id),d.push(h))},g=h=>{for(let x of h)o.has(x.id)||(c.add(x.id),d.push(x))},m=we(a,s);for(let h of m)f(h);let v=0,T=0,A=(h,x=!0)=>{if(h.length===0)return;let z=JSON.stringify(h),te=h.map(H=>H.id),B;try{B=fetch(l,{method:"POST",keepalive:!0,body:z,headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`}})}catch(H){ee(h,s,a),g(h),T++,v=Date.now()+Z(T);return}let le=H=>{if(oe(H)!=="retry"){if(!H.ok&&x){let re=h.filter(Y=>Y.eventType!=="pageview");if(re.length>0&&re.length<h.length){i(h.filter(Y=>Y.eventType==="pageview").map(Y=>Y.id)),A(re,!1);return}}i(te),T=0,v=0;return}ee(h,s,a),g(h),T++,v=Date.now()+Z(T)};B instanceof Promise?B.then(le).catch(()=>{ee(h,s,a),g(h),T++,v=Date.now()+Z(T)}):le(B)},D=typeof TextEncoder!="undefined"?new TextEncoder:null,_=h=>D?D.encode(h).length:h.length,b=h=>{let x=[],z=2;for(let te of h){let B=_(JSON.stringify(te))+1;if(x.length>0&&z+B>Bt||x.length>=n)break;x.push(te),z+=B}return x},N=()=>{try{if(Date.now()<v)return;for(;d.length>0&&!(Date.now()<v);){let h=d.filter(z=>!o.has(z.id));if(d.length=0,h.length===0)break;let x=b(h);if(x.length===0)break;x.length<h.length&&d.push(...h.slice(x.length)),A(x)}}catch(h){}},K=!0,S=null;S=setInterval(()=>{K&&N()},t);let k=()=>{document.visibilityState==="hidden"&&N()},q=()=>{N()};return document.addEventListener("visibilitychange",k),window.addEventListener("pagehide",q),{push(h){f(h),d.length>=n&&N()},flush:N,destroy(){K=!1,S!==null&&(clearInterval(S),S=null),document.removeEventListener("visibilitychange",k),window.removeEventListener("pagehide",q),N()}}}var jt=200;function Ne(e){return`_snt_goal_retry_${e.slice(0,12)}`}var Wt={send:()=>{},flush:()=>{},destroy:()=>{}};function Ve(e){var b,N,K;if(typeof window=="undefined")return Wt;let t=(b=e.flushIntervalMs)!=null?b:5e3,n=(N=e.maxRetrySize)!=null?N:100,s=(K=e.maxPerFlush)!=null?K:5,l=Ne(e.apiKey),u=[],a=new Set,d=new Set,o=[],r=0,i=0,c=!1,f=S=>{for(a.delete(S.id),d.has(S.id)||(d.add(S.id),o.push(S.id));o.length>jt;){let k=o.shift();k&&d.delete(k)}be([S.id],l)},g=S=>{ee([S],n,l),!d.has(S.id)&&!a.has(S.id)&&(a.add(S.id),u.push(S)),Date.now()>=r&&(i++,r=Date.now()+Z(i))},m=S=>{let k;try{k=fetch(e.url,{method:"POST",keepalive:!0,body:S.body,headers:e.headers})}catch(J){g(S);return}let q=J=>{var W;let G=oe(J);if(G==="retry"){g(S);return}G==="dropped"&&((W=e.onDrop)==null||W.call(e,S,J.status)),f(S),i=0,r=0};k instanceof Promise?k.then(q).catch(()=>g(S)):q(k)},v=()=>{try{if(c||Date.now()<r)return;let S=0;for(;u.length>0&&S<s&&!(Date.now()<r);){let k=u.shift();a.delete(k.id),!d.has(k.id)&&(S++,m(k))}}catch(S){}},T=we(l,n);for(let S of T)a.has(S.id)||(a.add(S.id),u.push(S));T.length>0&&ee(T,n,l);let A=setInterval(v,t),D=()=>{document.visibilityState==="hidden"&&v()},_=()=>v();return document.addEventListener("visibilitychange",D),window.addEventListener("pagehide",_),{send(S){if(!c&&!(d.has(S.id)||a.has(S.id))){if(Date.now()<r){ee([S],n,l),a.add(S.id),u.push(S);return}m(S)}},flush:v,destroy(){clearInterval(A),document.removeEventListener("visibilitychange",D),window.removeEventListener("pagehide",_),v(),c=!0}}}var zt=1800*1e3;function Ie(e,t){return`${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function Xe(e=zt,t){let n=new Map,s=`_snt_asgn${ne(t)}_`,l=(r,i)=>`${s}${encodeURIComponent(r)}:${encodeURIComponent(i)}`,u=r=>{let i=r.slice(s.length),c=i.indexOf(":");if(c<0)return null;try{return{componentId:decodeURIComponent(i.slice(0,c)),segment:decodeURIComponent(i.slice(c+1))}}catch(f){return null}},a=()=>{try{let r=[];for(let i=0;i<localStorage.length;i++){let c=localStorage.key(i);c!=null&&c.startsWith(s)&&r.push(c)}return r}catch(r){return[]}},d=r=>r.assignedAt+(r.ttlMs&&r.ttlMs>0?r.ttlMs:e)<Date.now();return typeof window!="undefined"&&(()=>{for(let r of a())try{let i=localStorage.getItem(r);if(!i)continue;let c=JSON.parse(i);if(d(c)){localStorage.removeItem(r);continue}let f=u(r);if(!f)continue;n.set(Ie(f.componentId,f.segment),c)}catch(i){}})(),{get(r,i){let c=n.get(Ie(r,i));return c?d(c)?(n.delete(Ie(r,i)),null):c:null},set(r,i,c){let f=Ie(r,i);n.set(f,c);try{localStorage.setItem(l(r,i),JSON.stringify(c))}catch(g){}},invalidate(r){let i=`${encodeURIComponent(r)}:`;for(let c of[...n.keys()])c.startsWith(i)&&n.delete(c);for(let c of a()){let f=u(c);if((f==null?void 0:f.componentId)===r)try{localStorage.removeItem(c)}catch(g){}}},clear(){n.clear();for(let r of a())try{localStorage.removeItem(r)}catch(i){}}}}var Ze=["GPTBot","ChatGPT-User","OAI-SearchBot","ClaudeBot","Claude-User","Claude-SearchBot","PerplexityBot","Perplexity-User","Google-Extended","Applebot-Extended","Meta-ExternalAgent","Bytespider","CCBot","Amazonbot","cohere-ai","Diffbot"];function Ee(e){return et(e)!==null}function et(e){var n;if(!e)return null;let t=e.toLowerCase();return(n=Ze.find(s=>t.includes(s.toLowerCase())))!=null?n:null}function se(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function ie(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(l){}let s=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(s)?"search":/(^|\.)(twitter\.com|x\.com|facebook\.com|linkedin\.com|reddit\.com|t\.co)$/.test(s)?"social":"referral"}catch(n){return"direct"}}function ae(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function ce(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function Pe(e){let t=Qt("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function Qt(e,t){var u,a,d,o,r,i,c;let n=(a=(u=t==null?void 0:t.userAgent)==null?void 0:u.trim())!=null?a:"",s=(o=(d=t==null?void 0:t.referer)==null?void 0:d.trim())!=null?o:"",l=(r=t==null?void 0:t.now)!=null?r:new Date;return{sessionId:e,ephemeral:!1,utmParams:(i=t==null?void 0:t.utmParams)!=null?i:{},deviceClass:n?se(n):"desktop",trafficSource:s?ie(s,t==null?void 0:t.appOrigin):"direct",referrerDomain:ae(s),timeOfDay:ce(l),dayOfWeek:(c=["sun","mon","tue","wed","thu","fri","sat"][l.getDay()])!=null?c:"sun",automation:(t==null?void 0:t.webdriver)===!0||Ee(n)}}var de=require("@sentientui/policy");function Me(e){return I(I(I({id:e.id},e.arms?{arms:[...e.arms]}:{}),e.dims?{dims:Object.fromEntries(Object.entries(e.dims).map(([t,n])=>[t,[...n]]))}:{}),e.baseline!==void 0?{baseline:e.baseline}:{})}function Le(e){let t=Me(e);return(0,de.slotResultFor)(t,(0,de.slotBaselineArm)(t))}function tt(e){return typeof e=="string"?e:(0,de.canonicalArm)(e)}var xe="_snt_snap:",qt=["low","medium","high"];function nt(e){try{let t=localStorage.getItem(xe+e);if(!t)return null;let n=JSON.parse(t);return!n||typeof n!="object"||n.v!==1||typeof n.persona!="string"||typeof n.band!="string"||!qt.includes(n.band)||typeof n.slots!="object"||n.slots===null||Array.isArray(n.slots)||!(n.layoutOrder===null||Array.isArray(n.layoutOrder))||typeof n.savedAt!="number"||!(n.slotConfig===void 0||typeof n.slotConfig=="object"&&n.slotConfig!==null&&!Array.isArray(n.slotConfig))?null:n}catch(t){return null}}function Ce(e,t){try{localStorage.setItem(xe+e,JSON.stringify(t))}catch(n){}}var Ke=require("@sentientui/policy");var Te=require("@sentientui/policy");var rt="[sentient] No API key configured \u2014 nothing is being learned. Set NEXT_PUBLIC_SENTIENT_API_KEY or pass localMode: true for local development.",Jt="[sentient] Local mode \u2014 decisions are simulated on-device and nothing is sent over the network. Add an API key to learn from real traffic.",ot=!1,Ae=!1;function Ht(){var e;try{return(e=new URLSearchParams(window.location.search).get("sentient_persona"))!=null?e:void 0}catch(t){return}}function st(e){var d;let t=ve({ssrSessionId:e.ssrSessionId,apiKey:e.apiKey}),n=(d=t.getSessionId())!=null?d:"local",s=Ht(),l=import("@sentientui/core/local").then(o=>{let r=o;return r.LOCAL_ENGINE_AVAILABLE?(ot||(ot=!0,console.info(Jt)),r):(Ae||(Ae=!0,console.error(rt)),null)}).catch(()=>(Ae||(Ae=!0,console.error(rt)),null)),u=null;function a(o){let r=document.documentElement;r.dataset.sentientPersona===void 0&&(r.dataset.sentientPersona=o.persona,r.dataset.sentientConfidence=(0,Te.confidenceBand)(o.confidence))}return{isLocal:!0,async decide(o){var c,f,g;let r=await l;if(!r)return null;let i=r.createLocalEngine({sessionId:n,forcedPersona:s}).decide(o);return u=X(I({},i),{layoutOrder:(f=(c=i.layoutOrder)!=null?c:u==null?void 0:u.layoutOrder)!=null?f:null,slots:I(I({},(g=u==null?void 0:u.slots)!=null?g:{}),i.slots)}),Ce(e.apiKey||"local",{v:1,persona:u.persona,band:(0,Te.confidenceBand)(u.confidence),slots:u.slots,layoutOrder:u.layoutOrder,savedAt:Date.now()}),a(i),i},getSlotResult(o){var r,i,c;return(c=(i=u==null?void 0:u.slots[o])!=null?i:(r=e.initialSlots)==null?void 0:r[o])!=null?c:null},getPersona(){return u?{persona:u.persona,confidence:u.confidence,band:(0,Te.confidenceBand)(u.confidence)}:null},async assign(o,r){var f;let i=await l;return!i||!r||r.length===0?r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null:{variantId:(f=i.createLocalEngine({sessionId:n,forcedPersona:s}).decide({components:[{id:o,variantIds:r}]}).assignments[o])!=null?f:r[0],assignmentTtlMs:0}},track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>t.destroy()}}var it="https://api.sentient-ui.com/v1/events",j=new Map,Yt=null;function Vt(e){return"value"in e||"currency"in e||"externalId"in e||"metadata"in e||"weight"in e||"stepIndex"in e}var Xt=3;function Ge(){return he()}function ke(){var e;if(typeof window!="undefined")return((e=window.location)==null?void 0:e.pathname)||void 0}function Zt(){let e=new WeakMap,t=new Map,n=!1,s=(d,o,r)=>{let i=d.get(o);return r===null?i?!0:(d.set(o,new Set),!1):i?i.has(r)?!0:(i.add(r),!1):(d.set(o,new Set([r])),!1)},l=typeof window!="undefined"&&"event"in window,u=()=>{if(!l)return;let d=window.event;return typeof Event=="function"&&d instanceof Event?d:void 0},a=()=>{if(l){Promise.resolve().then(()=>{n=!1,t.clear()});return}let d=!1,o=()=>{d||(d=!0,n=!1,t.clear())};if(setTimeout(o,0),typeof MessageChannel=="function"){let r=new MessageChannel;r.port1.onmessage=()=>{r.port1.close(),r.port2.close(),o()},r.port2.postMessage(0)}};return{firedBefore(d,o){let r=u();if(r){let c=e.get(r);return c||(c=new Map,e.set(r,c)),s(c,d,o)}let i=s(t,d,o);return!i&&!n&&(n=!0,a()),i}}}var at=new Set;function en(e,t,n){let s=typeof window=="undefined"?null:window.history;if(!s)return()=>{};let l=!1,u,a=()=>{if(l)return;let r=ke();!r||r===u||(u=r,e.track({projectId:t,componentId:"__page__",eventType:"pageview",payload:{}}),n(`${t}:${r}`))},d=[];for(let r of["pushState","replaceState"]){let i=s[r],c=function(...f){let g=i.apply(this,f);return a(),g};s[r]=c,d.push([r,i,c])}window.addEventListener("popstate",a);let o=ke();return o&&at.has(`${t}:${o}`)?u=o:a(),()=>{if(!l){l=!0,window.removeEventListener("popstate",a);for(let[r,i,c]of d)s[r]===c&&(s[r]=i)}}}var me={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>{}};function tn(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,s]of t)n.startsWith("utm_")&&(e[n]=s);return e}catch(e){return{}}}function ct(e){return e.replace(/\/events\/?$/,"")}function Ue(){return typeof navigator!="undefined"&&navigator.globalPrivacyControl===!0?!0:[typeof navigator!="undefined"?navigator.doNotTrack:void 0,typeof window!="undefined"?window.doNotTrack:void 0,typeof navigator!="undefined"?navigator.msDoNotTrack:void 0].some(t=>t==="1"||t==="yes")}function nn(e){var d;let t=e.preConsentBehavior==="statistical_winner",n=ct((d=e.ingestUrl)!=null?d:it),s={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},l={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),async assign(o,r,i){if(!t)return null;try{let c=new URLSearchParams({componentId:o});for(let m of r!=null?r:[])c.append("variantIds[]",m);let f=await fetch(`${n}/winner?${c.toString()}`,{headers:s});return f.ok?{variantId:(await f.json()).variantId,assignmentTtlMs:0}:r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}catch(c){return r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}},decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>{}},u={track:o=>l.track(o),goal:((o,r,i,c)=>l.goal(o,r,i,c)),componentGoal:(o,r,i)=>l.componentGoal(o,r,i),identify:o=>l.identify(o),getAssignment:(o,r)=>l.getAssignment(o,r),assign:(o,r,i,c)=>l.assign(o,r,i,c),decide:o=>l.decide(o),getSlotResult:o=>l.getSlotResult(o),getPersona:()=>l.getPersona(),fetchWeights:()=>l.fetchWeights(),getGraph:()=>l.getGraph(),dispose:()=>l.dispose(),destroy:()=>l.destroy()};function a(o){l=o}return{proxy:u,setInner:a}}function dt(e){var x,z,te,B,le,H,re,Y,Fe;if(typeof window=="undefined")return me;Yt=e.apiKey;let t=j.get(e.apiKey||"local");if(t!=null&&t.dispose)try{t.dispose()}catch(p){}let n=e.respectDoNotTrack!==!1&&Ue(),s=e.consent===!1||n,l=typeof e.apiKey=="string"&&e.apiKey.startsWith("pk_");if(e.localMode===!0||!l&&e.localMode!==!1)return s?(j.set(e.apiKey||"local",{config:e,upgrade:null}),me):(j.set(e.apiKey||"local",{config:e,upgrade:null}),st(e));if(s){if(!e.apiKey||!e.apiKey.startsWith("pk_"))return e.preConsentBehavior==="statistical_winner"&&console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),j.set(e.apiKey,{config:e,upgrade:null}),me;let{proxy:p,setInner:y}=nn(e);return j.set(e.apiKey,{config:e,upgrade:n?null:y}),p}if(!e.apiKey||!e.apiKey.startsWith("pk_"))return console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),me;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),me;let u=(x=e.ingestUrl)!=null?x:it,a=Date.now(),d=ve({ssrSessionId:e.ssrSessionId,apiKey:e.apiKey}),o=Xe(void 0,e.apiKey),r=Ye({ingestUrl:u,apiKey:e.apiKey}),i=ct(u),c={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},f=new Set,g=Ve({url:`${i}/goals`,apiKey:e.apiKey,headers:c,onDrop:(p,y)=>{if(!e.debug){if(f.has(y))return;f.add(y)}console.warn(`[sentient] goal dropped (HTTP ${y}) \u2014 this will not be retried. `+(y===400?"The session was not found: call init() and let the session upsert complete before firing goals.":y===401||y===403?"Check the API key and that this origin is on the project allowlist.":"See the response status for the cause."),p)}}),m=se((z=navigator.userAgent)!=null?z:""),v=typeof window!="undefined"?window.location.origin:void 0,T=ie((te=document.referrer)!=null?te:"",v),A=(B=e.sessionSegment)!=null?B:`${m}:${T}`,D=new Map,_=new Map,b=null,N=p=>{for(let y of p)_.has(y.id)||_.set(y.id,Le(y))};if(e.initialSlots)for(let[p,y]of Object.entries(e.initialSlots))_.set(p,y);let K=nt(e.apiKey);if(K)for(let[p,y]of Object.entries(K.slots))_.has(p)||_.set(p,y);let S={low:.15,medium:.5,high:.85};if(e.initialPersona)b=I({},e.initialPersona);else{let p=document.documentElement.dataset;p.sentientPersona?b={persona:p.sentientPersona,confidence:(H=S[(le=p.sentientConfidence)!=null?le:"low"])!=null?H:.15}:K&&(b={persona:K.persona,confidence:(re=S[K.band])!=null?re:.15})}if(e.initialAssignments)for(let[p,y]of Object.entries(e.initialAssignments))o.set(p,A,{variantId:y,assignedAt:Date.now(),segment:A,confidence:1});let k=Promise.resolve(),q=d.getSessionId();if(q){let p=ae((Y=document.referrer)!=null?Y:""),y=I(I(I({sessionId:q,deviceClass:m,trafficSource:T,referrerDomain:p,utmParams:tn(),timeOfDay:ce(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:d.isEphemeral(),automation:typeof navigator!="undefined"&&navigator.webdriver===!0||Ee((Fe=navigator.userAgent)!=null?Fe:"")},e.userId?{userId:e.userId}:{}),e.persona?{persona:e.persona}:{}),e.country?{country:e.country}:{}),w=async()=>{for(let O=0;;O++){try{let R=await fetch(`${i}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(y),headers:c});if(R.status===402){console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentient-ui.com/pricing");return}if(R.ok||oe(R)==="dropped")return}catch(R){}if(O>=Xt){console.warn("[SentientUI] Could not register the session after retries. Conversions in this visit may not be recorded.");return}await new Promise(R=>setTimeout(R,Z(O+1)))}};try{k=w()}catch(O){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:r});let J=Zt(),G=null,W=!1,h={goal(p,y={},w=1,O=0){var ue,$,pe,C,V,ye,M;let R=d.getSessionId();if(!R)return;let E=Vt(y)?y:{metadata:y},Q=[p,(ue=E.externalId)!=null?ue:"",($=E.stepIndex)!=null?$:O,(pe=E.weight)!=null?pe:w].join("\0"),F=E.value!==void 0?`${E.value}\0${(C=E.currency)!=null?C:""}`:null;if(J.firedBefore(Q,F)){e.debug&&console.log(`[sentient] goal("${p}") already recorded for this action \u2014 not sent twice`);return}let P=Ge(),U={sessionId:R,name:p,metadata:(V=E.metadata)!=null?V:{},weight:(ye=E.weight)!=null?ye:w,stepIndex:(M=E.stepIndex)!=null?M:O,goalId:P,value:E.value,currency:E.currency,externalId:E.externalId};e.debug&&console.log("[sentient] goal",U);let L={id:P,body:JSON.stringify(U)};k.then(()=>g.send(L))},componentGoal(p,y,w){var P,U,L;let O=d.getSessionId();if(!O)return;let R=o.get(p,A),E=R?null:(P=_.get(p))!=null?P:null;if(!R&&E===null){e.debug&&console.warn(`[sentient] componentGoal("${p}"): no assignment or slot decision yet \u2014 render its <Adaptive>/adaptive hook or call assign()/decide() before recording a goal.`);return}let Q=R?R.variantId:tt(E),F={id:Ge(),sessionId:O,projectId:e.apiKey,componentId:p,variantId:Q,eventType:"goal_achieved",goalType:y,payload:I({reward:(U=w==null?void 0:w.reward)!=null?U:1,goalValue:w==null?void 0:w.value,currency:w==null?void 0:w.currency},(L=w==null?void 0:w.metadata)!=null?L:{}),timestamp:Date.now(),timeInSession:Date.now()-a,path:ke()};e.debug&&console.log("[sentient] componentGoal",F),k.then(()=>r.push(F))},identify(p){let y=d.getSessionId();y&&k.then(()=>{fetch(`${i}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,userId:p,ephemeral:d.isEphemeral()}),headers:c}).catch(()=>{})})},track(p){let y=d.getSessionId();if(!y)return;let w=X(I({path:ke()},p),{id:Ge(),sessionId:y,timestamp:Date.now(),timeInSession:Date.now()-a});e.debug&&console.log("[sentient] track",w),k.then(()=>r.push(w))},getAssignment(p,y){return o.get(p,y)},async assign(p,y,w,O){let R=d.getSessionId();if(!R)return null;let E=o.get(p,A);if(E&&(y!=null&&y.length||E.content!==void 0)){let P=E.ttlMs&&E.ttlMs>0?Math.max(0,E.assignedAt+E.ttlMs-Date.now()):0;return{variantId:E.variantId,assignmentTtlMs:P,content:E.content}}let Q=D.get(p);if(Q)return Q;let F=(async()=>{await k;try{let P={sessionId:R,componentId:p,variantIds:y};O!==void 0?P.agentDataByVariant=O:w!==void 0&&(P.agentData=w);let U=await fetch(`${i}/assign`,{method:"POST",body:JSON.stringify(P),headers:c});if(!U.ok)return null;let L=await U.json();return o.set(p,A,I({variantId:L.variantId,assignedAt:Date.now(),segment:A,confidence:1,content:L.content},L.assignmentTtlMs&&L.assignmentTtlMs>0?{ttlMs:L.assignmentTtlMs}:{})),L}catch(P){return null}finally{D.delete(p)}})();return D.set(p,F),F},async decide(p){var O,R,E,Q,F,P,U,L,ue;let y=d.getSessionId();if(!y)return null;let w=(O=p.slots)!=null?O:[];await k;try{let $={sessionId:y};p.sections&&p.sections.length>0&&($.sections=p.sections.map(M=>({id:M}))),$.components=(R=p.components)!=null?R:[],w.length>0&&($.slots=w.map(Me)),p.slotsFrom==="registry"&&($.slotsFrom="registry"),p.v&&($.v=p.v),e.persona&&($.persona=e.persona);let pe=await fetch(`${i}/decide`,{method:"POST",body:JSON.stringify($),headers:c});if(!pe.ok)return N(w),null;let C=await pe.json(),V={};for(let M of w)V[M.id]=(Q=(E=C.slots)==null?void 0:E[M.id])!=null?Q:Le(M);if(C.slots)for(let[M,ge]of Object.entries(C.slots))M in V||(V[M]=ge);for(let[M,ge]of Object.entries(V))_.set(M,ge);let ye=b!=null&&b.persona!=="unknown";C.persona&&!(C.persona==="unknown"&&ye)?b={persona:C.persona,confidence:(F=C.confidence)!=null?F:0}:b||(b={persona:"unknown",confidence:0});for(let[M,ge]of Object.entries((P=C.assignments)!=null?P:{}))o.set(M,A,{variantId:ge,assignedAt:Date.now(),segment:A,confidence:1});return Ce(e.apiKey,I(I({v:1,persona:b.persona,band:(0,Ke.confidenceBand)(b.confidence),slots:Object.fromEntries(_),layoutOrder:(U=C.layoutOrder)!=null?U:null,savedAt:Date.now()},C.slotConfig?{slotConfig:C.slotConfig}:{}),C.palette?{palette:C.palette}:{})),I(I(I(I({layoutOrder:(L=C.layoutOrder)!=null?L:null,assignments:(ue=C.assignments)!=null?ue:{},slots:V,persona:b.persona,confidence:b.confidence},C.slotConfig?{slotConfig:C.slotConfig}:{}),C.goals?{goals:C.goals}:{}),C.sectionMap?{sectionMap:C.sectionMap}:{}),C.palette?{palette:C.palette}:{})}catch($){return N(w),null}},getSlotResult(p){var y;return(y=_.get(p))!=null?y:null},getPersona(){return b?{persona:b.persona,confidence:b.confidence,band:(0,Ke.confidenceBand)(b.confidence)}:null},async fetchWeights(){var p;try{let y=await fetch(`${i}/weights`,{headers:c});return y.ok?(p=(await y.json()).components)!=null?p:[]:[]}catch(y){return[]}},getGraph(){return{pageNodes:[],capturedAt:0}},dispose(){var p;G==null||G(),W=!0,r.destroy(),g.destroy(),((p=j.get(e.apiKey))==null?void 0:p.dispose)===h.dispose&&j.delete(e.apiKey),e.debug&&console.log("[sentient] disposed")},destroy(){var p;G==null||G(),W=!0,r.destroy(),g.destroy(),d.destroy(),((p=j.get(e.apiKey))==null?void 0:p.dispose)===h.dispose&&j.delete(e.apiKey);try{localStorage.removeItem(xe+e.apiKey),localStorage.removeItem(De(e.apiKey)),localStorage.removeItem(Ne(e.apiKey))}catch(y){}e.debug&&console.log("[sentient] destroyed")}};if(j.set(e.apiKey,{config:e,upgrade:null,dispose:h.dispose}),G=en(h,e.apiKey,p=>{k.then(()=>{W||at.add(p)})}),e.debug){let p=window;p.__sentient&&(p.__sentient.client=h)}return h}var lt="_snt_graph_edges",rn={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function on(e){var t;return(t=rn[e])!=null?t:[]}function sn(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function an(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var cn=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function dn(e){return cn.has(e)?e:"generic"}function $e(e){try{let t=new URL(e);return`${t.origin}${t.pathname}`}catch(t){return"/"}}function ln(e,t,n){let s=`${e}:${t}:${n.join(",")}`,l=5381;for(let u=0;u<s.length;u++)l=(l<<5)+l+s.charCodeAt(u)&4294967295;return(l>>>0).toString(16).padStart(8,"0")}function ut(e){let t=new Map,n=new Map,s=`_snt_graph_nodes${ne(e==null?void 0:e.apiKey)}`,l=()=>{typeof window!="undefined"&&an(s,[...t.values()])},u=a=>{var d;try{let o=JSON.parse(a);t.clear();for(let r of(d=o.pageNodes)!=null?d:[])t.set(r.componentId,r)}catch(o){}};if(typeof window!="undefined"){let a=sn(s,[]);for(let d of a)t.set(d.componentId,d);try{localStorage.removeItem(lt)}catch(d){}}return{addPageNode(a){t.set(a.componentId,a),l()},addStructuralEdge(a){let d=`${a.fromComponentId}->${a.toComponentId}`;n.set(d,a)},syncOnce(){var d,o;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let a=[...t.values()];if(a.length!==0)try{let r=new Map;for(let m of a){let v=(d=r.get(m.semanticType))!=null?d:[];v.push(m),r.set(m.semanticType,v)}let i=[],c=new Set;for(let m of a)for(let v of on(m.semanticType)){let T=(o=r.get(v))!=null?o:[];for(let A of T){if(A.componentId===m.componentId)continue;let D=`semantic:${m.componentId}->${A.componentId}`;c.has(D)||(c.add(D),i.push({fromComponentId:m.componentId,toComponentId:A.componentId,type:"semantic",weight:.4,confidence:.9}))}}let f=new Set(a.map(m=>m.componentId));for(let m of n.values()){if(!f.has(m.fromComponentId)||!f.has(m.toComponentId))continue;let v=`structural:${m.fromComponentId}->${m.toComponentId}`;c.has(v)||(c.add(v),i.push({fromComponentId:m.fromComponentId,toComponentId:m.toComponentId,type:"structural",weight:m.weight,confidence:1}))}let g=X(I(I({pageUrl:$e(window.location.href)},e.sessionId?{sessionId:e.sessionId}:{}),e.projectId?{projectId:e.projectId}:{}),{nodes:a.map(m=>{let v=dn(m.semanticType);return{componentId:m.componentId,semanticType:v,answers:m.answers,contentHash:ln(m.componentId,v,m.answers),prominenceScore:m.prominenceScore,depthInPage:m.depth}}),edges:i});fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:I({"Content-Type":"application/json"},e.apiKey?{Authorization:`Bearer ${e.apiKey}`}:{}),body:JSON.stringify(g)}).catch(()=>{})}catch(r){}},snapshot(){return{pageNodes:[...t.values()],capturedAt:Date.now()}},serialize(){return JSON.stringify({pageNodes:[...t.values()]})},restore:u,destroy(){if(typeof window!="undefined")try{localStorage.removeItem(s),localStorage.removeItem(lt)}catch(a){}}}}var pt=["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"],un=[["pricing",/\b(pricing|price|plans?|subscriptions?|per month|\/mo|tier)\b/i],["faq",/\b(faq|frequently asked|common questions?)\b/i],["comparison",/\b(compare|comparison|versus|vs\.)\b/i],["social_proof",/\b(testimonial|reviews?|trusted by|loved by|customers?|logos|rated|case stud)\b/i],["trust",/\b(security|guarantee|privacy|compliance|secure|gdpr|soc ?2|encrypt)\b/i],["features",/\b(features?|how it works|benefits?|capabilit|what you get)\b/i]],pn=[["pricing",/(?:[$€£]\s?\d[\d,.]*\s*(?:\/|per\s)\s*(?:mo|month|yr|year|seat|user))|(?:\b(?:starter|basic|pro|growth|premium|enterprise)\b[^.]{0,60}[$€£]\s?\d)/i],["social_proof",/(?:★{2,})|(?:\b\d(?:\.\d)?\s*(?:out of|\/)\s*5\b)|(?:\brated\b)|(?:["“][^"”]{20,160}["”]\s*[—–-]\s*[A-Z][a-z]+)/],["trust",/\b(?:money[- ]back guarantee|refund(?:s)? within|encrypted|soc ?2|iso ?27001|gdpr[- ]compliant|cancel anytime)\b/i],["comparison",/\b(?:vs|versus)\b\.?[^.!?]{0,80}\b(?:compare|comparison|plans?|features?|alternative)\b|\bhow (?:we|it) compares?\b/i]];function gn(e){var n;let t=e.querySelector("h1, h2, h3");return((n=t==null?void 0:t.textContent)!=null?n:"").slice(0,160)}function fn(e){if(e.tag==="nav"||e.tag==="footer")return{type:"navigation",strength:"weak"};let t=`${e.idClass} ${e.headingText}`.toLowerCase();for(let[n,s]of un)if(s.test(t))return{type:n,strength:"strong"};for(let[n,s]of pn)if(s.test(e.bodyText))return{type:n,strength:"strong"};return e.actionCount>=1&&e.textLength>0&&e.textLength<200?{type:"cta",strength:"weak"}:e.tag==="header"?{type:"hero",strength:"weak"}:/\b(hero|headline|banner)\b/i.test(t)?{type:"hero",strength:"weak"}:{type:"generic",strength:"weak"}}function mn(e){var n,s;let t=((n=e.textContent)!=null?n:"").replace(/\s+/g," ").trim();return{tag:e.tagName.toLowerCase(),idClass:`${e.id} ${String((s=e.className)!=null?s:"")}`,headingText:gn(e),bodyText:t.slice(0,2e3),actionCount:e.querySelectorAll('a, button, [role="button"]').length,textLength:t.length}}function gt(e){return fn(mn(e)).type}var yn=new Set(["SECTION","ARTICLE","MAIN","DIV"]),hn="h1, h2, h3",ft=30,Sn=1500,vn={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function mt(e,t,n){return n<=t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function wn(e){var t,n,s;try{let l=e;for(let u of Object.keys(l)){if(!u.startsWith("__reactFiber")&&!u.startsWith("__reactInternalInstance"))continue;let a=l[u],d=(s=(t=a==null?void 0:a.type)==null?void 0:t.displayName)!=null?s:(n=a==null?void 0:a.type)==null?void 0:n.name;if(d&&d.length>1)return d}}catch(l){}}function bn(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}var yt=new Set(pt);function In(e){let t=e.getAttribute("data-sentient-type");if(t&&yt.has(t))return t;let n=e.getAttribute("role");return n&&yt.has(n)?n:gt(e)}function En(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)&4294967295;return(t>>>0).toString(16).padStart(8,"0")}function xn(e){let t=[],n=e;for(;n;){let s=n.parentElement;if(!s){t.push(n.tagName.toLowerCase());break}let l=Array.prototype.indexOf.call(s.children,n);t.push(`${n.tagName.toLowerCase()}[${l}]`),n=s}return t.reverse().join("/")}function Cn(e){var n;let t=(n=e.getAttribute("data-sentient-id"))!=null?n:e.getAttribute("id");return t||`${e.tagName.toLowerCase()}-${En(xn(e))}`}function An(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function Be(e,t){var s,l,u;let n=e.querySelector(hn);return{componentId:Cn(e),semanticType:In(e),ariaLabel:(s=e.getAttribute("aria-label"))!=null?s:void 0,headingText:(u=(l=n==null?void 0:n.textContent)==null?void 0:l.trim())!=null?u:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:An(e),reactComponentName:wn(e),dataAttributes:bn(e)}}function ht(e){var u;let t=[],n=new Set,s="__root__",l=new Map;for(let[a,d]of e){let o=a.parentElement,r=s;for(;o;){if(e.has(o)){r=e.get(o);let c=e.get(a),f=`${r}->${c}`;!n.has(f)&&r!==c&&(n.add(f),t.push({fromComponentId:r,toComponentId:c,weight:.6}));break}o=o.parentElement}let i=(u=l.get(r))!=null?u:[];i.push(a),l.set(r,i)}for(let a of l.values()){if(a.length<2)continue;let d=a.length>ft?a.slice(0,ft):a;for(let o=0;o<d.length;o++)for(let r=o+1;r<d.length;r++){if(t.length>=Sn)return t;let i=e.get(d[o]),c=e.get(d[r]);if(i===c)continue;let f=`${i}->${c}::sib`,g=`${c}->${i}::sib`;n.has(f)||(n.add(f),t.push({fromComponentId:i,toComponentId:c,weight:.3})),n.has(g)||(n.add(g),t.push({fromComponentId:c,toComponentId:i,weight:.3}))}}return t}function Tn(e){let t=[],n=new Set,s=new Map;return document.querySelectorAll("[data-sentient-id]").forEach(a=>{if(a instanceof Element&&!n.has(a)){n.add(a);let d=Be(a,e);t.push(d),s.set(a,d.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(a=>{if(!(a instanceof Element)||n.has(a))return;let d=a.hasAttribute("aria-label"),o=a.hasAttribute("data-sentient-id");if(!d&&!o)return;n.add(a);let r=Be(a,e);t.push(r),s.set(a,r.componentId)}),{nodes:t,edges:ht(s),elementToId:s}}function St(){if(typeof window=="undefined")return vn;let e=null,t=0,n=null,s=new Map,l=o=>{try{let r=window.getComputedStyle(o),i=parseFloat(r.fontSize)||12,c=parseFloat(r.zIndex)||0,f=o.getBoundingClientRect(),g=Math.max(f.top,0),m=window.innerHeight||1,v=1/(g/m+1),T=mt(i,12,48)*.4+v*.4+mt(c,0,100)*.2;return Math.max(0,Math.min(1,T))}catch(r){return .5}};return{scan:()=>new Promise(o=>{let r=()=>{let{nodes:i,edges:c,elementToId:f}=Tn(l);s.clear();for(let[g,m]of f)s.set(g,m);o({nodes:i,edges:c,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(r,{timeout:100}):r()}catch(i){r()}}),observe:o=>{n=o;try{e=new MutationObserver(r=>{let i=[],c=new Set;for(let g of r)g.type==="childList"&&g.addedNodes.forEach(m=>{if(!(m instanceof Element)||!yn.has(m.tagName))return;let v=m.hasAttribute("data-sentient-id"),T=m.hasAttribute("aria-label");if(!v&&!T)return;let A=Be(m,l);i.push(A),c.add(A.componentId),s.set(m,A.componentId)});if(i.length===0||!n)return;for(let g of[...s.keys()])g.isConnected||s.delete(g);let f=ht(s).filter(g=>c.has(g.fromComponentId)||c.has(g.toComponentId));n({nodes:i,edges:f,addedAt:Date.now()})}),e.observe(document.body,{childList:!0,subtree:!0})}catch(r){}},getProminenceScore:l,destroy:()=>{if(e&&(e.disconnect(),e=null),t&&typeof cancelIdleCallback=="function")try{cancelIdleCallback(t)}catch(o){}t=0,n=null,s.clear()}}}var kn="https://api.sentient-ui.com/v1/events";function Rn(e){var n;let t=s=>{try{let l=document.cookie.match(new RegExp(`(?:^|; )${s}=([^;]*)`));return l?decodeURIComponent(l[1]):void 0}catch(l){return}};return(n=e?t(Se(e)):void 0)!=null?n:t(_e)}var Re=new Map;function _n(e){var c;let t=dt(e),n=e.respectDoNotTrack!==!1&&Ue(),s=e.consent===!1||n;if(!e.graph||!e.apiKey||s||typeof window=="undefined")return t;let l=Re.get(e.apiKey);if(l)try{l()}catch(f){}let u=St(),a=(c=e.ingestUrl)!=null?c:kn,d=ut({syncUrl:a.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:Rn(e.apiKey)});u.scan().then(f=>{for(let g of f.nodes)d.addPageNode({id:g.componentId,componentId:g.componentId,semanticType:g.semanticType,answers:e.captureDomText&&g.headingText?[g.headingText]:[],prominenceScore:g.prominenceScore,depth:g.depth});for(let g of f.edges)d.addStructuralEdge(g);d.syncOnce()});let o=null,r=()=>{o!==null&&clearTimeout(o),o=setTimeout(()=>{o=null,d.syncOnce()},500)};u.observe(f=>{for(let g of f.nodes)d.addPageNode({id:g.componentId,componentId:g.componentId,semanticType:g.semanticType,answers:e.captureDomText&&g.headingText?[g.headingText]:[],prominenceScore:g.prominenceScore,depth:g.depth});for(let g of f.edges)d.addStructuralEdge(g);r()});let i=()=>{o!==null&&(clearTimeout(o),o=null),u.destroy(),d.destroy(),Re.get(e.apiKey)===i&&Re.delete(e.apiKey)};return Re.set(e.apiKey,i),X(I({},t),{getGraph:()=>d.snapshot(),dispose:()=>{i(),t.dispose()},destroy:()=>{i(),t.destroy()}})}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,init,referrerDomainFromReferer,sanitizePageUrl});
|
|
1
|
+
"use strict";var Mt=Object.create;var ve=Object.defineProperty,Kt=Object.defineProperties,Gt=Object.getOwnPropertyDescriptor,$t=Object.getOwnPropertyDescriptors,Ut=Object.getOwnPropertyNames,et=Object.getOwnPropertySymbols,Ft=Object.getPrototypeOf,nt=Object.prototype.hasOwnProperty,jt=Object.prototype.propertyIsEnumerable;var tt=(e,t,n)=>t in e?ve(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,v=(e,t)=>{for(var n in t||(t={}))nt.call(t,n)&&tt(e,n,t[n]);if(et)for(var n of et(t))jt.call(t,n)&&tt(e,n,t[n]);return e},j=(e,t)=>Kt(e,$t(t));var Wt=(e,t)=>{for(var n in t)ve(e,n,{get:t[n],enumerable:!0})},ot=(e,t,n,c)=>{if(t&&typeof t=="object"||typeof t=="function")for(let d of Ut(t))!nt.call(e,d)&&d!==n&&ve(e,d,{get:()=>t[d],enumerable:!(c=Gt(t,d))||c.enumerable});return e};var Ht=(e,t,n)=>(n=e!=null?Mt(Ft(e)):{},ot(t||!e||!e.__esModule?ve(n,"default",{value:e,enumerable:!0}):n,e)),zt=e=>ot(ve({},"__esModule",{value:!0}),e);var yo={};Wt(yo,{BLOCK_ALIGNS:()=>mn,BLOCK_EMPHASES:()=>vn,BLOCK_FITS:()=>xn,BLOCK_GAPS:()=>fn,BLOCK_GRID_COLUMNS:()=>Cn,BLOCK_HEADING_LEVELS:()=>In,BLOCK_JUSTIFIES:()=>yn,BLOCK_RATIOS:()=>En,BLOCK_SIZES:()=>hn,BLOCK_TEXT_ALIGNS:()=>wn,BLOCK_TONES:()=>bn,BLOCK_WEIGHTS:()=>Sn,LEGACY_SESSION_COOKIE_NAME:()=>we,MAX_BLOCK_ARMS:()=>_n,MAX_BLOCK_CHILDREN:()=>An,MAX_BLOCK_DEPTH:()=>kn,MAX_BLOCK_NODES:()=>Tn,MAX_BLOCK_TEXT_LEN:()=>Rn,SNAPSHOT_STORAGE_KEY_PREFIX:()=>oe,armOfResult:()=>Le,attachMicroSignalDetectors:()=>ht,baselineResultFor:()=>fe,baselineSlots:()=>pt,deriveSessionSegment:()=>je,detectDeviceClass:()=>le,detectTimeOfDay:()=>pe,detectTrafficSource:()=>de,grantConsent:()=>xt,init:()=>Bt,isDoNotTrackEnabled:()=>Ce,locatorFromElement:()=>Ke,readSnapshot:()=>me,referrerDomainFromReferer:()=>ue,renderPrePaintScript:()=>gt,sanitizePageUrl:()=>Qe,sessionCookieName:()=>ae,toWireSlot:()=>Ee,writeSnapshot:()=>ye});module.exports=zt(yo);function ke(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}try{if(typeof crypto!="undefined"&&typeof crypto.getRandomValues=="function"){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t="";for(let n=0;n<16;n++)t+=e[n].toString(16).padStart(2,"0"),(n===3||n===5||n===7||n===9)&&(t+="-");return t}}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function ne(e){return e?`_${e.slice(0,12)}`:""}var we="_snt_uid";function ae(e){return`${we}${ne(e)}`}var qt="_snt_uid",Qt=365,Ae="_snt_uid";function Jt(){return ke()}function rt(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function Xt(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(c){}}function $e(e){try{return localStorage.getItem(e)}catch(t){return null}}function st(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function it(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function Vt(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function Yt(e){try{sessionStorage.removeItem(e)}catch(t){}}function Zt(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function en(e){try{localStorage.removeItem(e)}catch(t){}}function tn(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var nn={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function _e(e){var m,S,E,w,G,U,_;if(typeof window=="undefined")return nn;let t=ne(e==null?void 0:e.apiKey),n=(m=e==null?void 0:e.cookieName)!=null?m:ae(e==null?void 0:e.apiKey),c=`${Ae}${t}`,d=`${Ae}_tomb${t}`,i=((S=e==null?void 0:e.cookieTTLDays)!=null?S:Qt)*24*60*60,l=C=>C&&C.length>0?C:null,u=()=>{var C,P;return t&&!(e!=null&&e.cookieName)&&$e(d)===null?(P=(C=l(rt(qt)))!=null?C:l($e(Ae)))!=null?P:l(it(Ae)):null},r=(_=(U=(G=(w=(E=l(rt(n)))!=null?E:l($e(c)))!=null?w:l(it(c)))!=null?G:u())!=null?U:l(e==null?void 0:e.ssrSessionId))!=null?_:Jt();Xt(n,r,i);let o=st(c,r),s=Zt(n),f=o?!1:Vt(c,r),p=!o&&!s&&!f;return{getSessionId:()=>r,isEphemeral:()=>p,destroy:()=>{r=null,tn(n),en(c),Yt(c),t&&!(e!=null&&e.cookieName)&&st(d,"1")}}}function V(e){return Math.min(6e4,1e3*2**Math.min(e,6))}function ce(e){if(e.ok===!0)return"delivered";let{status:t}=e;return typeof t!="number"?"retry":t>=200&&t<300?"delivered":t>=400&&t<500&&t!==429?"dropped":"retry"}function Re(e,t){try{let n=localStorage.getItem(e);if(!n)return[];let c=JSON.parse(n);return Array.isArray(c)?(localStorage.removeItem(e),c.slice(-t)):[]}catch(n){return[]}}function Y(e,t,n){try{let c=(()=>{try{let a=localStorage.getItem(n);if(!a)return[];let i=JSON.parse(a);return Array.isArray(i)?i:[]}catch(a){return[]}})(),d=new Map;for(let a of c)d.set(a.id,a);for(let a of e)d.set(a.id,a);localStorage.setItem(n,JSON.stringify([...d.values()].slice(-t)))}catch(c){}}function Oe(e,t){try{let n=localStorage.getItem(t);if(!n)return;let c=JSON.parse(n);if(!Array.isArray(c))return;let d=new Set(e),a=c.filter(i=>!d.has(i.id));if(a.length===c.length)return;a.length===0?localStorage.removeItem(t):localStorage.setItem(t,JSON.stringify(a))}catch(n){}}var on=500,rn=56*1024;function Ue(e){return`_snt_retry_${e.slice(0,12)}`}var sn={push:()=>{},flush:()=>{},destroy:()=>{}};function at(e){var Z,B,re;if(typeof window=="undefined")return sn;let t=(Z=e.flushIntervalMs)!=null?Z:5e3,n=(B=e.maxBatchSize)!=null?B:20,c=(re=e.maxRetrySize)!=null?re:100,d=e.ingestUrl,a=e.apiKey,i=Ue(a),l=[],u=new Set,r=[],o=h=>{for(let T of h)s.delete(T),!u.has(T)&&(u.add(T),r.push(T));for(;r.length>on;){let T=r.shift();T&&u.delete(T)}Oe(h,i)},s=new Set,f=()=>{for(;l.length>c;){let h=l.shift();h&&s.delete(h.id)}},p=h=>{u.has(h.id)||s.has(h.id)||(s.add(h.id),l.push(h),f())},m=h=>{for(let T of h)u.has(T.id)||(s.add(T.id),l.push(T));f()},S=Re(i,c);for(let h of S)p(h);let E=0,w=0,G=(h,T=!0)=>{if(h.length===0)return;let H=JSON.stringify(h),ee=h.map(q=>q.id),F;try{F=fetch(d,{method:"POST",keepalive:!0,body:H,headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`}})}catch(q){Y(h,c,i),m(h),w++,E=Date.now()+V(w);return}let he=q=>{if(ce(q)!=="retry"){if(!q.ok&&T){let se=h.filter(Q=>Q.eventType!=="pageview");if(se.length>0&&se.length<h.length){o(h.filter(Q=>Q.eventType==="pageview").map(Q=>Q.id)),G(se,!1);return}}o(ee),w=0,E=0;return}Y(h,c,i),m(h),w++,E=Date.now()+V(w)};F instanceof Promise?F.then(he).catch(()=>{Y(h,c,i),m(h),w++,E=Date.now()+V(w)}):he(F)},U=typeof TextEncoder!="undefined"?new TextEncoder:null,_=h=>U?U.encode(h).length:h.length,C=h=>{let T=[],H=2;for(let ee of h){let F=_(JSON.stringify(ee))+1;if(T.length>0&&H+F>rn||T.length>=n)break;T.push(ee),H+=F}return T},P=()=>{try{if(Date.now()<E)return;for(;l.length>0&&!(Date.now()<E);){let h=l.filter(H=>!u.has(H.id));if(l.length=0,h.length===0)break;let T=C(h);if(T.length===0)break;T.length<h.length&&l.push(...h.slice(T.length)),G(T)}}catch(h){}},b=!0,O=null;O=setInterval(()=>{b&&P()},t);let D=()=>{document.visibilityState==="hidden"&&P()},W=()=>{P()};return document.addEventListener("visibilitychange",D),window.addEventListener("pagehide",W),{push(h){p(h),l.length>=n&&P()},flush:P,destroy(){b=!1,O!==null&&(clearInterval(O),O=null),document.removeEventListener("visibilitychange",D),window.removeEventListener("pagehide",W),P()}}}var an=200;function Fe(e){return`_snt_goal_retry_${e.slice(0,12)}`}var cn={send:()=>{},flush:()=>{},destroy:()=>{}};function ct(e){var _,C,P;if(typeof window=="undefined")return cn;let t=(_=e.flushIntervalMs)!=null?_:5e3,n=(C=e.maxRetrySize)!=null?C:100,c=(P=e.maxPerFlush)!=null?P:5,d=Fe(e.apiKey),a=[],i=new Set,l=new Set,u=[],r=0,o=0,s=!1,f=b=>{for(i.delete(b.id),l.has(b.id)||(l.add(b.id),u.push(b.id));u.length>an;){let O=u.shift();O&&l.delete(O)}Oe([b.id],d)},p=b=>{Y([b],n,d),!l.has(b.id)&&!i.has(b.id)&&(i.add(b.id),a.push(b)),Date.now()>=r&&(o++,r=Date.now()+V(o))},m=b=>{let O;try{O=fetch(e.url,{method:"POST",keepalive:!0,body:b.body,headers:e.headers})}catch(W){p(b);return}let D=W=>{var B;let Z=ce(W);if(Z==="retry"){p(b);return}Z==="dropped"&&((B=e.onDrop)==null||B.call(e,b,W.status)),f(b),o=0,r=0};O instanceof Promise?O.then(D).catch(()=>p(b)):D(O)},S=()=>{try{if(s||Date.now()<r)return;let b=0;for(;a.length>0&&b<c&&!(Date.now()<r);){let O=a.shift();i.delete(O.id),!l.has(O.id)&&(b++,m(O))}}catch(b){}},E=Re(d,n);for(let b of E)i.has(b.id)||(i.add(b.id),a.push(b));E.length>0&&Y(E,n,d);let w=setInterval(S,t),G=()=>{document.visibilityState==="hidden"&&S()},U=()=>S();return document.addEventListener("visibilitychange",G),window.addEventListener("pagehide",U),{send(b){if(!s&&!(l.has(b.id)||i.has(b.id))){if(Date.now()<r){Y([b],n,d),i.add(b.id),a.push(b);return}m(b)}},flush:S,destroy(){clearInterval(w),document.removeEventListener("visibilitychange",G),window.removeEventListener("pagehide",U),S(),s=!0}}}var ln=1800*1e3;function Ne(e,t){return`${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function lt(e=ln,t){let n=new Map,c=`_snt_asgn${ne(t)}_`,d=(r,o)=>`${c}${encodeURIComponent(r)}:${encodeURIComponent(o)}`,a=r=>{let o=r.slice(c.length),s=o.indexOf(":");if(s<0)return null;try{return{componentId:decodeURIComponent(o.slice(0,s)),segment:decodeURIComponent(o.slice(s+1))}}catch(f){return null}},i=()=>{try{let r=[];for(let o=0;o<localStorage.length;o++){let s=localStorage.key(o);s!=null&&s.startsWith(c)&&r.push(s)}return r}catch(r){return[]}},l=r=>r.assignedAt+(r.ttlMs&&r.ttlMs>0?r.ttlMs:e)<Date.now();return typeof window!="undefined"&&(()=>{for(let r of i())try{let o=localStorage.getItem(r);if(!o)continue;let s=JSON.parse(o);if(l(s)){localStorage.removeItem(r);continue}let f=a(r);if(!f)continue;n.set(Ne(f.componentId,f.segment),s)}catch(o){}})(),{get(r,o){let s=n.get(Ne(r,o));return s?l(s)?(n.delete(Ne(r,o)),null):s:null},set(r,o,s){let f=Ne(r,o);n.set(f,s);try{localStorage.setItem(d(r,o),JSON.stringify(s))}catch(p){}},clear(){n.clear();for(let r of i())try{localStorage.removeItem(r)}catch(o){}}}}var dt=["GPTBot","ChatGPT-User","OAI-SearchBot","ClaudeBot","Claude-User","Claude-SearchBot","PerplexityBot","Perplexity-User","Google-Extended","Applebot-Extended","Meta-ExternalAgent","Bytespider","CCBot","Amazonbot","cohere-ai","Diffbot"];function Pe(e){return ut(e)!==null}function ut(e){var n;if(!e)return null;let t=e.toLowerCase();return(n=dt.find(c=>t.includes(c.toLowerCase())))!=null?n:null}function le(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function de(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(d){}let c=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(c)?"search":/(^|\.)(twitter\.com|x\.com|facebook\.com|linkedin\.com|reddit\.com|t\.co)$/.test(c)?"social":"referral"}catch(n){return"direct"}}function ue(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function pe(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function je(e){let t=dn("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function dn(e,t){var a,i,l,u,r,o,s;let n=(i=(a=t==null?void 0:t.userAgent)==null?void 0:a.trim())!=null?i:"",c=(u=(l=t==null?void 0:t.referer)==null?void 0:l.trim())!=null?u:"",d=(r=t==null?void 0:t.now)!=null?r:new Date;return{sessionId:e,ephemeral:!1,utmParams:(o=t==null?void 0:t.utmParams)!=null?o:{},deviceClass:n?le(n):"desktop",trafficSource:c?de(c,t==null?void 0:t.appOrigin):"direct",referrerDomain:ue(c),timeOfDay:pe(d),dayOfWeek:(s=["sun","mon","tue","wed","thu","fri","sat"][d.getDay()])!=null?s:"sun",automation:(t==null?void 0:t.webdriver)===!0||Pe(n)}}var ge=require("@sentientui/policy");function Ee(e){return v(v(v({id:e.id},e.arms?{arms:[...e.arms]}:{}),e.dims?{dims:Object.fromEntries(Object.entries(e.dims).map(([t,n])=>[t,[...n]]))}:{}),e.baseline!==void 0?{baseline:e.baseline}:{})}function fe(e){let t=Ee(e);return(0,ge.slotResultFor)(t,(0,ge.slotBaselineArm)(t))}function pt(e){let t={};for(let n of e)t[n.id]=fe(n);return t}function Le(e){return typeof e=="string"?e:(0,ge.canonicalArm)(e)}var oe="_snt_snap:",un=["low","medium","high"];function me(e){try{let t=localStorage.getItem(oe+e);if(!t)return null;let n=JSON.parse(t);return!n||typeof n!="object"||n.v!==1||typeof n.persona!="string"||typeof n.band!="string"||!un.includes(n.band)||typeof n.slots!="object"||n.slots===null||Array.isArray(n.slots)||!(n.layoutOrder===null||Array.isArray(n.layoutOrder))||typeof n.savedAt!="number"||!(n.slotConfig===void 0||typeof n.slotConfig=="object"&&n.slotConfig!==null&&!Array.isArray(n.slotConfig))?null:n}catch(t){return null}}function ye(e,t){try{localStorage.setItem(oe+e,JSON.stringify(t))}catch(n){}}function gt(e){return"(function(){try{var r=localStorage.getItem("+JSON.stringify(oe+e).replace(/</g,"\\u003c")+');if(!r)return;var s=JSON.parse(r);if(!s||s.v!==1||typeof s.persona!=="string"||typeof s.band!=="string")return;var d=document.documentElement;if(d.hasAttribute("data-sentient-persona"))return;d.setAttribute("data-sentient-persona",s.persona);d.setAttribute("data-sentient-confidence",s.band);}catch(e){}})();'}var He=require("@sentientui/policy");var Be=require("@sentientui/policy");var ft="[sentient] No API key configured \u2014 nothing is being learned. Set NEXT_PUBLIC_SENTIENT_API_KEY or pass localMode: true for local development.",pn="[sentient] Local mode \u2014 decisions are simulated on-device and nothing is sent over the network. Add an API key to learn from real traffic.",mt=!1,De=!1;function gn(){var e;try{return(e=new URLSearchParams(window.location.search).get("sentient_persona"))!=null?e:void 0}catch(t){return}}function yt(e){var r;let t=_e({ssrSessionId:e.ssrSessionId,apiKey:e.apiKey}),n=(r=t.getSessionId())!=null?r:"local",c=gn(),d=import("@sentientui/core/local").then(o=>{let s=o;return s.LOCAL_ENGINE_AVAILABLE?(mt||(mt=!0,console.info(pn)),s):(De||(De=!0,console.error(ft)),null)}).catch(()=>(De||(De=!0,console.error(ft)),null)),a=null,i={low:.15,medium:.5,high:.85},l=(()=>{var s;if(e.initialPersona)return v({},e.initialPersona);let o=me(e.apiKey||"local");return o?{persona:o.persona,confidence:(s=i[o.band])!=null?s:.15}:null})();function u(o){let s=document.documentElement;s.dataset.sentientPersona===void 0&&(s.dataset.sentientPersona=o.persona,s.dataset.sentientConfidence=(0,Be.confidenceBand)(o.confidence))}return{isLocal:!0,async decide(o){var p,m,S;let s=await d;if(!s)return null;let f=s.createLocalEngine({sessionId:n,forcedPersona:c}).decide(o);return a=j(v({},f),{layoutOrder:(m=(p=f.layoutOrder)!=null?p:a==null?void 0:a.layoutOrder)!=null?m:null,slots:v(v({},(S=a==null?void 0:a.slots)!=null?S:{}),f.slots)}),ye(e.apiKey||"local",{v:1,persona:a.persona,band:(0,Be.confidenceBand)(a.confidence),slots:a.slots,layoutOrder:a.layoutOrder,savedAt:Date.now()}),u(f),f},getSlotResult(o){var s,f,p;return(p=(f=a==null?void 0:a.slots[o])!=null?f:(s=e.initialSlots)==null?void 0:s[o])!=null?p:null},getPersona(){let o=a!=null?a:l;return o?{persona:o.persona,confidence:o.confidence,band:(0,Be.confidenceBand)(o.confidence)}:null},async assign(o,s){var m;let f=await d;return!f||!s||s.length===0?s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null:{variantId:(m=f.createLocalEngine({sessionId:n,forcedPersona:c}).decide({components:[{id:o,variantIds:s}]}).assignments[o])!=null?m:s[0],assignmentTtlMs:0}},track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>t.destroy()}}var fn=["none","sm","md","lg"],mn=["start","center","end","stretch"],yn=["start","center","end","between"],hn=["sm","md","lg"],Sn=["normal","medium","bold"],bn=["default","muted","accent"],vn=["primary","secondary","ghost"],wn=["left","center","right"],En=["auto","square","landscape","wide"],xn=["cover","contain"],Cn=[2,3,4],In=[2,3,4],Tn=64,kn=5,An=12,_n=4,Rn=500;function ht(e,t,n,c){let d=[];{let l=!1,u=[],r=()=>{if(l)return;let o=Date.now();for(u.push(o);u.length>0&&o-u[0]>500;)u.shift();u.length>=3&&(l=!0,e("rage_click"))};t.addEventListener("click",r),d.push(()=>t.removeEventListener("click",r))}{let a=!1,i=l=>{if(a||!(l.target instanceof Node)||!t.contains(l.target)&&t!==l.target)return;a=!0;let u=typeof window!="undefined"?window.getSelection():null,r=u?u.toString().length:0;e("text_copy",{selectionLength:r})};document.addEventListener("copy",i),d.push(()=>document.removeEventListener("copy",i))}{let a=!1,i=!1,l=null,u=()=>{l!==null&&(clearTimeout(l),l=null)},r=()=>{a||!i||(u(),l=setTimeout(()=>{!a&&i&&(a=!0,e("scroll_hesitation"))},3e3))},o=()=>{u(),r()},s=p=>{for(let m of p)i=m.intersectionRatio>.3,i?r():u()},f=new IntersectionObserver(s,{threshold:[.3]});f.observe(t),window.addEventListener("scroll",o,{passive:!0}),d.push(()=>{f.disconnect(),window.removeEventListener("scroll",o),u()})}if((c==null?void 0:c.tabLoss)!==!1){let a=!1,i=n!=null?n:Date.now(),l=()=>{if(a||document.visibilityState!=="hidden")return;let u=Date.now()-i;u<15e3&&(a=!0,e("tab_loss",{timeOnPage:u}))};document.addEventListener("visibilitychange",l),d.push(()=>document.removeEventListener("visibilitychange",l))}return()=>{for(let a of d)a()}}var St="https://api.sentient-ui.com/v1/events",K=new Map,bt=null;function vt(e,t){let n=K.get(e);n&&n.upgrade&&(n.reinit=t)}function On(e){return"value"in e||"currency"in e||"externalId"in e||"metadata"in e||"weight"in e||"stepIndex"in e}var Nn=3;function We(){return ke()}function Me(){var e;if(typeof window!="undefined")return((e=window.location)==null?void 0:e.pathname)||void 0}function Pn(){let e=new WeakMap,t=new Map,n=!1,c=(l,u,r)=>{let o=l.get(u);return r===null?o?!0:(l.set(u,new Set),!1):o?o.has(r)?!0:(o.add(r),!1):(l.set(u,new Set([r])),!1)},d=typeof window!="undefined"&&"event"in window,a=()=>{if(!d)return;let l=window.event;return typeof Event=="function"&&l instanceof Event?l:void 0},i=()=>{if(d){Promise.resolve().then(()=>{n=!1,t.clear()});return}let l=!1,u=()=>{l||(l=!0,n=!1,t.clear())};if(setTimeout(u,0),typeof MessageChannel=="function"){let r=new MessageChannel;r.port1.onmessage=()=>{r.port1.close(),r.port2.close(),u()},r.port2.postMessage(0)}};return{firedBefore(l,u){let r=a();if(r){let s=e.get(r);return s||(s=new Map,e.set(r,s)),c(s,l,u)}let o=c(t,l,u);return!o&&!n&&(n=!0,i()),o}}}var wt=new Set;function Ln(e,t,n){let c=typeof window=="undefined"?null:window.history;if(!c)return()=>{};let d=!1,a,i=()=>{if(d)return;let r=Me();!r||r===a||(a=r,e.track({projectId:t,componentId:"__page__",eventType:"pageview",payload:{}}),n(`${t}:${r}`))},l=[];for(let r of["pushState","replaceState"]){let o=c[r],s=function(...f){let p=o.apply(this,f);return i(),p};c[r]=s,l.push([r,o,s])}window.addEventListener("popstate",i);let u=Me();return u&&wt.has(`${t}:${u}`)?a=u:i(),()=>{if(!d){d=!0,window.removeEventListener("popstate",i);for(let[r,o,s]of l)c[r]===s&&(c[r]=o)}}}var xe={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>{}};function Dn(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,c]of t)n.startsWith("utm_")&&(e[n]=c);return e}catch(e){return{}}}function Et(e){return e.replace(/\/events\/?$/,"")}function Ce(){return typeof navigator!="undefined"&&navigator.globalPrivacyControl===!0?!0:[typeof navigator!="undefined"?navigator.doNotTrack:void 0,typeof window!="undefined"?window.doNotTrack:void 0,typeof navigator!="undefined"?navigator.msDoNotTrack:void 0].some(t=>t==="1"||t==="yes")}function xt(e){var u;if(typeof window=="undefined")return;let t=e!=null?e:bt;if(!t){console.warn("[sentient] grantConsent() called before init()");return}let n=K.get(t);if(!n){console.warn("[sentient] grantConsent() called before init()");return}let{config:c,upgrade:d,reinit:a}=n;if(!d){n.upgradeBlockedReason&&console.warn(n.upgradeBlockedReason);return}if(c.respectDoNotTrack!==!1&&Ce())return;let i=(a!=null?a:qe)(j(v({},c),{consent:!0}));d(i);let l=(u=K.get(t))==null?void 0:u.dispose;K.set(t,{config:j(v({},c),{consent:!0}),upgrade:null,dispose:l})}function Bn(e){var r;let t=e.preConsentBehavior==="statistical_winner",n=Et((r=e.ingestUrl)!=null?r:St),c={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},d=new Map,a=new Map,i={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),assign(o,s,f){if(!t)return Promise.resolve(null);let p=d.get(o);return p?Promise.resolve(p):ze(a,o,async()=>{try{let m=new URLSearchParams({componentId:o});for(let G of s!=null?s:[])m.append("variantIds[]",G);let S=await fetch(`${n}/winner?${m.toString()}`,{headers:c});if(!S.ok)return s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null;let w={variantId:(await S.json()).variantId,assignmentTtlMs:0};return d.set(o,w),w}catch(m){return s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}})},decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>{}},l={track:o=>i.track(o),goal:((o,s,f,p)=>i.goal(o,s,f,p)),componentGoal:(o,s,f)=>i.componentGoal(o,s,f),identify:o=>i.identify(o),getAssignment:(o,s)=>i.getAssignment(o,s),assign:(o,s,f,p)=>i.assign(o,s,f,p),decide:o=>i.decide(o),getSlotResult:o=>i.getSlotResult(o),getPersona:()=>i.getPersona(),fetchWeights:()=>i.fetchWeights(),getGraph:()=>i.getGraph(),dispose:()=>i.dispose(),destroy:()=>i.destroy()};function u(o){i=o}return{proxy:l,setInner:u}}function ze(e,t,n){let c=e.get(t);if(c)return c;let d=(async()=>{try{return await n()}finally{e.delete(t)}})();return e.set(t,d),d}function qe(e){var T,H,ee,F,he,q,se,Q,Ve;if(typeof window=="undefined")return xe;bt=e.apiKey||"local";let t=K.get(e.apiKey||"local");if(t!=null&&t.dispose)try{t.dispose()}catch(g){}let n=e.respectDoNotTrack!==!1&&Ce(),c=e.consent===!1||n,d=typeof e.apiKey=="string"&&e.apiKey.startsWith("pk_");if(e.localMode===!0||!d&&e.localMode!==!1)return K.set(e.apiKey||"local",{config:e,upgrade:null,upgradeBlockedReason:"[sentient] grantConsent(): this client is keyless/local \u2014 there is no hosted client to upgrade to. Configure a pk_ API key to enable tracking."}),c?xe:yt(e);if(c){if(!e.apiKey||!e.apiKey.startsWith("pk_"))return e.preConsentBehavior==="statistical_winner"&&console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),K.set(e.apiKey||"local",{config:e,upgrade:null,upgradeBlockedReason:"[sentient] grantConsent(): the client was initialized with an invalid apiKey (expected a pk_ public key) \u2014 consent cannot enable tracking."}),xe;let{proxy:g,setInner:y}=Bn(e);return K.set(e.apiKey,{config:e,upgrade:n?null:y}),g}if(!e.apiKey||!e.apiKey.startsWith("pk_"))return console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),xe;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),xe;let a=(T=e.ingestUrl)!=null?T:St,i=Date.now(),l=_e({ssrSessionId:e.ssrSessionId,apiKey:e.apiKey}),u=lt(void 0,e.apiKey),r=at({ingestUrl:a,apiKey:e.apiKey}),o=Et(a),s={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},f=new Set,p=ct({url:`${o}/goals`,apiKey:e.apiKey,headers:s,onDrop:(g,y)=>{if(!e.debug){if(f.has(y))return;f.add(y)}console.warn(`[sentient] goal dropped (HTTP ${y}) \u2014 this will not be retried. `+(y===400?"The session was not found: call init() and let the session upsert complete before firing goals.":y===401||y===403?"Check the API key and that this origin is on the project allowlist.":"See the response status for the cause."),g)}}),m=le((H=navigator.userAgent)!=null?H:""),S=window.location.origin,E=de((ee=document.referrer)!=null?ee:"",S),w=(F=e.sessionSegment)!=null?F:`${m}:${E}`,G=new Map,U=new Map,_=new Map,C=null,P=g=>{for(let y of g)_.has(y.id)||_.set(y.id,fe(y))};if(e.initialSlots)for(let[g,y]of Object.entries(e.initialSlots))_.set(g,y);let b=me(e.apiKey);if(b)for(let[g,y]of Object.entries(b.slots))_.has(g)||_.set(g,y);let O={low:.15,medium:.5,high:.85};if(e.initialPersona)C=v({},e.initialPersona);else{let g=document.documentElement.dataset;g.sentientPersona?C={persona:g.sentientPersona,confidence:(q=O[(he=g.sentientConfidence)!=null?he:"low"])!=null?q:.15}:b&&(C={persona:b.persona,confidence:(se=O[b.band])!=null?se:.15})}if(e.initialAssignments)for(let[g,y]of Object.entries(e.initialAssignments))u.set(g,w,{variantId:y,assignedAt:Date.now(),segment:w,confidence:1});let D=Promise.resolve(),W=l.getSessionId();if(W){let g=ue((Q=document.referrer)!=null?Q:""),y=v(v(v({sessionId:W,deviceClass:m,trafficSource:E,referrerDomain:g,utmParams:Dn(),timeOfDay:pe(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:l.isEphemeral(),automation:typeof navigator!="undefined"&&navigator.webdriver===!0||Pe((Ve=navigator.userAgent)!=null?Ve:"")},e.userId?{userId:e.userId}:{}),e.persona?{persona:e.persona}:{}),e.country?{country:e.country}:{}),x=async()=>{for(let A=0;;A++){try{let R=await fetch(`${o}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(y),headers:s});if(R.status===402){console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentient-ui.com/pricing");return}if(R.ok||ce(R)==="dropped")return}catch(R){}if(A>=Nn){console.warn("[SentientUI] Could not register the session after retries. Conversions in this visit may not be recorded.");return}await new Promise(R=>setTimeout(R,V(A+1)))}};try{D=x()}catch(A){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:r});let Z=Pn(),B=null,re=!1,h={goal(g,y={},x=1,A=0){var Se,be,ie,k,z,Te,N;let R=l.getSessionId();if(!R)return;let I=On(y)?y:{metadata:y},M=[g,(Se=I.externalId)!=null?Se:"",(be=I.stepIndex)!=null?be:A,(ie=I.weight)!=null?ie:x].join("\0"),$=I.value!==void 0?`${I.value}\0${(k=I.currency)!=null?k:""}`:null;if(Z.firedBefore(M,$)){e.debug&&console.log(`[sentient] goal("${g}") already recorded for this action \u2014 not sent twice`);return}let L=We(),J={sessionId:R,name:g,metadata:(z=I.metadata)!=null?z:{},weight:(Te=I.weight)!=null?Te:x,stepIndex:(N=I.stepIndex)!=null?N:A,goalId:L,value:I.value,currency:I.currency,externalId:I.externalId};e.debug&&console.log("[sentient] goal",J);let te={id:L,body:JSON.stringify(J)};D.then(()=>p.send(te))},componentGoal(g,y,x){var L,J,te;let A=l.getSessionId();if(!A)return;let R=u.get(g,w),I=R?null:(L=_.get(g))!=null?L:null;if(!R&&I===null){e.debug&&console.warn(`[sentient] componentGoal("${g}"): no assignment or slot decision yet \u2014 render its <Adaptive>/adaptive hook or call assign()/decide() before recording a goal.`);return}let M=R?R.variantId:Le(I),$={id:We(),sessionId:A,projectId:e.apiKey,componentId:g,variantId:M,eventType:"goal_achieved",goalType:y,payload:v({reward:(J=x==null?void 0:x.reward)!=null?J:1,goalValue:x==null?void 0:x.value,currency:x==null?void 0:x.currency},(te=x==null?void 0:x.metadata)!=null?te:{}),timestamp:Date.now(),timeInSession:Date.now()-i,path:Me()};e.debug&&console.log("[sentient] componentGoal",$),D.then(()=>r.push($))},identify(g){let y=l.getSessionId();y&&D.then(()=>{fetch(`${o}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,userId:g,ephemeral:l.isEphemeral()}),headers:s}).catch(()=>{})})},track(g){let y=l.getSessionId();if(!y)return;let x=j(v({path:Me()},g),{id:We(),sessionId:y,timestamp:Date.now(),timeInSession:Date.now()-i});e.debug&&console.log("[sentient] track",x),D.then(()=>r.push(x))},getAssignment(g,y){return u.get(g,y)},async assign(g,y,x,A){let R=l.getSessionId();if(!R)return null;let I=u.get(g,w);if(I&&(y!=null&&y.length||I.content!==void 0)){let M=I.ttlMs&&I.ttlMs>0?Math.max(0,I.assignedAt+I.ttlMs-Date.now()):0;return{variantId:I.variantId,assignmentTtlMs:M,content:I.content}}return ze(G,g,async()=>{await D;try{let M={sessionId:R,componentId:g,variantIds:y};A!==void 0?M.agentDataByVariant=A:x!==void 0&&(M.agentData=x);let $=await fetch(`${o}/assign`,{method:"POST",body:JSON.stringify(M),headers:s});if(!$.ok)return null;let L=await $.json();return u.set(g,w,v({variantId:L.variantId,assignedAt:Date.now(),segment:w,confidence:1,content:L.content},L.assignmentTtlMs&&L.assignmentTtlMs>0?{ttlMs:L.assignmentTtlMs}:{})),L}catch(M){return null}})},async decide(g){var I,M;let y=l.getSessionId();if(!y)return null;let x=(I=g.slots)!=null?I:[],A={sessionId:y};g.sections&&g.sections.length>0&&(A.sections=g.sections.map($=>({id:$}))),A.components=(M=g.components)!=null?M:[],x.length>0&&(A.slots=x.map(Ee)),g.slotsFrom==="registry"&&(A.slotsFrom="registry"),g.v&&(A.v=g.v),e.persona&&(A.persona=e.persona);let R=JSON.stringify(A);return ze(U,R,async()=>{var $,L,J,te,Se,be;await D;try{let ie=await fetch(`${o}/decide`,{method:"POST",body:R,headers:s});if(!ie.ok)return P(x),null;let k=await ie.json(),z={};for(let N of x){let X=($=k.slots)==null?void 0:$[N.id];if(X!==void 0){z[N.id]=X,_.set(N.id,X);continue}let Ye=_.get(N.id);if(Ye!==void 0)z[N.id]=Ye;else{let Ze=fe(N);z[N.id]=Ze,_.set(N.id,Ze)}}if(k.slots)for(let[N,X]of Object.entries(k.slots))N in z||(z[N]=X,_.set(N,X));let Te=C!=null&&C.persona!=="unknown";k.persona&&!(k.persona==="unknown"&&Te)?C={persona:k.persona,confidence:(L=k.confidence)!=null?L:0}:C||(C={persona:"unknown",confidence:0});for(let[N,X]of Object.entries((J=k.assignments)!=null?J:{}))u.set(N,w,{variantId:X,assignedAt:Date.now(),segment:w,confidence:1});return ye(e.apiKey,v(v({v:1,persona:C.persona,band:(0,He.confidenceBand)(C.confidence),slots:Object.fromEntries(_),layoutOrder:(te=k.layoutOrder)!=null?te:null,savedAt:Date.now()},k.slotConfig?{slotConfig:k.slotConfig}:{}),k.palette?{palette:k.palette}:{})),v(v(v(v({layoutOrder:(Se=k.layoutOrder)!=null?Se:null,assignments:(be=k.assignments)!=null?be:{},slots:z,persona:C.persona,confidence:C.confidence},k.slotConfig?{slotConfig:k.slotConfig}:{}),k.goals?{goals:k.goals}:{}),k.sectionMap?{sectionMap:k.sectionMap}:{}),k.palette?{palette:k.palette}:{})}catch(ie){return P(x),null}})},getSlotResult(g){var y;return(y=_.get(g))!=null?y:null},getPersona(){return C?{persona:C.persona,confidence:C.confidence,band:(0,He.confidenceBand)(C.confidence)}:null},async fetchWeights(){var g;try{let y=await fetch(`${o}/weights`,{headers:s});return y.ok?(g=(await y.json()).components)!=null?g:[]:[]}catch(y){return[]}},getGraph(){return{pageNodes:[],capturedAt:0}},dispose(){var g;B==null||B(),re=!0,r.destroy(),p.destroy(),((g=K.get(e.apiKey))==null?void 0:g.dispose)===h.dispose&&K.delete(e.apiKey),e.debug&&console.log("[sentient] disposed")},destroy(){var g;B==null||B(),re=!0,r.destroy(),p.destroy(),l.destroy(),u.clear(),((g=K.get(e.apiKey))==null?void 0:g.dispose)===h.dispose&&K.delete(e.apiKey);try{localStorage.removeItem(oe+e.apiKey),localStorage.removeItem(Ue(e.apiKey)),localStorage.removeItem(Fe(e.apiKey))}catch(y){}e.debug&&console.log("[sentient] destroyed")}};if(K.set(e.apiKey,{config:e,upgrade:null,dispose:h.dispose}),B=Ln(h,e.apiKey,g=>{D.then(()=>{re||wt.add(g)})}),e.debug){let g=window;g.__sentient&&(g.__sentient.client=h)}return h}var Ct="_snt_graph_edges",Mn={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function Kn(e){var t;return(t=Mn[e])!=null?t:[]}function Gn(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function $n(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var Un=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function Fn(e){return Un.has(e)?e:"generic"}function Qe(e){try{let t=new URL(e);return`${t.origin}${t.pathname}`}catch(t){return"/"}}function jn(e,t,n){let c=`${e}:${t}:${n.join(",")}`,d=5381;for(let a=0;a<c.length;a++)d=(d<<5)+d+c.charCodeAt(a)&4294967295;return(d>>>0).toString(16).padStart(8,"0")}function It(e){let t=new Map,n=new Map,c=`_snt_graph_nodes${ne(e==null?void 0:e.apiKey)}`,d=()=>{typeof window!="undefined"&&$n(c,[...t.values()])};if(typeof window!="undefined"){let a=Gn(c,[]);for(let i of a)t.set(i.componentId,i);try{localStorage.removeItem(Ct)}catch(i){}}return{addPageNode(a){t.set(a.componentId,a),d()},addStructuralEdge(a){let i=`${a.fromComponentId}->${a.toComponentId}`;n.set(i,a)},syncOnce(){var i,l;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let a=[...t.values()];if(a.length!==0)try{let u=new Map;for(let p of a){let m=(i=u.get(p.semanticType))!=null?i:[];m.push(p),u.set(p.semanticType,m)}let r=[],o=new Set;for(let p of a)for(let m of Kn(p.semanticType)){let S=(l=u.get(m))!=null?l:[];for(let E of S){if(E.componentId===p.componentId)continue;let w=`semantic:${p.componentId}->${E.componentId}`;o.has(w)||(o.add(w),r.push({fromComponentId:p.componentId,toComponentId:E.componentId,type:"semantic",weight:.4,confidence:.9}))}}let s=new Set(a.map(p=>p.componentId));for(let p of n.values()){if(!s.has(p.fromComponentId)||!s.has(p.toComponentId))continue;let m=`structural:${p.fromComponentId}->${p.toComponentId}`;o.has(m)||(o.add(m),r.push({fromComponentId:p.fromComponentId,toComponentId:p.toComponentId,type:"structural",weight:p.weight,confidence:1}))}let f=j(v(v({pageUrl:Qe(window.location.href)},e.sessionId?{sessionId:e.sessionId}:{}),e.projectId?{projectId:e.projectId}:{}),{nodes:a.map(p=>{let m=Fn(p.semanticType);return{componentId:p.componentId,semanticType:m,answers:p.answers,contentHash:jn(p.componentId,m,p.answers),prominenceScore:p.prominenceScore,depthInPage:p.depth}}),edges:r});fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:v({"Content-Type":"application/json"},e.apiKey?{Authorization:`Bearer ${e.apiKey}`}:{}),body:JSON.stringify(f)}).catch(()=>{})}catch(u){}},snapshot(){return{pageNodes:[...t.values()],capturedAt:Date.now()}},destroy(){if(typeof window!="undefined")try{localStorage.removeItem(c),localStorage.removeItem(Ct)}catch(a){}}}}var Wn=["data-testid","data-test","data-id","data-name","data-cy"];function Je(e){var t;return((t=e.textContent)!=null?t:"").replace(/\s+/g," ").trim()}function Hn(e){return{tag:e.tagName.toLowerCase(),text:Je(e).slice(0,40)}}function Tt(e){return e.replace(/["\\\]]/g,"\\$&")}function Ie(e,t){try{return e.querySelectorAll(t).length===1}catch(n){return!1}}function kt(e,t){var i;let n=e.tagName.toLowerCase();if(!n)return null;let c=((i=e.getAttribute("class"))!=null?i:"").split(/\s+/).filter(l=>/^[a-zA-Z][\w-]*$/.test(l)),d=[n,...c.map(l=>`${n}.${l}`)];for(let l of d)if(Ie(t,l))return l;let a=e.parentElement;if(a&&a!==t){let l=kt(a,t);if(l){for(let s of d){let f=`${l} > ${s}`;if(Ie(t,f))return f}let u=Array.from(a.children).filter(s=>s.tagName.toLowerCase()===n),r=u.indexOf(e),o=u.some(s=>s!==e&&Je(s)!==Je(e));if(r>=0&&o){let s=`${l} > ${n}:nth-of-type(${r+1})`;if(Ie(t,s))return s}}}return null}function Ke(e,t){let n=Hn(e),c=e.getAttribute("id");if(c&&Ie(t,`#${Tt(c)}`))return{v:1,id:c,fingerprint:n};for(let a of Wn){let i=e.getAttribute(a);if(i&&Ie(t,`[${a}="${Tt(i)}"]`))return{v:1,dataAttr:{name:a,value:i},fingerprint:n}}let d=kt(e,t);return d?{v:1,selector:d,fingerprint:n}:null}var _t=["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"],zn={banner:"hero",navigation:"navigation",contentinfo:"footer"};function qn(e){let t=e.ariaRole?zn[e.ariaRole.toLowerCase()]:void 0;if(t)return t;if(e.tag==="nav")return"navigation";if(e.tag==="footer")return"footer";if(e.tag==="header")return"hero";let n=`${e.idClass} ${e.headingText}`.toLowerCase();return/\b(navbar|nav-bar|navigation|site-nav|main-nav|topbar|footer)\b/.test(n)?/footer/.test(n)?"footer":"navigation":/\b(hero|masthead|jumbotron)\b/i.test(e.idClass)?"hero":null}function Qn(e){return e.actionCount>=1&&e.textLength>0&&e.textLength<200?"cta":"generic"}var Jn=[["pricing",/\b(pricing|price list|per month|\/mo|subscriptions?)\b|\bplans?\b(?=[^.]{0,40}(from|start|month|year|[$€£]))/i],["faq",/\bfaq\b|frequently asked|common questions?/i],["comparison",/\b(compare|comparison|versus)\b|\bvs\./i],["social_proof",/\b(reviews?|ratings?|testimonial|brands?|galler(y|ies)|logos)\b|trusted by|loved by|case stud|what our customers say/i],["trust",/\b(insurance|warrant(y|ies)|guarantees?|certifi|accredit|security|privacy|compliance|gdpr|encrypt)\b|why choose|about us|our team/i],["cta",/\b(book|booking|reserve|appointments?|newsletter|subscribe)\b|contact us|get in touch|opening hours/i],["features",/\b(features?|benefits?|capabilit|services?|repairs?|menus?|products?)\b|how it works|our process|what we (do|offer)|what you get/i]],Xn=[["pricing",/(?:[$€£]\s?\d[\d,.]*\s*(?:\/|per\s)\s*(?:mo|month|yr|year|seat|user))|(?:\b(?:starter|basic|pro|growth|premium|enterprise)\b[^.]{0,60}[$€£]\s?\d)/i],["social_proof",/(?:★{2,})|(?:\b\d(?:\.\d)?\s*(?:out of|\/)\s*5\b)|(?:\brated\b)|(?:["“][^"”]{20,160}["”]\s*[—–-]\s*[A-Z][a-z]+)/],["trust",/\b(?:money[- ]back guarantee|free returns?|returns? within|refund(?:s)? within|encrypted|soc ?2|iso ?27001|gdpr[- ]compliant|cancel anytime)\b/i],["comparison",/\b(?:vs|versus)\b\.?[^.!?]{0,80}\b(?:compare|comparison|plans?|features?|alternative)\b|\bhow (?:we|it) compares?\b/i]],At={navigation:"navigation",footer:"navigation",hero:"hero",cta:"cta",generic:"generic"};function Vn(e){var n;let t=e.querySelector("h1, h2, h3");return((n=t==null?void 0:t.textContent)!=null?n:"").slice(0,160)}function Yn(e){var d,a;let t=qn(e);if(t)return{type:(d=At[t])!=null?d:"generic",strength:"strong"};let n=`${e.idClass} ${e.headingText}`.toLowerCase();for(let[i,l]of Jn)if(l.test(n))return{type:i,strength:"strong"};for(let[i,l]of Xn)if(l.test(e.bodyText))return{type:i,strength:"strong"};let c=Qn(e);return{type:(a=At[c])!=null?a:"generic",strength:"weak"}}function Zn(e){var c,d;let t=((c=e.textContent)!=null?c:"").replace(/\s+/g," ").trim(),n=e.getAttribute("role");return v({tag:e.tagName.toLowerCase(),idClass:`${e.id} ${String((d=e.className)!=null?d:"")}`,headingText:Vn(e),bodyText:t.slice(0,2e3),actionCount:e.querySelectorAll('a, button, [role="button"]').length,textLength:t.length},n?{ariaRole:n}:{})}function Rt(e){return Yn(Zn(e)).type}var eo=new Set(["SECTION","ARTICLE","MAIN","DIV","ASIDE"]),to="h1, h2, h3",no="[data-sentient-id], section[aria-label], article[aria-label], main[aria-label], aside[aria-label]",Ot=30,oo=1500,ro={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function Nt(e,t,n){return n<=t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function so(e){var t,n,c;try{let d=e;for(let a of Object.keys(d)){if(!a.startsWith("__reactFiber")&&!a.startsWith("__reactInternalInstance"))continue;let i=d[a],l=(c=(t=i==null?void 0:i.type)==null?void 0:t.displayName)!=null?c:(n=i==null?void 0:i.type)==null?void 0:n.name;if(l&&l.length>1)return l}}catch(d){}}function io(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}var Pt=new Set(_t);function ao(e){let t=e.getAttribute("data-sentient-type");if(t&&Pt.has(t))return t;let n=e.getAttribute("role");return n&&Pt.has(n)?n:Rt(e)}function co(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)&4294967295;return(t>>>0).toString(16).padStart(8,"0")}function lo(e){let t=[],n=e;for(;n;){let c=n.parentElement;if(!c){t.push(n.tagName.toLowerCase());break}let d=Array.prototype.indexOf.call(c.children,n);t.push(`${n.tagName.toLowerCase()}[${d}]`),n=c}return t.reverse().join("/")}function uo(e){var n;let t=(n=e.getAttribute("data-sentient-id"))!=null?n:e.getAttribute("id");return t||`${e.tagName.toLowerCase()}-${co(lo(e))}`}function po(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function Xe(e,t){var c,d,a,i;let n=e.querySelector(to);return{componentId:uo(e),semanticType:ao(e),ariaLabel:(c=e.getAttribute("aria-label"))!=null?c:void 0,headingText:(a=(d=n==null?void 0:n.textContent)==null?void 0:d.trim())!=null?a:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:po(e),reactComponentName:so(e),dataAttributes:io(e),locator:(i=Ke(e,e.ownerDocument))!=null?i:void 0}}function Lt(e){var a;let t=[],n=new Set,c="__root__",d=new Map;for(let[i,l]of e){let u=i.parentElement,r=c;for(;u;){if(e.has(u)){r=e.get(u);let s=e.get(i),f=`${r}->${s}`;!n.has(f)&&r!==s&&(n.add(f),t.push({fromComponentId:r,toComponentId:s,weight:.6}));break}u=u.parentElement}let o=(a=d.get(r))!=null?a:[];o.push(i),d.set(r,o)}for(let i of d.values()){if(i.length<2)continue;let l=i.length>Ot?i.slice(0,Ot):i;for(let u=0;u<l.length;u++)for(let r=u+1;r<l.length;r++){if(t.length>=oo)return t;let o=e.get(l[u]),s=e.get(l[r]);if(o===s)continue;let f=`${o}->${s}::sib`,p=`${s}->${o}::sib`;n.has(f)||(n.add(f),t.push({fromComponentId:o,toComponentId:s,weight:.3})),n.has(p)||(n.add(p),t.push({fromComponentId:s,toComponentId:o,weight:.3}))}}return t}function go(e){let t=[],n=new Set,c=new Map;return document.querySelectorAll("[data-sentient-id]").forEach(i=>{if(i instanceof Element&&!n.has(i)){n.add(i);let l=Xe(i,e);t.push(l),c.set(i,l.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(i=>{if(!(i instanceof Element)||n.has(i))return;let l=i.hasAttribute("aria-label"),u=i.hasAttribute("data-sentient-id");if(!l&&!u)return;n.add(i);let r=Xe(i,e);t.push(r),c.set(i,r.componentId)}),{nodes:t,edges:Lt(c),elementToId:c}}function Dt(){if(typeof window=="undefined")return ro;let e=null,t=0,n=null,c=new Map,d=u=>{try{let r=window.getComputedStyle(u),o=parseFloat(r.fontSize)||12,s=parseFloat(r.zIndex)||0,f=u.getBoundingClientRect(),p=Math.max(f.top,0),m=window.innerHeight||1,S=1/(p/m+1),E=Nt(o,12,48)*.4+S*.4+Nt(s,0,100)*.2;return Math.max(0,Math.min(1,E))}catch(r){return .5}};return{scan:()=>new Promise(u=>{let r=()=>{let{nodes:o,edges:s,elementToId:f}=go(d);c.clear();for(let[p,m]of f)c.set(p,m);u({nodes:o,edges:s,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(r,{timeout:100}):r()}catch(o){r()}}),observe:u=>{n=u;try{e=new MutationObserver(r=>{let o=[],s=new Set;for(let p of r)p.type==="childList"&&p.addedNodes.forEach(m=>{if(!(m instanceof Element))return;let S=[];eo.has(m.tagName)&&(m.hasAttribute("data-sentient-id")||m.hasAttribute("aria-label"))&&S.push(m);try{m.querySelectorAll(no).forEach(E=>S.push(E))}catch(E){}for(let E of S){if(c.has(E))continue;let w=Xe(E,d);o.push(w),s.add(w.componentId),c.set(E,w.componentId)}});if(o.length===0||!n)return;for(let p of[...c.keys()])p.isConnected||c.delete(p);let f=Lt(c).filter(p=>s.has(p.fromComponentId)||s.has(p.toComponentId));n({nodes:o,edges:f,addedAt:Date.now()})}),e.observe(document.body,{childList:!0,subtree:!0})}catch(r){}},getProminenceScore:d,destroy:()=>{if(e&&(e.disconnect(),e=null),t&&typeof cancelIdleCallback=="function")try{cancelIdleCallback(t)}catch(u){}t=0,n=null,c.clear()}}}var fo="https://api.sentient-ui.com/v1/events";function mo(e){var n;let t=c=>{try{let d=document.cookie.match(new RegExp(`(?:^|; )${c}=([^;]*)`));return d?decodeURIComponent(d[1]):void 0}catch(d){return}};return(n=e?t(ae(e)):void 0)!=null?n:t(we)}var Ge=new Map;function Bt(e){var p;let t=qe(e),n=e.respectDoNotTrack!==!1&&Ce(),c=e.consent===!1||n,d=typeof e.apiKey=="string"&&e.apiKey.startsWith("pk_"),a=e.localMode===!0||!d;if(!e.graph||a||typeof window=="undefined")return t;if(c)return n||vt(e.apiKey,m=>Bt(m)),t;let i=Ge.get(e.apiKey);if(i)try{i()}catch(m){}let l=Dt(),u=(p=e.ingestUrl)!=null?p:fo,r=It({syncUrl:u.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:mo(e.apiKey)});l.scan().then(m=>{for(let S of m.nodes)r.addPageNode({id:S.componentId,componentId:S.componentId,semanticType:S.semanticType,answers:e.captureDomText&&S.headingText?[S.headingText]:[],prominenceScore:S.prominenceScore,depth:S.depth});for(let S of m.edges)r.addStructuralEdge(S);r.syncOnce()});let o=null,s=()=>{o!==null&&clearTimeout(o),o=setTimeout(()=>{o=null,r.syncOnce()},500)};l.observe(m=>{for(let S of m.nodes)r.addPageNode({id:S.componentId,componentId:S.componentId,semanticType:S.semanticType,answers:e.captureDomText&&S.headingText?[S.headingText]:[],prominenceScore:S.prominenceScore,depth:S.depth});for(let S of m.edges)r.addStructuralEdge(S);s()});let f=()=>{o!==null&&(clearTimeout(o),o=null),l.destroy(),r.destroy(),Ge.get(e.apiKey)===f&&Ge.delete(e.apiKey)};return Ge.set(e.apiKey,f),j(v({},t),{getGraph:()=>r.snapshot(),dispose:()=>{f(),t.dispose()},destroy:()=>{f(),t.destroy()}})}0&&(module.exports={BLOCK_ALIGNS,BLOCK_EMPHASES,BLOCK_FITS,BLOCK_GAPS,BLOCK_GRID_COLUMNS,BLOCK_HEADING_LEVELS,BLOCK_JUSTIFIES,BLOCK_RATIOS,BLOCK_SIZES,BLOCK_TEXT_ALIGNS,BLOCK_TONES,BLOCK_WEIGHTS,LEGACY_SESSION_COOKIE_NAME,MAX_BLOCK_ARMS,MAX_BLOCK_CHILDREN,MAX_BLOCK_DEPTH,MAX_BLOCK_NODES,MAX_BLOCK_TEXT_LEN,SNAPSHOT_STORAGE_KEY_PREFIX,armOfResult,attachMicroSignalDetectors,baselineResultFor,baselineSlots,deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,grantConsent,init,isDoNotTrackEnabled,locatorFromElement,readSnapshot,referrerDomainFromReferer,renderPrePaintScript,sanitizePageUrl,sessionCookieName,toWireSlot,writeSnapshot});
|
|
2
2
|
//# sourceMappingURL=index-graph.js.map
|