@aglyn/plugins-marketing 1.0.0-beta.220 → 1.0.0-beta.222

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.
Files changed (106) hide show
  1. package/README.md +4 -1
  2. package/package.json +15 -15
  3. package/src/lib/components/campaign-conversions-card.js +53 -64
  4. package/src/lib/components/campaign-conversions-card.js.map +1 -1
  5. package/src/lib/components/campaign-detail-card.js +2 -1
  6. package/src/lib/components/campaign-detail-card.js.map +1 -1
  7. package/src/lib/components/campaign-edit-drawer.js +1 -1
  8. package/src/lib/components/campaign-edit-drawer.js.map +1 -1
  9. package/src/lib/components/campaign-queries.js +1 -1
  10. package/src/lib/components/campaign-queries.js.map +1 -1
  11. package/src/lib/components/campaign-reach-sections.js +1 -1
  12. package/src/lib/components/campaign-reach-sections.js.map +1 -1
  13. package/src/lib/components/campaign-report-card.js +5 -4
  14. package/src/lib/components/campaign-report-card.js.map +1 -1
  15. package/src/lib/components/campaigns-card.js +1 -1
  16. package/src/lib/components/campaigns-card.js.map +1 -1
  17. package/src/lib/components/email-compose-card.js +1 -1
  18. package/src/lib/components/email-compose-card.js.map +1 -1
  19. package/src/lib/components/email-detail.js +5 -4
  20. package/src/lib/components/email-detail.js.map +1 -1
  21. package/src/lib/components/email-template-report-card.d.ts +53 -0
  22. package/src/lib/components/email-template-report-card.js +469 -0
  23. package/src/lib/components/email-template-report-card.js.map +1 -0
  24. package/src/lib/components/emails-list-card.js +2 -2
  25. package/src/lib/components/emails-list-card.js.map +1 -1
  26. package/src/lib/components/host-experiments-card.component.js +3 -2
  27. package/src/lib/components/host-experiments-card.component.js.map +1 -1
  28. package/src/lib/components/site-runtime.js +3 -1
  29. package/src/lib/components/site-runtime.js.map +1 -1
  30. package/src/lib/declarations.server.d.ts +9 -0
  31. package/src/lib/declarations.server.js +62 -0
  32. package/src/lib/declarations.server.js.map +1 -1
  33. package/src/lib/model/campaign-container.d.ts +503 -0
  34. package/src/lib/model/campaign-container.js +498 -0
  35. package/src/lib/model/campaign-container.js.map +1 -0
  36. package/src/lib/model/campaign-conversions.d.ts +8 -1
  37. package/src/lib/model/campaign-conversions.js +11 -0
  38. package/src/lib/model/campaign-conversions.js.map +1 -1
  39. package/src/lib/model/campaign-report.d.ts +158 -0
  40. package/src/lib/model/campaign-report.js +268 -0
  41. package/src/lib/model/campaign-report.js.map +1 -0
  42. package/src/lib/model/campaign-revenue.d.ts +3 -3
  43. package/src/lib/model/campaign-revenue.js +3 -3
  44. package/src/lib/model/campaign-revenue.js.map +1 -1
  45. package/src/lib/model/campaign-send-time.js +2 -2
  46. package/src/lib/model/campaign-send-time.js.map +1 -1
  47. package/src/lib/model/compile-client-automations.d.ts +2 -2
  48. package/src/lib/model/compile-client-automations.js +3 -3
  49. package/src/lib/model/compile-client-automations.js.map +1 -1
  50. package/src/lib/model/email-record.d.ts +175 -0
  51. package/src/lib/model/email-record.js +206 -0
  52. package/src/lib/model/email-record.js.map +1 -0
  53. package/src/lib/model/site-contract.d.ts +2 -2
  54. package/src/lib/model/site-contract.js.map +1 -1
  55. package/src/lib/model/template-report.d.ts +158 -0
  56. package/src/lib/model/template-report.js +249 -0
  57. package/src/lib/model/template-report.js.map +1 -0
  58. package/src/lib/plugin.js +16 -0
  59. package/src/lib/plugin.js.map +1 -1
  60. package/src/lib/preview-props.js.map +1 -1
  61. package/src/lib/server/campaign-attribution-store.d.ts +55 -0
  62. package/src/lib/server/campaign-attribution-store.js +98 -0
  63. package/src/lib/server/campaign-attribution-store.js.map +1 -0
  64. package/src/lib/server/campaign-conversion-attribution.d.ts +283 -0
  65. package/src/lib/server/campaign-conversion-attribution.js +447 -0
  66. package/src/lib/server/campaign-conversion-attribution.js.map +1 -0
  67. package/src/lib/server/campaign-manage.js +1 -1
  68. package/src/lib/server/campaign-manage.js.map +1 -1
  69. package/src/lib/server/campaign-org-refs.js +1 -1
  70. package/src/lib/server/campaign-org-refs.js.map +1 -1
  71. package/src/lib/server/campaign-recipients.js +7 -7
  72. package/src/lib/server/campaign-recipients.js.map +1 -1
  73. package/src/lib/server/campaign-send.js +25 -19
  74. package/src/lib/server/campaign-send.js.map +1 -1
  75. package/src/lib/server/conversion-creditor.d.ts +18 -0
  76. package/src/lib/server/conversion-creditor.js +131 -0
  77. package/src/lib/server/conversion-creditor.js.map +1 -0
  78. package/src/lib/server/email-campaign-touch.d.ts +81 -0
  79. package/src/lib/server/email-campaign-touch.js +227 -0
  80. package/src/lib/server/email-campaign-touch.js.map +1 -0
  81. package/src/lib/server/email-events.js +8 -6
  82. package/src/lib/server/email-events.js.map +1 -1
  83. package/src/lib/server/email-revenue-attribution.d.ts +186 -0
  84. package/src/lib/server/email-revenue-attribution.js +322 -0
  85. package/src/lib/server/email-revenue-attribution.js.map +1 -0
  86. package/src/lib/server/email-send-record-index.d.ts +34 -0
  87. package/src/lib/server/email-send-record-index.js +90 -0
  88. package/src/lib/server/email-send-record-index.js.map +1 -0
  89. package/src/lib/server/get-client-automations.js.map +1 -1
  90. package/src/lib/server/marketing-figures.js +3 -3
  91. package/src/lib/server/marketing-figures.js.map +1 -1
  92. package/src/lib/server/send-tally.d.ts +32 -0
  93. package/src/lib/server/send-tally.js +54 -0
  94. package/src/lib/server/send-tally.js.map +1 -0
  95. package/src/lib/testing/stand-in-person-records.d.ts +35 -0
  96. package/src/lib/testing/stand-in-person-records.js +67 -0
  97. package/src/lib/testing/stand-in-person-records.js.map +1 -0
  98. package/src/lib/testing/stand-in-record-counts.d.ts +26 -0
  99. package/src/lib/testing/stand-in-record-counts.js +70 -0
  100. package/src/lib/testing/stand-in-record-counts.js.map +1 -0
  101. package/src/lib/transfer/campaigns-package.d.ts +72 -0
  102. package/src/lib/transfer/campaigns-package.js +145 -0
  103. package/src/lib/transfer/campaigns-package.js.map +1 -0
  104. package/src/lib/transfer/campaigns-package.server.d.ts +33 -0
  105. package/src/lib/transfer/campaigns-package.server.js +305 -0
  106. package/src/lib/transfer/campaigns-package.server.js.map +1 -0
@@ -886,7 +886,9 @@ function AnnouncementBar(props) {
886
886
  }),
887
887
  popup.imageUrl && !Aglyn.isRefusedAuthorImageSrc(popup.imageUrl) ? // eslint-disable-next-line @next/next/no-img-element
888
888
  /*#__PURE__*/ _jsx("img", {
889
- src: popup.imageUrl,
889
+ src: Aglyn.siteRelativeMediaSrc(popup.imageUrl, {
890
+ hostId
891
+ }),
890
892
  // AGL-1896. This was a hardcoded `alt=""` with no field behind
891
893
  // it. Still empty when the author left it empty — a decorative
892
894
  // banner beside its own headline is the case `alt=""` exists for
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketing/src/lib/components/site-runtime.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { sendAnalyticsBeacon } from '@aglyn/aglyn/app-utils/analytics-beacon'\nimport {\n trackAuthoredEvent,\n trackEvent,\n} from '@aglyn/aglyn/app-utils/analytics-events'\nimport { utmTouchField } from '@aglyn/aglyn/app-utils/utm-touch'\nimport { type CSSProperties, useEffect, useRef, useState } from 'react'\nimport type { SiteRuntimeProps } from '@aglyn/aglyn'\nimport * as MarketingModel from '../model'\nimport type {\n AnnouncementBarData,\n ClientAutomation,\n PopupData,\n ScreenExperiment,\n} from '../model/site-contract'\n\n/**\n * Overlay metrics beacon (AGL-200): fire-and-forget, never blocks UX.\n * With an `overlayId` (marketing-hub docs, AGL-271) the collector also\n * increments that overlay's own stats counters.\n */\nfunction sendOverlayBeacon(\n hostId: string | undefined,\n overlay: string,\n overlayId?: string,\n) {\n if (!hostId) return\n // Best-effort, and refused outright from a non-production build or a browser\n // marked ours — the same gate the pageview beacon passes. The GA mirror\n // below is NOT gated here: `trackEvent` carries the taxonomy's own\n // environment check and stamps `traffic_type` rather than dropping the hit.\n sendAnalyticsBeacon({\n hostId,\n overlay,\n ...(overlayId ? { overlayId } : {}),\n })\n // GA mirror (wave v8): sites with Analytics configured see overlay\n // engagement in their own property; no-op without gtag.\n //\n // Through the taxonomy since AGL-1591 rather than raw gtag. `trackEvent`\n // already swallows everything and never throws, so the try/catch this used\n // to need is gone rather than kept as decoration.\n trackEvent('aglyn_overlay', {\n overlay_action: overlay,\n ...(overlayId ? { overlay_id: overlayId } : {}),\n })\n}\n\n/**\n * Site-wide announcement bar (AGL-195). Dismissal is per content-hash in\n * localStorage (no cookies): editing the text re-shows the bar for\n * everyone who hid the old one.\n */\n/**\n * Experiments runner (AGL-253): deterministic per-visitor assignment for\n * the screen's experiments. The first active experiment wins (one per\n * screen); its variant tree — composed server-side per variant version —\n * swaps in via canvas.setNodes on hydration. Exposures beacon on\n * assignment; the conversion listener matches the experiment's goal and\n * beacons once per pageview.\n */\nfunction ExperimentsRunner(props: {\n hostId?: string\n experiments: ScreenExperiment[]\n /** Host consent config (AGL-1498); decides where the visitor id may live. */\n consentHost?: Aglyn.VisitorConsentHost | null\n}) {\n const { hostId, experiments, consentHost } = props\n\n useEffect(() => {\n if (!hostId || !experiments.length) return undefined\n const experiment = experiments[0]\n // Visitor-id persistence honors the consent gate (AGL-1498): without an\n // analytics yes on a consent-gated site, the id lives in sessionStorage —\n // variants stay stable within the visit, and the indefinite identifier\n // is not kept. The id never leaves the browser either way (the beacons\n // below carry no visitor id), which is why this is a persistence\n // downgrade rather than a kill switch on experiments.\n const persistence = Aglyn.resolveVisitorIdPersistence(\n consentHost,\n Aglyn.readStoredVisitorConsent(hostId),\n )\n let visitorId: string\n try {\n const storage =\n persistence === 'local' ? localStorage : sessionStorage\n // Read across BOTH stores so the assignment survives a consent move:\n // a session id promoted to local (consent granted mid-visit) and a\n // legacy local id migrating down to session both keep their variant.\n visitorId =\n storage.getItem(Aglyn.VISITOR_ID_STORAGE_KEY) ??\n sessionStorage.getItem(Aglyn.VISITOR_ID_STORAGE_KEY) ??\n localStorage.getItem(Aglyn.VISITOR_ID_STORAGE_KEY) ??\n ''\n if (!visitorId) {\n visitorId = `v-${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`\n }\n storage.setItem(Aglyn.VISITOR_ID_STORAGE_KEY, visitorId)\n // A pre-consent-tool id may still sit in localStorage from before the\n // gate existed; while un-consented it must not persist.\n if (persistence === 'session') {\n localStorage.removeItem(Aglyn.VISITOR_ID_STORAGE_KEY)\n }\n } catch {\n return undefined // No storage (privacy mode) — serve the default.\n }\n const variant = MarketingModel.assignExperimentVariant(\n // Wire-typed props (AGL-418); the plugin narrows its own enum.\n { status: experiment.status as never, variants: experiment.variants,\n ...(experiment.winnerVariantId\n ? { winnerVariantId: experiment.winnerVariantId }\n : {}),\n // End dates (AGL-273): past-end experiments serve the default.\n ...(experiment.endAtMs ? { endAtMs: experiment.endAtMs } : {}) },\n experiment.id,\n visitorId,\n )\n if (!variant) return undefined\n const payload = experiment.payloads[variant.id]\n if (payload) Aglyn.canvas.setNodes(payload as any)\n\n const beacon = (kind: 'exposure' | 'conversion') => {\n void fetch('/api/experiments/track', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n experimentId: experiment.id,\n variantId: variant.id,\n kind,\n }),\n keepalive: true,\n }).catch(() => undefined)\n // GA mirror (wave v8): exposure/conversion events land in the\n // site's own Analytics property when configured. Through the taxonomy\n // since AGL-1591 — which also reserves the name against an authored\n // `trackGaEvent` step, so nothing hand-written can add itself to the\n // counts that decide which variant wins.\n trackEvent('aglyn_experiment', {\n experiment_id: experiment.id,\n variant_id: variant.id,\n experiment_action: kind,\n })\n }\n // Finished experiments serve the winner without counting stats.\n if (experiment.status !== 'running') return undefined\n beacon('exposure')\n\n // Goal listener — client-observable goals only; server-side goals\n // (bookings etc.) count through their own pipelines in a follow-up.\n const cleanups: Array<() => void> = []\n let converted = false\n const convert = () => {\n if (converted) return\n converted = true\n beacon('conversion')\n }\n const goal = experiment.goal?.event ?? 'formSubmission'\n if (goal === 'formSubmission') {\n const onSubmit = () => convert()\n document.addEventListener('submit', onSubmit, true)\n cleanups.push(() => document.removeEventListener('submit', onSubmit, true))\n } else if (goal === 'elementClick') {\n const selector = experiment.goal?.filter?.trim() || 'a, button'\n const onClick = (event: MouseEvent) => {\n const target = event.target as Element | null\n if (target?.closest?.(selector)) convert()\n }\n document.addEventListener('click', onClick, true)\n cleanups.push(() => document.removeEventListener('click', onClick, true))\n } else if (goal === 'scrollDepth') {\n const onScroll = () => {\n const doc = document.documentElement\n const max = doc.scrollHeight - window.innerHeight\n if (max <= 0 || (window.scrollY / max) * 100 >= 50) {\n convert()\n window.removeEventListener('scroll', onScroll)\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n cleanups.push(() => window.removeEventListener('scroll', onScroll))\n } else if (goal === 'timeOnPage') {\n const timer = setTimeout(convert, 30_000)\n cleanups.push(() => clearTimeout(timer))\n }\n return () => {\n for (const cleanup of cleanups) cleanup()\n }\n // Experiments are static per pageview (ISR props).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hostId, experiments.length && experiments[0]?.id])\n\n return null\n}\n\n/**\n * Site-event automations engine (AGL-256/257): arms the page's triggers\n * (scroll depth, element visibility/clicks, exit intent, dwell time),\n * runs each fired action's CLIENT steps in the browser, and dispatches\n * actions with server steps to /api/events/dispatch. Every trigger fires\n * at most once per pageview.\n */\nfunction AutomationsEngine(props: {\n hostId?: string\n automations: ClientAutomation[]\n /** Host routing map (screen id → slug) for rename-safe redirects. */\n screens?: Record<string, string>\n onShowOverlay: (overlayId: string) => void\n}) {\n const { hostId, automations, screens, onShowOverlay } = props\n const showOverlayRef = useRef(onShowOverlay)\n showOverlayRef.current = onShowOverlay\n\n useEffect(() => {\n if (!hostId || !automations.length) return undefined\n const fired = new Set<string>()\n const cleanups: Array<() => void> = []\n\n const showToast = (\n message: string,\n severity: 'info' | 'success' | 'warning' | 'error',\n ) => {\n const toast = document.createElement('div')\n toast.textContent = message\n toast.setAttribute('role', 'status')\n Object.assign(toast.style, {\n position: 'fixed',\n bottom: '16px',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: '2147483000',\n padding: '10px 16px',\n borderRadius: '8px',\n fontSize: '14px',\n fontFamily: 'system-ui, sans-serif',\n color: '#fff',\n backgroundColor:\n severity === 'error'\n ? '#c62828'\n : severity === 'warning'\n ? '#e65100'\n : severity === 'success'\n ? '#2e7d32'\n : 'rgba(0, 0, 0, 0.85)',\n maxWidth: '90vw',\n })\n document.body.appendChild(toast)\n setTimeout(() => toast.remove(), 6000)\n }\n\n const runClientSteps = (automation: ClientAutomation) => {\n for (const step of automation.steps) {\n try {\n if (\n step.type === 'addClass' ||\n step.type === 'removeClass' ||\n step.type === 'toggleClass'\n ) {\n // Expand the raw-id selector to also match the layout-composed\n // live id (AGL-573); non-leaf selectors are unchanged.\n const targets = document.querySelectorAll(\n Aglyn.expandLeafSelector(step.selector),\n )\n targets.forEach((element) => {\n if (step.type === 'addClass') {\n element.classList.add(step.className)\n } else if (step.type === 'removeClass') {\n element.classList.remove(step.className)\n } else {\n element.classList.toggle(step.className)\n }\n })\n } else if (\n step.type === 'setAttribute' ||\n step.type === 'removeAttribute'\n ) {\n /*\n The semantics half of a hand-built disclosure (AGL-2546).\n\n Deliberately in THIS loop rather than behind a guard of its own:\n it then inherits exactly the gating the visibility steps have,\n including which surfaces mount the runtime at all. A separate\n path reaching `document.querySelector` directly is how this\n would come to run somewhere `showElement` does not.\n\n The name is re-checked here and not only in the editor. The\n editor is a convenience; a step can reach this runtime from a\n document written before the allowlist existed, or by any route\n that does not pass through the console UI.\n\n A rejected name is a NO-OP, not a throw — the `catch` around\n this loop would otherwise let one bad attribute name silently\n drop every step after it in the same automation.\n */\n if (Aglyn.isInteractionAttributeAllowed(step.name)) {\n const name = step.name.trim().toLowerCase()\n const targets = document.querySelectorAll(\n Aglyn.expandLeafSelector(step.selector),\n )\n targets.forEach((element) => {\n if (step.type === 'setAttribute') {\n element.setAttribute(name, step.value ?? '')\n } else {\n element.removeAttribute(name)\n }\n })\n }\n } else if (step.type === 'scrollTo') {\n // One target, the first one on screen (AGL-2867). A target that\n // is missing, deleted or hidden makes the step a no-op, and the\n // steps after it in this automation still run.\n Aglyn.runScrollToStep(Aglyn.expandLeafSelector(step.selector), {\n behavior: step.behavior,\n offsetPx: step.offsetPx,\n })\n } else if (step.type === 'playVideo') {\n // The Video element's own poster press, sent to the element: the\n // player loads only now, exactly as it would for a click on the\n // poster, and under the same consent rules.\n Aglyn.runPlayVideoStep(Aglyn.expandLeafSelector(step.selector))\n } else if (step.type === 'stickyNav') {\n const target = document.querySelector(\n Aglyn.expandLeafSelector(step.selector?.trim() || 'header, nav'),\n )\n if (target instanceof HTMLElement) {\n target.style.position = 'sticky'\n target.style.top = '0'\n target.style.zIndex = '1100'\n }\n } else if (step.type === 'showHtml') {\n const container = document.createElement('div')\n // Sanitize (AGL-504): unlike runJs, showHtml is NOT dropped by the\n // JS entitlement gate, so raw innerHTML would let any automations-\n // tier author execute event-handler attributes (<img onerror>).\n //\n // ONE policy for the surface (AGL-2486). AGL-1901 moved rich text\n // and Custom HTML onto `sanitizeAuthorHtml`; this call was the\n // last raw DOMPurify left on a published page, and two sanitizers\n // with different rules on one surface is worse than the weaker of\n // them — a reviewer reads the strict one and assumes it covers\n // both. It did not: DOMPurify filters NO CSS, so every `style`\n // attribute arriving here reached the visitor unexamined while\n // the Custom HTML block beside it went through `sanitizeAuthorCss`.\n //\n // Nothing this used to refuse is now allowed. `sanitizeAuthorHtml`\n // is a strict SUBSET of the DOMPurify config it replaces, and that\n // is measured rather than asserted: `rich-text-hydration.spec.tsx`\n // holds this exact former config as `referenceShowHtmlPurify` and\n // runs the shared corpus through both. So the change is only in\n // what it ADDITIONALLY refuses:\n //\n // - `style` now gets the CSS rule — `http:` and unknown-scheme\n // `url()` neutered to `about:invalid`, and `@import`,\n // `expression()`, `behavior:` and `-moz-binding` dropping the\n // declaration whole. Character references are decoded BEFORE\n // the scheme is judged, which the old config did not do: it\n // emitted `url(&#104;ttp://…)` as a literal `http://`.\n // - `<form>` stops being an element. The former FORBID_TAGS here\n // listed `script, iframe, object, embed, base` and omitted\n // `form` — alone among this repo's author-HTML configs, both of\n // which forbade it — so a password field on the owner's live\n // page was one paste away.\n //\n // What is deliberately NOT refused, on either side of the change:\n // a third-party `https:` `url()`, and `position:fixed` / `z-index`.\n // The first is AGL-1725's actor analysis (the site owner chooses\n // recipients for their own visitors); the second is a capability\n // the Styles panel already gives the same author as a first-class\n // field, so refusing it only here would move nothing.\n container.innerHTML = Aglyn.sanitizeAuthorHtml(step.html)\n document.body.appendChild(container)\n } else if (step.type === 'runJs') {\n // Business-gated server-side (dropped from props otherwise);\n // the site owner's own code running on their own page.\n // eslint-disable-next-line no-new-func\n new Function(step.code)()\n } else if (step.type === 'redirect') {\n // Screen targets resolve through the routing map (AGL-339) so\n // slug renames never break the interaction; url is the manual\n // fallback.\n const screenSlug =\n (step as any).screenId != null\n ? screens?.[(step as any).screenId]\n : undefined\n const destination =\n screenSlug != null\n ? Aglyn.screenRoutePathToUrl(screenSlug)\n : step.url\n if (destination) window.location.assign(destination)\n } else if (\n step.type === 'showElement' ||\n step.type === 'hideElement' ||\n step.type === 'toggleElement'\n ) {\n // Element choreography (AGL-562): class-based so \"show\"\n // reveals targets the author started hidden. The tenant page\n // ships the hidden-class rule in its SSR HTML; ensure is the\n // fallback for other embeddings. Grace delays + Escape/\n // outside-click dismissal ride the same step (AGL-589).\n Aglyn.ensureElementHiddenStyle()\n Aglyn.runElementVisibilityStep(\n step.type === 'showElement'\n ? 'show'\n : step.type === 'hideElement'\n ? 'hide'\n : 'toggle',\n // Expand so a show/hide/toggle authored against the raw\n // canvas id still reaches the layout-composed node (AGL-573).\n Aglyn.expandLeafSelector(step.selector),\n {\n delayMs: (step as { delayMs?: number }).delayMs,\n dismissOn: (\n step as { dismissOn?: Aglyn.ElementDismissOption[] }\n ).dismissOn,\n },\n )\n } else if (\n step.type === 'openDrawer' ||\n step.type === 'closeDrawer' ||\n step.type === 'toggleDrawer'\n ) {\n // Drawer commands (AGL-562) ride the window event bus; the\n // muiDrawer element answers (first drawer for broadcasts).\n Aglyn.dispatchDrawerCommand(\n step.type === 'openDrawer'\n ? 'open'\n : step.type === 'closeDrawer'\n ? 'close'\n : 'toggle',\n step.drawerNodeId || undefined,\n )\n } else if (\n step.type === 'openMenu' ||\n step.type === 'closeMenu' ||\n step.type === 'toggleMenu'\n ) {\n // Menu commands (AGL-568) ride their own event bus like\n // drawers; the nav-menu elements answer (first menu for\n // broadcasts). A hover-enter trigger stamps the hover flag\n // so a menu opened this way closes itself when the pointer\n // leaves the trigger + panel surface.\n Aglyn.dispatchMenuCommand(\n step.type === 'openMenu'\n ? 'open'\n : step.type === 'closeMenu'\n ? 'close'\n : 'toggle',\n step.menuNodeId || undefined,\n { hover: automation.event === 'elementHoverEnter' },\n )\n } else if (step.type === 'trackGaEvent') {\n // AGL-1587: the name and the params are AUTHORED, which makes\n // this the least trustworthy analytics input in the repo — a\n // param could carry a form field's value. It goes through the\n // shared sanitizer and the reserved-name refusal like everything\n // else, never raw gtag.\n trackAuthoredEvent(step.eventName, step.params)\n } else if (step.type === 'siteAlert') {\n showToast(\n String(step.message ?? '').slice(0, 300),\n step.severity ?? 'info',\n )\n } else if (step.type === 'showOverlay') {\n if (step.overlayId) showOverlayRef.current(step.overlayId)\n }\n } catch (error) {\n console.error('automation step failed', error)\n }\n }\n }\n\n const fire = (automation: ClientAutomation) => {\n // Repeatable UI choreography (AGL-562): everyTime automations skip\n // the once-per-pageview gate (explicit caps below still apply).\n if (!automation.everyTime) {\n if (fired.has(automation.id)) return\n fired.add(automation.id)\n }\n // Once per visitor (AGL-266): a persisted flag outlives the pageview.\n if (automation.oncePerVisitor) {\n const key = `aglyn:auto:${automation.id}`\n try {\n if (localStorage.getItem(key)) return\n localStorage.setItem(key, '1')\n } catch {\n // Storage unavailable — degrade to once per pageview.\n }\n } else if (automation.oncePerSession) {\n // Once per session (AGL-274): survives navigation, not the tab.\n const key = `aglyn:auto:${automation.id}`\n try {\n if (sessionStorage.getItem(key)) return\n sessionStorage.setItem(key, '1')\n } catch {\n // Storage unavailable — degrade to once per pageview.\n }\n } else if (automation.cooldownMinutes) {\n // Cooldown (AGL-274): a timestamp gates re-fires for the visitor.\n const key = `aglyn:auto:${automation.id}:at`\n try {\n const last = Number(localStorage.getItem(key) ?? 0)\n if (\n last &&\n Date.now() - last < automation.cooldownMinutes * 60_000\n ) {\n return\n }\n localStorage.setItem(key, String(Date.now()))\n } catch {\n // Storage unavailable — degrade to once per pageview.\n }\n }\n runClientSteps(automation)\n if (automation.hasServerSteps) {\n void fetch('/api/events/dispatch', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n actionId: automation.id,\n event: automation.event,\n payload: { path: window.location.pathname },\n }),\n keepalive: true,\n }).catch(() => undefined)\n }\n }\n\n /**\n * Elements that arrive AFTER this effect binds (AGL-2512).\n *\n * `elementVisible` and `scrollToElement` are the only two triggers that\n * resolve their targets by querying the DOM — every other one listens on\n * `document` and so needs no element to exist yet. A single query at bind\n * time made them dead on the two pages where the tree lands late: a\n * deferred lazy panel patched back in on interaction (AGL-1285), and a\n * gated screen's tree swapped in once the visitor is past the gate\n * (AGL-2510).\n *\n * One MutationObserver for all of them, not one each, and it stops the\n * moment nothing is left watching — these triggers fire once per pageview\n * by construction, so a page whose targets have all been seen pays\n * nothing for the rest of the visit. A page with no such automation never\n * starts one at all.\n */\n const pendingObservers: Array<() => void> = []\n let domObserver: MutationObserver | null = null\n const rescan = () => {\n for (const attach of [...pendingObservers]) attach()\n if (!pendingObservers.length) {\n domObserver?.disconnect()\n domObserver = null\n }\n }\n const watchLateElements = (attach: () => void) => {\n pendingObservers.push(attach)\n if (domObserver || typeof MutationObserver === 'undefined') return\n domObserver = new MutationObserver(rescan)\n domObserver.observe(document.body, { childList: true, subtree: true })\n }\n const stopWatching = (attach: () => void) => {\n const index = pendingObservers.indexOf(attach)\n if (index >= 0) pendingObservers.splice(index, 1)\n if (!pendingObservers.length) {\n domObserver?.disconnect()\n domObserver = null\n }\n }\n cleanups.push(() => {\n pendingObservers.length = 0\n domObserver?.disconnect()\n domObserver = null\n })\n\n for (const automation of automations) {\n const { event, threshold } = automation\n // Composition namespaces a node's live `data-aglyn` id, but the\n // interaction builder records the RAW canvas id in the selector.\n // Expand it so the trigger still matches the live element — layouts\n // (AGL-573) and reusable-component grafts (AGL-1229), the latter being\n // why every interaction authored inside the Site nav bound to nothing.\n // Hand-typed CSS selectors pass through untouched.\n const selector = automation.selector\n ? Aglyn.expandLeafSelector(automation.selector)\n : automation.selector\n if (event === 'pageVisit') {\n fire(automation)\n } else if (event === 'timeOnPage') {\n const timer = setTimeout(\n () => fire(automation),\n Math.max(1, threshold ?? 5) * 1000,\n )\n cleanups.push(() => clearTimeout(timer))\n } else if (event === 'scrollDepth') {\n const onScroll = () => {\n const doc = document.documentElement\n const max = doc.scrollHeight - window.innerHeight\n const percent = max > 0 ? (window.scrollY / max) * 100 : 100\n if (percent >= Math.min(100, Math.max(1, threshold ?? 50))) {\n fire(automation)\n window.removeEventListener('scroll', onScroll)\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n cleanups.push(() => window.removeEventListener('scroll', onScroll))\n } else if (event === 'elementVisible' || event === 'scrollToElement') {\n if (!selector) continue\n let fired = false\n const observer = new IntersectionObserver((entries) => {\n if (fired || !entries.some((entry) => entry.isIntersecting)) return\n fired = true\n fire(automation)\n observer.disconnect()\n stopWatching(attachTargets)\n })\n // Re-entrant: called again on every DOM change until the trigger\n // fires, and observing an element twice is a no-op, so a rescan costs\n // one `querySelectorAll` and nothing else.\n const attachTargets = () => {\n if (fired) return stopWatching(attachTargets)\n document\n .querySelectorAll(selector)\n .forEach((target) => observer.observe(target))\n }\n attachTargets()\n watchLateElements(attachTargets)\n cleanups.push(() => observer.disconnect())\n } else if (event === 'elementClick') {\n if (!selector) continue\n const onClick = (mouseEvent: MouseEvent) => {\n const target = mouseEvent.target as Element | null\n if (target?.closest?.(selector)) fire(automation)\n }\n document.addEventListener('click', onClick, true)\n cleanups.push(() =>\n document.removeEventListener('click', onClick, true),\n )\n } else if (\n event === 'elementHoverEnter' ||\n event === 'elementHoverLeave'\n ) {\n // Hover choreography (AGL-562): delegated mouseover/mouseout with\n // enter/leave semantics — moves WITHIN the matched element (its\n // own children) never re-fire.\n if (!selector) continue\n const onHover = (mouseEvent: MouseEvent) => {\n const target = mouseEvent.target as Element | null\n const match = target?.closest?.(selector)\n if (!match) return\n const related = mouseEvent.relatedTarget as Element | null\n if (related && match.contains(related)) return\n fire(automation)\n }\n const type = event === 'elementHoverEnter' ? 'mouseover' : 'mouseout'\n document.addEventListener(type, onHover, true)\n cleanups.push(() =>\n document.removeEventListener(type, onHover, true),\n )\n } else if (event === 'exitIntent') {\n const onLeave = (mouseEvent: MouseEvent) => {\n if (mouseEvent.clientY <= 0) fire(automation)\n }\n document.addEventListener('mouseleave', onLeave)\n cleanups.push(() => document.removeEventListener('mouseleave', onLeave))\n }\n }\n return () => {\n for (const cleanup of cleanups) cleanup()\n }\n // Automations are static per pageview (ISR props).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n hostId,\n screens,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(automations.map((automation) => automation.id)),\n ])\n\n return null\n}\n\nfunction AnnouncementBar(props: {\n bar: AnnouncementBarData\n hostId?: string\n}) {\n const { bar, hostId } = props\n const storageKey = `aglyn-abar-${bar.contentHash}`\n const [hidden, setHidden] = useState(true)\n useEffect(() => {\n try {\n setHidden(Boolean(window.localStorage.getItem(storageKey)))\n } catch {\n setHidden(false)\n }\n }, [storageKey])\n // Impression (AGL-271): once per pageview, only when actually shown.\n useEffect(() => {\n if (!hidden) sendOverlayBeacon(hostId, 'barImpression', bar.overlayId)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hidden])\n if (hidden) return null\n const style: CSSProperties = {\n position: 'relative',\n zIndex: 1300,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 8,\n padding: '8px 40px 8px 16px',\n fontSize: 14,\n fontFamily: 'system-ui, sans-serif',\n textAlign: 'center',\n color: bar.textColor || '#fff',\n backgroundColor: bar.backgroundColor || '#111827',\n }\n const text = bar.href ? (\n <a\n href={bar.href}\n onClick={() => sendOverlayBeacon(hostId, 'barClick', bar.overlayId)}\n style={{ color: 'inherit', textDecoration: 'underline' }}\n >\n {bar.text}\n </a>\n ) : (\n <span>{bar.text}</span>\n )\n return (\n <div role=\"region\" aria-label=\"Announcement\" style={style}>\n {text}\n {bar.dismissible ? (\n <button\n type=\"button\"\n aria-label=\"Dismiss announcement\"\n onClick={() => {\n try {\n window.localStorage.setItem(storageKey, '1')\n } catch {\n // Storage may be unavailable (private mode); hide anyway.\n }\n sendOverlayBeacon(hostId, 'barDismiss', bar.overlayId)\n setHidden(true)\n }}\n style={{\n position: 'absolute',\n right: 8,\n top: '50%',\n transform: 'translateY(-50%)',\n border: 'none',\n background: 'transparent',\n color: 'inherit',\n fontSize: 16,\n lineHeight: 1,\n cursor: 'pointer',\n padding: 6,\n }}\n >\n {'✕'}\n </button>\n ) : null}\n </div>\n )\n}\n\n/**\n * Promotional popup (AGL-196). Client owns: schedule-window re-check (the\n * page is ISR-cached), trigger timing (delay/scroll/exit), and frequency\n * capping via a per-content-hash localStorage stamp (no cookies). ESC and\n * backdrop close; reduced-motion preferences skip the entrance ease.\n */\nfunction PopupOverlay(props: {\n popup: PopupData\n hostId?: string\n}) {\n const { popup, hostId } = props\n const storageKey = `aglyn-popup-${popup.contentHash}`\n const [open, setOpen] = useState(false)\n // Email capture (AGL-200): submits into the forms pipeline (inbox +\n // contacts); success suppresses the popup for ~10 years.\n const [email, setEmail] = useState('')\n // The honeypot's value, held in state so whatever a bot typed into the\n // hidden input below is what gets POSTed (AGL-1665). This used to be a\n // hardcoded `website: ''` in the request body: the route drops a\n // submission only when the field is NON-empty, so a constant empty string\n // never failed the check — it removed it. There was no field on the page\n // to fill and no value a script could set, which made the popup the one\n // form surface on the site with no honeypot at all.\n const [website, setWebsite] = useState('')\n const [submitted, setSubmitted] = useState(false)\n\n useEffect(() => {\n if (open) sendOverlayBeacon(hostId, 'popupImpression', popup.overlayId)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, hostId])\n\n useEffect(() => {\n const now = Date.now()\n if (popup.startAtMs && now < popup.startAtMs) return\n if (popup.endAtMs && now > popup.endAtMs) return\n try {\n // The decision itself is a pure function in the model (AGL-2174) —\n // which store to read is the whole feature, and it has to agree with\n // what `close` writes.\n const suppressed = MarketingModel.popupSuppressed(\n popup,\n MarketingModel.popupCapStore(popup) === 'session'\n ? { sessionFlag: window.sessionStorage.getItem(storageKey) }\n : { lastShownMs: Number(window.localStorage.getItem(storageKey) ?? 0) },\n now,\n )\n if (suppressed) return\n } catch {\n // Storage unavailable: show at most per-pageview.\n }\n let cleanup: (() => void) | undefined\n if (popup.trigger === 'scroll') {\n const threshold = Math.min(100, Math.max(0, popup.triggerValue)) / 100\n const onScroll = () => {\n const height =\n document.documentElement.scrollHeight - window.innerHeight\n if (height <= 0 || window.scrollY / height >= threshold) {\n setOpen(true)\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n cleanup = () => window.removeEventListener('scroll', onScroll)\n } else if (popup.trigger === 'exit') {\n const onLeave = (event: MouseEvent) => {\n if (event.clientY <= 0) setOpen(true)\n }\n document.addEventListener('mouseout', onLeave)\n cleanup = () => document.removeEventListener('mouseout', onLeave)\n } else {\n const timer = window.setTimeout(\n () => setOpen(true),\n Math.max(0, popup.triggerValue) * 1000,\n )\n cleanup = () => window.clearTimeout(timer)\n }\n return cleanup\n }, [popup, storageKey])\n\n const close = (kind: 'popupDismiss' | 'popupClick' = 'popupDismiss') => {\n try {\n // Written to whichever store the cap READS (AGL-2174). Stamping\n // `localStorage` for a session-capped popup would leave a timestamp\n // nothing reads, outliving the cap it was meant to record.\n if (MarketingModel.popupCapStore(popup) === 'session') {\n window.sessionStorage.setItem(storageKey, '1')\n } else {\n window.localStorage.setItem(storageKey, String(Date.now()))\n }\n } catch {\n // Private mode etc. — closing still works for this pageview.\n }\n sendOverlayBeacon(hostId, kind, popup.overlayId)\n setOpen(false)\n }\n\n const handleEmailSubmit = async () => {\n const value = email.trim()\n if (!value || submitted) return\n try {\n const response = await fetch('/api/forms/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n // The door this capture comes through (AGL-3029): the popup is a\n // Marketing element, so a site that switched Forms off still\n // collects the address it shows the popup for.\n door: 'popup',\n formName: 'Popup',\n fields: { email: value },\n path: window.location.pathname,\n // Submitted AS-IS (AGL-1665) — the point of a honeypot is that the\n // client never judges it. `libs/plugins/mui/.../form.tsx` reads its\n // own hidden `website` input off the FormData and forwards it the\n // same way; `/api/forms/submit` is the single place that decides.\n website,\n // The campaign this visitor came from, when they came from one. A\n // popup capture is often a site's highest-converting door, so it\n // reports its campaign for the same reason it reports its lead.\n ...utmTouchField(),\n }),\n })\n // The popup's email capture is a lead, and it reported none: an\n // announcement popup is often a site's highest-converting capture, and\n // the merchant saw the impression and the dismiss (`aglyn_overlay`) with\n // nothing in between. The generic form block has sent `generate_lead`\n // since AGL-1561; this door was simply never wired to it.\n //\n // Gated on `response.ok`, unlike the visitor-facing thank-you below.\n // The two disagree deliberately: a spam-refused or rate-limited capture\n // is still shown the thank-you — telling a real visitor to try again\n // after a honeypot verdict would leak the honeypot — but it is NOT a\n // lead, and counting it would inflate the only number the merchant uses\n // to judge whether the popup is worth interrupting people with.\n //\n // `form_name` is the block's own name, matching the `formName` on the\n // wire; the address the visitor just typed never leaves this function.\n if (response.ok) {\n trackEvent('generate_lead', {\n form_name: 'Popup',\n form_location: window.location.pathname,\n })\n }\n } catch {\n // Best-effort — still thank the visitor.\n }\n setSubmitted(true)\n try {\n // Far-future stamp: a successful capture never re-prompts.\n window.localStorage.setItem(\n storageKey,\n String(Date.now() + 315360000000),\n )\n } catch {\n // Ignore.\n }\n }\n\n useEffect(() => {\n if (!open) return\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') close()\n }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open])\n\n if (!open) return null\n return (\n <div\n onClick={() => close()}\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 2147483200,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n padding: 16,\n }}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={popup.headline || 'Announcement'}\n onClick={(event) => event.stopPropagation()}\n style={{\n maxWidth: 420,\n width: '100%',\n background: '#fff',\n color: '#111827',\n borderRadius: 12,\n overflow: 'hidden',\n boxShadow: '0 24px 64px rgba(0, 0, 0, 0.35)',\n fontFamily: 'system-ui, sans-serif',\n position: 'relative',\n }}\n >\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={() => close()}\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n border: 'none',\n background: 'rgba(255, 255, 255, 0.85)',\n borderRadius: '50%',\n width: 28,\n height: 28,\n cursor: 'pointer',\n fontSize: 14,\n lineHeight: 1,\n }}\n >\n {'✕'}\n </button>\n {/* The popup image is a free-text console field rendered verbatim —\n one of AGL-1725's raw author sinks. Scheme rule only, never a\n host check: `http:` and unknown schemes render nothing;\n https/relative (the media picker's forms) render as stored. */}\n {popup.imageUrl && !Aglyn.isRefusedAuthorImageSrc(popup.imageUrl) ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={popup.imageUrl}\n // AGL-1896. This was a hardcoded `alt=\"\"` with no field behind\n // it. Still empty when the author left it empty — a decorative\n // banner beside its own headline is the case `alt=\"\"` exists for\n // — but it is now their choice rather than ours, and picking the\n // image from the library fills it in from the asset.\n alt={popup.imageAlt ?? ''}\n style={{\n width: '100%',\n maxHeight: 200,\n objectFit: 'cover',\n display: 'block',\n }}\n />\n ) : null}\n <div style={{ padding: 24, textAlign: 'center' }}>\n {popup.headline ? (\n <h2 style={{ margin: '0 0 8px', fontSize: 20 }}>\n {popup.headline}\n </h2>\n ) : null}\n <p style={{ margin: 0, fontSize: 14, whiteSpace: 'pre-wrap' }}>\n {popup.body}\n </p>\n {popup.collectEmail ? (\n <div style={{ marginTop: 16 }}>\n {submitted ? (\n <p style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>\n {'Thanks — you are on the list!'}\n </p>\n ) : (\n <form\n onSubmit={(event) => {\n event.preventDefault()\n void handleEmailSubmit()\n }}\n style={{ display: 'flex', gap: 8, justifyContent: 'center' }}\n >\n <input\n type=\"email\"\n required\n placeholder=\"you@example.com\"\n // Same nameless-input defect as the newsletter block\n // (AGL-2392). A popup is modal-ish and arrives unbidden,\n // so a screen-reader user meets this field with no\n // surrounding context at all.\n aria-label=\"Email address\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n style={{\n flex: 1,\n maxWidth: 240,\n padding: '8px 12px',\n borderRadius: 8,\n border: '1px solid #d1d5db',\n fontSize: 14,\n }}\n />\n {/* Honeypot: humans never see or fill this (AGL-1665).\n Off-screen rather than `display:none`/`hidden`, and\n named `website`, so the naive form-filling bots the\n route's check is aimed at treat it as an ordinary\n field — the same bait, presented the same way, as the\n site form's. Out of flow, so the flex row above is\n unchanged. */}\n <input\n type=\"text\"\n name=\"website\"\n tabIndex={-1}\n autoComplete=\"off\"\n aria-hidden=\"true\"\n value={website}\n onChange={(event) => setWebsite(event.target.value)}\n style={{\n position: 'absolute',\n left: '-5000px',\n height: 0,\n width: 0,\n }}\n />\n <button\n type=\"submit\"\n style={{\n padding: '8px 16px',\n borderRadius: 8,\n border: 'none',\n background: '#111827',\n color: '#fff',\n fontSize: 14,\n cursor: 'pointer',\n }}\n >\n {'Sign up'}\n </button>\n </form>\n )}\n </div>\n ) : null}\n {popup.ctaHref && popup.ctaLabel ? (\n <a\n href={popup.ctaHref}\n onClick={() => close('popupClick')}\n style={{\n display: 'inline-block',\n marginTop: 16,\n padding: '10px 24px',\n borderRadius: 8,\n background: '#111827',\n color: '#fff',\n textDecoration: 'none',\n fontSize: 14,\n }}\n >\n {popup.ctaLabel}\n </a>\n ) : null}\n </div>\n </div>\n </div>\n )\n}\n\n\n/**\n * The marketing plugin's site runtime (AGL-419), relocated verbatim from\n * the tenant catch-all: announcement bar + popup rendering (AGL-195/200),\n * the experiments runner (AGL-253), the site-event automations engine\n * (AGL-256/257), and automation-triggered overlays. Reads back exactly the\n * page-props slices its server enricher wrote (site-contract shapes).\n */\nexport function MarketingSiteRuntime({ hostId, screens, page }: SiteRuntimeProps) {\n const [automationOverlay, setAutomationOverlay] = useState<any>(null)\n const announcementBar = page['announcementBar'] as AnnouncementBarData | null\n const popup = page['popup'] as PopupData | null\n const experiments = (page['experiments'] ?? []) as ScreenExperiment[]\n const clientAutomations = (page['clientAutomations'] ?? []) as ClientAutomation[]\n const automationOverlays = page['automationOverlays'] as Record<string, any> | null\n\n return (\n <>\n {announcementBar ? (\n <AnnouncementBar bar={announcementBar} hostId={hostId} />\n ) : null}\n {popup ? <PopupOverlay popup={popup} hostId={hostId} /> : null}\n {/* Screen/section experiments (AGL-253). */}\n {experiments.length ? (\n <ExperimentsRunner\n hostId={hostId}\n experiments={experiments}\n consentHost={page['data']?.host as Aglyn.VisitorConsentHost | null}\n />\n ) : null}\n {/* Site-event automations (AGL-256/257). */}\n {clientAutomations.length ? (\n <AutomationsEngine\n hostId={hostId}\n automations={clientAutomations}\n screens={screens}\n onShowOverlay={(overlayId) => {\n const overlay = automationOverlays?.[overlayId]\n if (overlay) setAutomationOverlay({ id: overlayId, ...overlay })\n }}\n />\n ) : null}\n {automationOverlay?.kind === 'bar' && automationOverlay.bar?.text ? (\n <AnnouncementBar\n bar={{\n ...automationOverlay.bar,\n text: String(automationOverlay.bar.text),\n dismissible: automationOverlay.bar.dismissible !== false,\n contentHash: `automation-${automationOverlay.id}`,\n }}\n hostId={hostId}\n />\n ) : null}\n {automationOverlay?.kind === 'popup' && automationOverlay.popup?.body ? (\n <PopupOverlay\n popup={{\n ...automationOverlay.popup,\n body: String(automationOverlay.popup.body),\n trigger: 'delay',\n triggerValue: 0,\n frequencyDays: Math.max(\n 1,\n Number(automationOverlay.popup.frequencyDays ?? 1),\n ),\n contentHash: `automation-${automationOverlay.id}`,\n }}\n hostId={hostId}\n />\n ) : null}\n </>\n )\n}\n"],"names":["Aglyn","sendAnalyticsBeacon","trackAuthoredEvent","trackEvent","utmTouchField","useEffect","useRef","useState","MarketingModel","sendOverlayBeacon","hostId","overlay","overlayId","overlay_action","overlay_id","ExperimentsRunner","props","experiments","consentHost","experiment","length","undefined","persistence","resolveVisitorIdPersistence","readStoredVisitorConsent","visitorId","storage","localStorage","sessionStorage","getItem","VISITOR_ID_STORAGE_KEY","Math","random","toString","slice","Date","now","setItem","removeItem","variant","assignExperimentVariant","status","variants","winnerVariantId","endAtMs","id","payload","payloads","canvas","setNodes","beacon","kind","fetch","method","headers","body","JSON","stringify","experimentId","variantId","keepalive","catch","experiment_id","variant_id","experiment_action","cleanups","converted","convert","goal","event","onSubmit","document","addEventListener","push","removeEventListener","selector","filter","trim","onClick","target","closest","onScroll","doc","documentElement","max","scrollHeight","window","innerHeight","scrollY","passive","timer","setTimeout","clearTimeout","cleanup","AutomationsEngine","automations","screens","onShowOverlay","showOverlayRef","current","fired","Set","showToast","message","severity","toast","createElement","textContent","setAttribute","Object","assign","style","position","bottom","left","transform","zIndex","padding","borderRadius","fontSize","fontFamily","color","backgroundColor","maxWidth","appendChild","remove","runClientSteps","automation","step","steps","type","targets","querySelectorAll","expandLeafSelector","forEach","element","classList","add","className","toggle","isInteractionAttributeAllowed","name","toLowerCase","value","removeAttribute","runScrollToStep","behavior","offsetPx","runPlayVideoStep","querySelector","HTMLElement","top","container","innerHTML","sanitizeAuthorHtml","html","Function","code","screenSlug","screenId","destination","screenRoutePathToUrl","url","location","ensureElementHiddenStyle","runElementVisibilityStep","delayMs","dismissOn","dispatchDrawerCommand","drawerNodeId","dispatchMenuCommand","menuNodeId","hover","eventName","params","String","error","console","fire","everyTime","has","oncePerVisitor","key","oncePerSession","cooldownMinutes","last","Number","hasServerSteps","actionId","path","pathname","pendingObservers","domObserver","rescan","attach","disconnect","watchLateElements","MutationObserver","observe","childList","subtree","stopWatching","index","indexOf","splice","threshold","percent","min","observer","IntersectionObserver","entries","some","entry","isIntersecting","attachTargets","mouseEvent","onHover","match","related","relatedTarget","contains","onLeave","clientY","map","AnnouncementBar","bar","storageKey","contentHash","hidden","setHidden","Boolean","display","alignItems","justifyContent","gap","textAlign","textColor","text","href","a","textDecoration","span","div","role","aria-label","dismissible","button","right","border","background","lineHeight","cursor","PopupOverlay","popup","open","setOpen","email","setEmail","website","setWebsite","submitted","setSubmitted","startAtMs","suppressed","popupSuppressed","popupCapStore","sessionFlag","lastShownMs","trigger","triggerValue","height","close","handleEmailSubmit","response","door","formName","fields","ok","form_name","form_location","onKey","inset","aria-modal","headline","stopPropagation","width","overflow","boxShadow","imageUrl","isRefusedAuthorImageSrc","img","src","alt","imageAlt","maxHeight","objectFit","h2","margin","p","whiteSpace","collectEmail","marginTop","fontWeight","form","preventDefault","input","required","placeholder","onChange","flex","tabIndex","autoComplete","aria-hidden","ctaHref","ctaLabel","MarketingSiteRuntime","page","automationOverlay","setAutomationOverlay","announcementBar","clientAutomations","automationOverlays","host","frequencyDays"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketing/src/lib/components/site-runtime.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2022 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { sendAnalyticsBeacon } from '@aglyn/aglyn/app-utils/analytics-beacon'\nimport {\n trackAuthoredEvent,\n trackEvent,\n} from '@aglyn/aglyn/app-utils/analytics-events'\nimport { utmTouchField } from '@aglyn/aglyn/app-utils/utm-touch'\nimport { type CSSProperties, useEffect, useRef, useState } from 'react'\nimport type { SiteRuntimeProps } from '@aglyn/aglyn'\nimport * as MarketingModel from '../model'\nimport type {\n AnnouncementBarData,\n ClientAutomation,\n PopupData,\n ScreenExperiment,\n} from '../model/site-contract'\n\n/**\n * Overlay metrics beacon (AGL-200): fire-and-forget, never blocks UX.\n * With an `overlayId` (marketing-hub docs, AGL-271) the collector also\n * increments that overlay's own stats counters.\n */\nfunction sendOverlayBeacon(\n hostId: string | undefined,\n overlay: string,\n overlayId?: string,\n) {\n if (!hostId) return\n // Best-effort, and refused outright from a non-production build or a browser\n // marked ours — the same gate the pageview beacon passes. The GA mirror\n // below is NOT gated here: `trackEvent` carries the taxonomy's own\n // environment check and stamps `traffic_type` rather than dropping the hit.\n sendAnalyticsBeacon({\n hostId,\n overlay,\n ...(overlayId ? { overlayId } : {}),\n })\n // GA mirror (wave v8): sites with Analytics configured see overlay\n // engagement in their own property; no-op without gtag.\n //\n // Through the taxonomy since AGL-1591 rather than raw gtag. `trackEvent`\n // already swallows everything and never throws, so the try/catch this used\n // to need is gone rather than kept as decoration.\n trackEvent('aglyn_overlay', {\n overlay_action: overlay,\n ...(overlayId ? { overlay_id: overlayId } : {}),\n })\n}\n\n/**\n * Site-wide announcement bar (AGL-195). Dismissal is per content-hash in\n * localStorage (no cookies): editing the text re-shows the bar for\n * everyone who hid the old one.\n */\n/**\n * Experiments runner (AGL-253): deterministic per-visitor assignment for\n * the screen's experiments. The first active experiment wins (one per\n * screen); its variant tree — composed server-side per variant version —\n * swaps in via canvas.setNodes on hydration. Exposures beacon on\n * assignment; the conversion listener matches the experiment's goal and\n * beacons once per pageview.\n */\nfunction ExperimentsRunner(props: {\n hostId?: string\n experiments: ScreenExperiment[]\n /** Host consent config (AGL-1498); decides where the visitor id may live. */\n consentHost?: Aglyn.VisitorConsentHost | null\n}) {\n const { hostId, experiments, consentHost } = props\n\n useEffect(() => {\n if (!hostId || !experiments.length) return undefined\n const experiment = experiments[0]\n // Visitor-id persistence honors the consent gate (AGL-1498): without an\n // analytics yes on a consent-gated site, the id lives in sessionStorage —\n // variants stay stable within the visit, and the indefinite identifier\n // is not kept. The id never leaves the browser either way (the beacons\n // below carry no visitor id), which is why this is a persistence\n // downgrade rather than a kill switch on experiments.\n const persistence = Aglyn.resolveVisitorIdPersistence(\n consentHost,\n Aglyn.readStoredVisitorConsent(hostId),\n )\n let visitorId: string\n try {\n const storage =\n persistence === 'local' ? localStorage : sessionStorage\n // Read across BOTH stores so the assignment survives a consent move:\n // a session id promoted to local (consent granted mid-visit) and a\n // legacy local id migrating down to session both keep their variant.\n visitorId =\n storage.getItem(Aglyn.VISITOR_ID_STORAGE_KEY) ??\n sessionStorage.getItem(Aglyn.VISITOR_ID_STORAGE_KEY) ??\n localStorage.getItem(Aglyn.VISITOR_ID_STORAGE_KEY) ??\n ''\n if (!visitorId) {\n visitorId = `v-${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`\n }\n storage.setItem(Aglyn.VISITOR_ID_STORAGE_KEY, visitorId)\n // A pre-consent-tool id may still sit in localStorage from before the\n // gate existed; while un-consented it must not persist.\n if (persistence === 'session') {\n localStorage.removeItem(Aglyn.VISITOR_ID_STORAGE_KEY)\n }\n } catch {\n return undefined // No storage (privacy mode) — serve the default.\n }\n const variant = MarketingModel.assignExperimentVariant(\n // Wire-typed props (AGL-418); the plugin narrows its own enum.\n { status: experiment.status as never, variants: experiment.variants,\n ...(experiment.winnerVariantId\n ? { winnerVariantId: experiment.winnerVariantId }\n : {}),\n // End dates (AGL-273): past-end experiments serve the default.\n ...(experiment.endAtMs ? { endAtMs: experiment.endAtMs } : {}) },\n experiment.id,\n visitorId,\n )\n if (!variant) return undefined\n const payload = experiment.payloads[variant.id]\n if (payload) Aglyn.canvas.setNodes(payload as any)\n\n const beacon = (kind: 'exposure' | 'conversion') => {\n void fetch('/api/experiments/track', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n experimentId: experiment.id,\n variantId: variant.id,\n kind,\n }),\n keepalive: true,\n }).catch(() => undefined)\n // GA mirror (wave v8): exposure/conversion events land in the\n // site's own Analytics property when configured. Through the taxonomy\n // since AGL-1591 — which also reserves the name against an authored\n // `trackGaEvent` step, so nothing hand-written can add itself to the\n // counts that decide which variant wins.\n trackEvent('aglyn_experiment', {\n experiment_id: experiment.id,\n variant_id: variant.id,\n experiment_action: kind,\n })\n }\n // Finished experiments serve the winner without counting stats.\n if (experiment.status !== 'running') return undefined\n beacon('exposure')\n\n // Goal listener — client-observable goals only; server-side goals\n // (bookings etc.) count through their own pipelines in a follow-up.\n const cleanups: Array<() => void> = []\n let converted = false\n const convert = () => {\n if (converted) return\n converted = true\n beacon('conversion')\n }\n const goal = experiment.goal?.event ?? 'formSubmission'\n if (goal === 'formSubmission') {\n const onSubmit = () => convert()\n document.addEventListener('submit', onSubmit, true)\n cleanups.push(() => document.removeEventListener('submit', onSubmit, true))\n } else if (goal === 'elementClick') {\n const selector = experiment.goal?.filter?.trim() || 'a, button'\n const onClick = (event: MouseEvent) => {\n const target = event.target as Element | null\n if (target?.closest?.(selector)) convert()\n }\n document.addEventListener('click', onClick, true)\n cleanups.push(() => document.removeEventListener('click', onClick, true))\n } else if (goal === 'scrollDepth') {\n const onScroll = () => {\n const doc = document.documentElement\n const max = doc.scrollHeight - window.innerHeight\n if (max <= 0 || (window.scrollY / max) * 100 >= 50) {\n convert()\n window.removeEventListener('scroll', onScroll)\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n cleanups.push(() => window.removeEventListener('scroll', onScroll))\n } else if (goal === 'timeOnPage') {\n const timer = setTimeout(convert, 30_000)\n cleanups.push(() => clearTimeout(timer))\n }\n return () => {\n for (const cleanup of cleanups) cleanup()\n }\n // Experiments are static per pageview (ISR props).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hostId, experiments.length && experiments[0]?.id])\n\n return null\n}\n\n/**\n * Site-event automations engine (AGL-256/257): arms the page's triggers\n * (scroll depth, element visibility/clicks, exit intent, dwell time),\n * runs each fired action's CLIENT steps in the browser, and dispatches\n * actions with server steps to /api/events/dispatch. Every trigger fires\n * at most once per pageview.\n */\nfunction AutomationsEngine(props: {\n hostId?: string\n automations: ClientAutomation[]\n /** Host routing map (screen id → slug) for rename-safe redirects. */\n screens?: Record<string, string>\n onShowOverlay: (overlayId: string) => void\n}) {\n const { hostId, automations, screens, onShowOverlay } = props\n const showOverlayRef = useRef(onShowOverlay)\n showOverlayRef.current = onShowOverlay\n\n useEffect(() => {\n if (!hostId || !automations.length) return undefined\n const fired = new Set<string>()\n const cleanups: Array<() => void> = []\n\n const showToast = (\n message: string,\n severity: 'info' | 'success' | 'warning' | 'error',\n ) => {\n const toast = document.createElement('div')\n toast.textContent = message\n toast.setAttribute('role', 'status')\n Object.assign(toast.style, {\n position: 'fixed',\n bottom: '16px',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: '2147483000',\n padding: '10px 16px',\n borderRadius: '8px',\n fontSize: '14px',\n fontFamily: 'system-ui, sans-serif',\n color: '#fff',\n backgroundColor:\n severity === 'error'\n ? '#c62828'\n : severity === 'warning'\n ? '#e65100'\n : severity === 'success'\n ? '#2e7d32'\n : 'rgba(0, 0, 0, 0.85)',\n maxWidth: '90vw',\n })\n document.body.appendChild(toast)\n setTimeout(() => toast.remove(), 6000)\n }\n\n const runClientSteps = (automation: ClientAutomation) => {\n for (const step of automation.steps) {\n try {\n if (\n step.type === 'addClass' ||\n step.type === 'removeClass' ||\n step.type === 'toggleClass'\n ) {\n // Expand the raw-id selector to also match the layout-composed\n // live id (AGL-573); non-leaf selectors are unchanged.\n const targets = document.querySelectorAll(\n Aglyn.expandLeafSelector(step.selector),\n )\n targets.forEach((element) => {\n if (step.type === 'addClass') {\n element.classList.add(step.className)\n } else if (step.type === 'removeClass') {\n element.classList.remove(step.className)\n } else {\n element.classList.toggle(step.className)\n }\n })\n } else if (\n step.type === 'setAttribute' ||\n step.type === 'removeAttribute'\n ) {\n /*\n The semantics half of a hand-built disclosure (AGL-2546).\n\n Deliberately in THIS loop rather than behind a guard of its own:\n it then inherits exactly the gating the visibility steps have,\n including which surfaces mount the runtime at all. A separate\n path reaching `document.querySelector` directly is how this\n would come to run somewhere `showElement` does not.\n\n The name is re-checked here and not only in the editor. The\n editor is a convenience; a step can reach this runtime from a\n document written before the allowlist existed, or by any route\n that does not pass through the console UI.\n\n A rejected name is a NO-OP, not a throw — the `catch` around\n this loop would otherwise let one bad attribute name silently\n drop every step after it in the same automation.\n */\n if (Aglyn.isInteractionAttributeAllowed(step.name)) {\n const name = step.name.trim().toLowerCase()\n const targets = document.querySelectorAll(\n Aglyn.expandLeafSelector(step.selector),\n )\n targets.forEach((element) => {\n if (step.type === 'setAttribute') {\n element.setAttribute(name, step.value ?? '')\n } else {\n element.removeAttribute(name)\n }\n })\n }\n } else if (step.type === 'scrollTo') {\n // One target, the first one on screen (AGL-2867). A target that\n // is missing, deleted or hidden makes the step a no-op, and the\n // steps after it in this automation still run.\n Aglyn.runScrollToStep(Aglyn.expandLeafSelector(step.selector), {\n behavior: step.behavior,\n offsetPx: step.offsetPx,\n })\n } else if (step.type === 'playVideo') {\n // The Video element's own poster press, sent to the element: the\n // player loads only now, exactly as it would for a click on the\n // poster, and under the same consent rules.\n Aglyn.runPlayVideoStep(Aglyn.expandLeafSelector(step.selector))\n } else if (step.type === 'stickyNav') {\n const target = document.querySelector(\n Aglyn.expandLeafSelector(step.selector?.trim() || 'header, nav'),\n )\n if (target instanceof HTMLElement) {\n target.style.position = 'sticky'\n target.style.top = '0'\n target.style.zIndex = '1100'\n }\n } else if (step.type === 'showHtml') {\n const container = document.createElement('div')\n // Sanitize (AGL-504): unlike runJs, showHtml is NOT dropped by the\n // JS entitlement gate, so raw innerHTML would let any automations-\n // tier author execute event-handler attributes (<img onerror>).\n //\n // ONE policy for the surface (AGL-2486). AGL-1901 moved rich text\n // and Custom HTML onto `sanitizeAuthorHtml`; this call was the\n // last raw DOMPurify left on a published page, and two sanitizers\n // with different rules on one surface is worse than the weaker of\n // them — a reviewer reads the strict one and assumes it covers\n // both. It did not: DOMPurify filters NO CSS, so every `style`\n // attribute arriving here reached the visitor unexamined while\n // the Custom HTML block beside it went through `sanitizeAuthorCss`.\n //\n // Nothing this used to refuse is now allowed. `sanitizeAuthorHtml`\n // is a strict SUBSET of the DOMPurify config it replaces, and that\n // is measured rather than asserted: `rich-text-hydration.spec.tsx`\n // holds this exact former config as `referenceShowHtmlPurify` and\n // runs the shared corpus through both. So the change is only in\n // what it ADDITIONALLY refuses:\n //\n // - `style` now gets the CSS rule — `http:` and unknown-scheme\n // `url()` neutered to `about:invalid`, and `@import`,\n // `expression()`, `behavior:` and `-moz-binding` dropping the\n // declaration whole. Character references are decoded BEFORE\n // the scheme is judged, which the old config did not do: it\n // emitted `url(&#104;ttp://…)` as a literal `http://`.\n // - `<form>` stops being an element. The former FORBID_TAGS here\n // listed `script, iframe, object, embed, base` and omitted\n // `form` — alone among this repo's author-HTML configs, both of\n // which forbade it — so a password field on the owner's live\n // page was one paste away.\n //\n // What is deliberately NOT refused, on either side of the change:\n // a third-party `https:` `url()`, and `position:fixed` / `z-index`.\n // The first is AGL-1725's actor analysis (the site owner chooses\n // recipients for their own visitors); the second is a capability\n // the Styles panel already gives the same author as a first-class\n // field, so refusing it only here would move nothing.\n container.innerHTML = Aglyn.sanitizeAuthorHtml(step.html)\n document.body.appendChild(container)\n } else if (step.type === 'runJs') {\n // Business-gated server-side (dropped from props otherwise);\n // the site owner's own code running on their own page.\n // eslint-disable-next-line no-new-func\n new Function(step.code)()\n } else if (step.type === 'redirect') {\n // Screen targets resolve through the routing map (AGL-339) so\n // slug renames never break the interaction; url is the manual\n // fallback.\n const screenSlug =\n (step as any).screenId != null\n ? screens?.[(step as any).screenId]\n : undefined\n const destination =\n screenSlug != null\n ? Aglyn.screenRoutePathToUrl(screenSlug)\n : step.url\n if (destination) window.location.assign(destination)\n } else if (\n step.type === 'showElement' ||\n step.type === 'hideElement' ||\n step.type === 'toggleElement'\n ) {\n // Element choreography (AGL-562): class-based so \"show\"\n // reveals targets the author started hidden. The tenant page\n // ships the hidden-class rule in its SSR HTML; ensure is the\n // fallback for other embeddings. Grace delays + Escape/\n // outside-click dismissal ride the same step (AGL-589).\n Aglyn.ensureElementHiddenStyle()\n Aglyn.runElementVisibilityStep(\n step.type === 'showElement'\n ? 'show'\n : step.type === 'hideElement'\n ? 'hide'\n : 'toggle',\n // Expand so a show/hide/toggle authored against the raw\n // canvas id still reaches the layout-composed node (AGL-573).\n Aglyn.expandLeafSelector(step.selector),\n {\n delayMs: (step as { delayMs?: number }).delayMs,\n dismissOn: (\n step as { dismissOn?: Aglyn.ElementDismissOption[] }\n ).dismissOn,\n },\n )\n } else if (\n step.type === 'openDrawer' ||\n step.type === 'closeDrawer' ||\n step.type === 'toggleDrawer'\n ) {\n // Drawer commands (AGL-562) ride the window event bus; the\n // muiDrawer element answers (first drawer for broadcasts).\n Aglyn.dispatchDrawerCommand(\n step.type === 'openDrawer'\n ? 'open'\n : step.type === 'closeDrawer'\n ? 'close'\n : 'toggle',\n step.drawerNodeId || undefined,\n )\n } else if (\n step.type === 'openMenu' ||\n step.type === 'closeMenu' ||\n step.type === 'toggleMenu'\n ) {\n // Menu commands (AGL-568) ride their own event bus like\n // drawers; the nav-menu elements answer (first menu for\n // broadcasts). A hover-enter trigger stamps the hover flag\n // so a menu opened this way closes itself when the pointer\n // leaves the trigger + panel surface.\n Aglyn.dispatchMenuCommand(\n step.type === 'openMenu'\n ? 'open'\n : step.type === 'closeMenu'\n ? 'close'\n : 'toggle',\n step.menuNodeId || undefined,\n { hover: automation.event === 'elementHoverEnter' },\n )\n } else if (step.type === 'trackGaEvent') {\n // AGL-1587: the name and the params are AUTHORED, which makes\n // this the least trustworthy analytics input in the repo — a\n // param could carry a form field's value. It goes through the\n // shared sanitizer and the reserved-name refusal like everything\n // else, never raw gtag.\n trackAuthoredEvent(step.eventName, step.params)\n } else if (step.type === 'siteAlert') {\n showToast(\n String(step.message ?? '').slice(0, 300),\n step.severity ?? 'info',\n )\n } else if (step.type === 'showOverlay') {\n if (step.overlayId) showOverlayRef.current(step.overlayId)\n }\n } catch (error) {\n console.error('automation step failed', error)\n }\n }\n }\n\n const fire = (automation: ClientAutomation) => {\n // Repeatable UI choreography (AGL-562): everyTime automations skip\n // the once-per-pageview gate (explicit caps below still apply).\n if (!automation.everyTime) {\n if (fired.has(automation.id)) return\n fired.add(automation.id)\n }\n // Once per visitor (AGL-266): a persisted flag outlives the pageview.\n if (automation.oncePerVisitor) {\n const key = `aglyn:auto:${automation.id}`\n try {\n if (localStorage.getItem(key)) return\n localStorage.setItem(key, '1')\n } catch {\n // Storage unavailable — degrade to once per pageview.\n }\n } else if (automation.oncePerSession) {\n // Once per session (AGL-274): survives navigation, not the tab.\n const key = `aglyn:auto:${automation.id}`\n try {\n if (sessionStorage.getItem(key)) return\n sessionStorage.setItem(key, '1')\n } catch {\n // Storage unavailable — degrade to once per pageview.\n }\n } else if (automation.cooldownMinutes) {\n // Cooldown (AGL-274): a timestamp gates re-fires for the visitor.\n const key = `aglyn:auto:${automation.id}:at`\n try {\n const last = Number(localStorage.getItem(key) ?? 0)\n if (\n last &&\n Date.now() - last < automation.cooldownMinutes * 60_000\n ) {\n return\n }\n localStorage.setItem(key, String(Date.now()))\n } catch {\n // Storage unavailable — degrade to once per pageview.\n }\n }\n runClientSteps(automation)\n if (automation.hasServerSteps) {\n void fetch('/api/events/dispatch', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n actionId: automation.id,\n event: automation.event,\n payload: { path: window.location.pathname },\n }),\n keepalive: true,\n }).catch(() => undefined)\n }\n }\n\n /**\n * Elements that arrive AFTER this effect binds (AGL-2512).\n *\n * `elementVisible` and `scrollToElement` are the only two triggers that\n * resolve their targets by querying the DOM — every other one listens on\n * `document` and so needs no element to exist yet. A single query at bind\n * time made them dead on the two pages where the tree lands late: a\n * deferred lazy panel patched back in on interaction (AGL-1285), and a\n * gated screen's tree swapped in once the visitor is past the gate\n * (AGL-2510).\n *\n * One MutationObserver for all of them, not one each, and it stops the\n * moment nothing is left watching — these triggers fire once per pageview\n * by construction, so a page whose targets have all been seen pays\n * nothing for the rest of the visit. A page with no such automation never\n * starts one at all.\n */\n const pendingObservers: Array<() => void> = []\n let domObserver: MutationObserver | null = null\n const rescan = () => {\n for (const attach of [...pendingObservers]) attach()\n if (!pendingObservers.length) {\n domObserver?.disconnect()\n domObserver = null\n }\n }\n const watchLateElements = (attach: () => void) => {\n pendingObservers.push(attach)\n if (domObserver || typeof MutationObserver === 'undefined') return\n domObserver = new MutationObserver(rescan)\n domObserver.observe(document.body, { childList: true, subtree: true })\n }\n const stopWatching = (attach: () => void) => {\n const index = pendingObservers.indexOf(attach)\n if (index >= 0) pendingObservers.splice(index, 1)\n if (!pendingObservers.length) {\n domObserver?.disconnect()\n domObserver = null\n }\n }\n cleanups.push(() => {\n pendingObservers.length = 0\n domObserver?.disconnect()\n domObserver = null\n })\n\n for (const automation of automations) {\n const { event, threshold } = automation\n // Composition namespaces a node's live `data-aglyn` id, but the\n // interaction builder records the RAW canvas id in the selector.\n // Expand it so the trigger still matches the live element — layouts\n // (AGL-573) and reusable-component grafts (AGL-1229), the latter being\n // why every interaction authored inside the Site nav bound to nothing.\n // Hand-typed CSS selectors pass through untouched.\n const selector = automation.selector\n ? Aglyn.expandLeafSelector(automation.selector)\n : automation.selector\n if (event === 'pageVisit') {\n fire(automation)\n } else if (event === 'timeOnPage') {\n const timer = setTimeout(\n () => fire(automation),\n Math.max(1, threshold ?? 5) * 1000,\n )\n cleanups.push(() => clearTimeout(timer))\n } else if (event === 'scrollDepth') {\n const onScroll = () => {\n const doc = document.documentElement\n const max = doc.scrollHeight - window.innerHeight\n const percent = max > 0 ? (window.scrollY / max) * 100 : 100\n if (percent >= Math.min(100, Math.max(1, threshold ?? 50))) {\n fire(automation)\n window.removeEventListener('scroll', onScroll)\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n cleanups.push(() => window.removeEventListener('scroll', onScroll))\n } else if (event === 'elementVisible' || event === 'scrollToElement') {\n if (!selector) continue\n let fired = false\n const observer = new IntersectionObserver((entries) => {\n if (fired || !entries.some((entry) => entry.isIntersecting)) return\n fired = true\n fire(automation)\n observer.disconnect()\n stopWatching(attachTargets)\n })\n // Re-entrant: called again on every DOM change until the trigger\n // fires, and observing an element twice is a no-op, so a rescan costs\n // one `querySelectorAll` and nothing else.\n const attachTargets = () => {\n if (fired) return stopWatching(attachTargets)\n document\n .querySelectorAll(selector)\n .forEach((target) => observer.observe(target))\n }\n attachTargets()\n watchLateElements(attachTargets)\n cleanups.push(() => observer.disconnect())\n } else if (event === 'elementClick') {\n if (!selector) continue\n const onClick = (mouseEvent: MouseEvent) => {\n const target = mouseEvent.target as Element | null\n if (target?.closest?.(selector)) fire(automation)\n }\n document.addEventListener('click', onClick, true)\n cleanups.push(() =>\n document.removeEventListener('click', onClick, true),\n )\n } else if (\n event === 'elementHoverEnter' ||\n event === 'elementHoverLeave'\n ) {\n // Hover choreography (AGL-562): delegated mouseover/mouseout with\n // enter/leave semantics — moves WITHIN the matched element (its\n // own children) never re-fire.\n if (!selector) continue\n const onHover = (mouseEvent: MouseEvent) => {\n const target = mouseEvent.target as Element | null\n const match = target?.closest?.(selector)\n if (!match) return\n const related = mouseEvent.relatedTarget as Element | null\n if (related && match.contains(related)) return\n fire(automation)\n }\n const type = event === 'elementHoverEnter' ? 'mouseover' : 'mouseout'\n document.addEventListener(type, onHover, true)\n cleanups.push(() =>\n document.removeEventListener(type, onHover, true),\n )\n } else if (event === 'exitIntent') {\n const onLeave = (mouseEvent: MouseEvent) => {\n if (mouseEvent.clientY <= 0) fire(automation)\n }\n document.addEventListener('mouseleave', onLeave)\n cleanups.push(() => document.removeEventListener('mouseleave', onLeave))\n }\n }\n return () => {\n for (const cleanup of cleanups) cleanup()\n }\n // Automations are static per pageview (ISR props).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n hostId,\n screens,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(automations.map((automation) => automation.id)),\n ])\n\n return null\n}\n\nfunction AnnouncementBar(props: {\n bar: AnnouncementBarData\n hostId?: string\n}) {\n const { bar, hostId } = props\n const storageKey = `aglyn-abar-${bar.contentHash}`\n const [hidden, setHidden] = useState(true)\n useEffect(() => {\n try {\n setHidden(Boolean(window.localStorage.getItem(storageKey)))\n } catch {\n setHidden(false)\n }\n }, [storageKey])\n // Impression (AGL-271): once per pageview, only when actually shown.\n useEffect(() => {\n if (!hidden) sendOverlayBeacon(hostId, 'barImpression', bar.overlayId)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hidden])\n if (hidden) return null\n const style: CSSProperties = {\n position: 'relative',\n zIndex: 1300,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 8,\n padding: '8px 40px 8px 16px',\n fontSize: 14,\n fontFamily: 'system-ui, sans-serif',\n textAlign: 'center',\n color: bar.textColor || '#fff',\n backgroundColor: bar.backgroundColor || '#111827',\n }\n const text = bar.href ? (\n <a\n href={bar.href}\n onClick={() => sendOverlayBeacon(hostId, 'barClick', bar.overlayId)}\n style={{ color: 'inherit', textDecoration: 'underline' }}\n >\n {bar.text}\n </a>\n ) : (\n <span>{bar.text}</span>\n )\n return (\n <div role=\"region\" aria-label=\"Announcement\" style={style}>\n {text}\n {bar.dismissible ? (\n <button\n type=\"button\"\n aria-label=\"Dismiss announcement\"\n onClick={() => {\n try {\n window.localStorage.setItem(storageKey, '1')\n } catch {\n // Storage may be unavailable (private mode); hide anyway.\n }\n sendOverlayBeacon(hostId, 'barDismiss', bar.overlayId)\n setHidden(true)\n }}\n style={{\n position: 'absolute',\n right: 8,\n top: '50%',\n transform: 'translateY(-50%)',\n border: 'none',\n background: 'transparent',\n color: 'inherit',\n fontSize: 16,\n lineHeight: 1,\n cursor: 'pointer',\n padding: 6,\n }}\n >\n {'✕'}\n </button>\n ) : null}\n </div>\n )\n}\n\n/**\n * Promotional popup (AGL-196). Client owns: schedule-window re-check (the\n * page is ISR-cached), trigger timing (delay/scroll/exit), and frequency\n * capping via a per-content-hash localStorage stamp (no cookies). ESC and\n * backdrop close; reduced-motion preferences skip the entrance ease.\n */\nfunction PopupOverlay(props: {\n popup: PopupData\n hostId?: string\n}) {\n const { popup, hostId } = props\n const storageKey = `aglyn-popup-${popup.contentHash}`\n const [open, setOpen] = useState(false)\n // Email capture (AGL-200): submits into the forms pipeline (inbox +\n // contacts); success suppresses the popup for ~10 years.\n const [email, setEmail] = useState('')\n // The honeypot's value, held in state so whatever a bot typed into the\n // hidden input below is what gets POSTed (AGL-1665). This used to be a\n // hardcoded `website: ''` in the request body: the route drops a\n // submission only when the field is NON-empty, so a constant empty string\n // never failed the check — it removed it. There was no field on the page\n // to fill and no value a script could set, which made the popup the one\n // form surface on the site with no honeypot at all.\n const [website, setWebsite] = useState('')\n const [submitted, setSubmitted] = useState(false)\n\n useEffect(() => {\n if (open) sendOverlayBeacon(hostId, 'popupImpression', popup.overlayId)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, hostId])\n\n useEffect(() => {\n const now = Date.now()\n if (popup.startAtMs && now < popup.startAtMs) return\n if (popup.endAtMs && now > popup.endAtMs) return\n try {\n // The decision itself is a pure function in the model (AGL-2174) —\n // which store to read is the whole feature, and it has to agree with\n // what `close` writes.\n const suppressed = MarketingModel.popupSuppressed(\n popup,\n MarketingModel.popupCapStore(popup) === 'session'\n ? { sessionFlag: window.sessionStorage.getItem(storageKey) }\n : { lastShownMs: Number(window.localStorage.getItem(storageKey) ?? 0) },\n now,\n )\n if (suppressed) return\n } catch {\n // Storage unavailable: show at most per-pageview.\n }\n let cleanup: (() => void) | undefined\n if (popup.trigger === 'scroll') {\n const threshold = Math.min(100, Math.max(0, popup.triggerValue)) / 100\n const onScroll = () => {\n const height =\n document.documentElement.scrollHeight - window.innerHeight\n if (height <= 0 || window.scrollY / height >= threshold) {\n setOpen(true)\n }\n }\n window.addEventListener('scroll', onScroll, { passive: true })\n cleanup = () => window.removeEventListener('scroll', onScroll)\n } else if (popup.trigger === 'exit') {\n const onLeave = (event: MouseEvent) => {\n if (event.clientY <= 0) setOpen(true)\n }\n document.addEventListener('mouseout', onLeave)\n cleanup = () => document.removeEventListener('mouseout', onLeave)\n } else {\n const timer = window.setTimeout(\n () => setOpen(true),\n Math.max(0, popup.triggerValue) * 1000,\n )\n cleanup = () => window.clearTimeout(timer)\n }\n return cleanup\n }, [popup, storageKey])\n\n const close = (kind: 'popupDismiss' | 'popupClick' = 'popupDismiss') => {\n try {\n // Written to whichever store the cap READS (AGL-2174). Stamping\n // `localStorage` for a session-capped popup would leave a timestamp\n // nothing reads, outliving the cap it was meant to record.\n if (MarketingModel.popupCapStore(popup) === 'session') {\n window.sessionStorage.setItem(storageKey, '1')\n } else {\n window.localStorage.setItem(storageKey, String(Date.now()))\n }\n } catch {\n // Private mode etc. — closing still works for this pageview.\n }\n sendOverlayBeacon(hostId, kind, popup.overlayId)\n setOpen(false)\n }\n\n const handleEmailSubmit = async () => {\n const value = email.trim()\n if (!value || submitted) return\n try {\n const response = await fetch('/api/forms/submit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n // The door this capture comes through (AGL-3029): the popup is a\n // Marketing element, so a site that switched Forms off still\n // collects the address it shows the popup for.\n door: 'popup',\n formName: 'Popup',\n fields: { email: value },\n path: window.location.pathname,\n // Submitted AS-IS (AGL-1665) — the point of a honeypot is that the\n // client never judges it. `libs/plugins/mui/.../form.tsx` reads its\n // own hidden `website` input off the FormData and forwards it the\n // same way; `/api/forms/submit` is the single place that decides.\n website,\n // The campaign this visitor came from, when they came from one. A\n // popup capture is often a site's highest-converting door, so it\n // reports its campaign for the same reason it reports its lead.\n ...utmTouchField(),\n }),\n })\n // The popup's email capture is a lead, and it reported none: an\n // announcement popup is often a site's highest-converting capture, and\n // the merchant saw the impression and the dismiss (`aglyn_overlay`) with\n // nothing in between. The generic form block has sent `generate_lead`\n // since AGL-1561; this door was simply never wired to it.\n //\n // Gated on `response.ok`, unlike the visitor-facing thank-you below.\n // The two disagree deliberately: a spam-refused or rate-limited capture\n // is still shown the thank-you — telling a real visitor to try again\n // after a honeypot verdict would leak the honeypot — but it is NOT a\n // lead, and counting it would inflate the only number the merchant uses\n // to judge whether the popup is worth interrupting people with.\n //\n // `form_name` is the block's own name, matching the `formName` on the\n // wire; the address the visitor just typed never leaves this function.\n if (response.ok) {\n trackEvent('generate_lead', {\n form_name: 'Popup',\n form_location: window.location.pathname,\n })\n }\n } catch {\n // Best-effort — still thank the visitor.\n }\n setSubmitted(true)\n try {\n // Far-future stamp: a successful capture never re-prompts.\n window.localStorage.setItem(\n storageKey,\n String(Date.now() + 315360000000),\n )\n } catch {\n // Ignore.\n }\n }\n\n useEffect(() => {\n if (!open) return\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') close()\n }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open])\n\n if (!open) return null\n return (\n <div\n onClick={() => close()}\n style={{\n position: 'fixed',\n inset: 0,\n zIndex: 2147483200,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n padding: 16,\n }}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={popup.headline || 'Announcement'}\n onClick={(event) => event.stopPropagation()}\n style={{\n maxWidth: 420,\n width: '100%',\n background: '#fff',\n color: '#111827',\n borderRadius: 12,\n overflow: 'hidden',\n boxShadow: '0 24px 64px rgba(0, 0, 0, 0.35)',\n fontFamily: 'system-ui, sans-serif',\n position: 'relative',\n }}\n >\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={() => close()}\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n border: 'none',\n background: 'rgba(255, 255, 255, 0.85)',\n borderRadius: '50%',\n width: 28,\n height: 28,\n cursor: 'pointer',\n fontSize: 14,\n lineHeight: 1,\n }}\n >\n {'✕'}\n </button>\n {/* The popup image is a free-text console field rendered verbatim —\n one of AGL-1725's raw author sinks. Scheme rule only, never a\n host check: `http:` and unknown schemes render nothing;\n https/relative (the media picker's forms) render as stored,\n except a library file's Storage URL, which the resolver routes\n through the site's CDN like every other image (AGL-3506). */}\n {popup.imageUrl && !Aglyn.isRefusedAuthorImageSrc(popup.imageUrl) ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={Aglyn.siteRelativeMediaSrc(popup.imageUrl, { hostId })}\n // AGL-1896. This was a hardcoded `alt=\"\"` with no field behind\n // it. Still empty when the author left it empty — a decorative\n // banner beside its own headline is the case `alt=\"\"` exists for\n // — but it is now their choice rather than ours, and picking the\n // image from the library fills it in from the asset.\n alt={popup.imageAlt ?? ''}\n style={{\n width: '100%',\n maxHeight: 200,\n objectFit: 'cover',\n display: 'block',\n }}\n />\n ) : null}\n <div style={{ padding: 24, textAlign: 'center' }}>\n {popup.headline ? (\n <h2 style={{ margin: '0 0 8px', fontSize: 20 }}>\n {popup.headline}\n </h2>\n ) : null}\n <p style={{ margin: 0, fontSize: 14, whiteSpace: 'pre-wrap' }}>\n {popup.body}\n </p>\n {popup.collectEmail ? (\n <div style={{ marginTop: 16 }}>\n {submitted ? (\n <p style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>\n {'Thanks — you are on the list!'}\n </p>\n ) : (\n <form\n onSubmit={(event) => {\n event.preventDefault()\n void handleEmailSubmit()\n }}\n style={{ display: 'flex', gap: 8, justifyContent: 'center' }}\n >\n <input\n type=\"email\"\n required\n placeholder=\"you@example.com\"\n // Same nameless-input defect as the newsletter block\n // (AGL-2392). A popup is modal-ish and arrives unbidden,\n // so a screen-reader user meets this field with no\n // surrounding context at all.\n aria-label=\"Email address\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n style={{\n flex: 1,\n maxWidth: 240,\n padding: '8px 12px',\n borderRadius: 8,\n border: '1px solid #d1d5db',\n fontSize: 14,\n }}\n />\n {/* Honeypot: humans never see or fill this (AGL-1665).\n Off-screen rather than `display:none`/`hidden`, and\n named `website`, so the naive form-filling bots the\n route's check is aimed at treat it as an ordinary\n field — the same bait, presented the same way, as the\n site form's. Out of flow, so the flex row above is\n unchanged. */}\n <input\n type=\"text\"\n name=\"website\"\n tabIndex={-1}\n autoComplete=\"off\"\n aria-hidden=\"true\"\n value={website}\n onChange={(event) => setWebsite(event.target.value)}\n style={{\n position: 'absolute',\n left: '-5000px',\n height: 0,\n width: 0,\n }}\n />\n <button\n type=\"submit\"\n style={{\n padding: '8px 16px',\n borderRadius: 8,\n border: 'none',\n background: '#111827',\n color: '#fff',\n fontSize: 14,\n cursor: 'pointer',\n }}\n >\n {'Sign up'}\n </button>\n </form>\n )}\n </div>\n ) : null}\n {popup.ctaHref && popup.ctaLabel ? (\n <a\n href={popup.ctaHref}\n onClick={() => close('popupClick')}\n style={{\n display: 'inline-block',\n marginTop: 16,\n padding: '10px 24px',\n borderRadius: 8,\n background: '#111827',\n color: '#fff',\n textDecoration: 'none',\n fontSize: 14,\n }}\n >\n {popup.ctaLabel}\n </a>\n ) : null}\n </div>\n </div>\n </div>\n )\n}\n\n\n/**\n * The marketing plugin's site runtime (AGL-419), relocated verbatim from\n * the tenant catch-all: announcement bar + popup rendering (AGL-195/200),\n * the experiments runner (AGL-253), the site-event automations engine\n * (AGL-256/257), and automation-triggered overlays. Reads back exactly the\n * page-props slices its server enricher wrote (site-contract shapes).\n */\nexport function MarketingSiteRuntime({ hostId, screens, page }: SiteRuntimeProps) {\n const [automationOverlay, setAutomationOverlay] = useState<any>(null)\n const announcementBar = page['announcementBar'] as AnnouncementBarData | null\n const popup = page['popup'] as PopupData | null\n const experiments = (page['experiments'] ?? []) as ScreenExperiment[]\n const clientAutomations = (page['clientAutomations'] ?? []) as ClientAutomation[]\n const automationOverlays = page['automationOverlays'] as Record<string, any> | null\n\n return (\n <>\n {announcementBar ? (\n <AnnouncementBar bar={announcementBar} hostId={hostId} />\n ) : null}\n {popup ? <PopupOverlay popup={popup} hostId={hostId} /> : null}\n {/* Screen/section experiments (AGL-253). */}\n {experiments.length ? (\n <ExperimentsRunner\n hostId={hostId}\n experiments={experiments}\n consentHost={page['data']?.host as Aglyn.VisitorConsentHost | null}\n />\n ) : null}\n {/* Site-event automations (AGL-256/257). */}\n {clientAutomations.length ? (\n <AutomationsEngine\n hostId={hostId}\n automations={clientAutomations}\n screens={screens}\n onShowOverlay={(overlayId) => {\n const overlay = automationOverlays?.[overlayId]\n if (overlay) setAutomationOverlay({ id: overlayId, ...overlay })\n }}\n />\n ) : null}\n {automationOverlay?.kind === 'bar' && automationOverlay.bar?.text ? (\n <AnnouncementBar\n bar={{\n ...automationOverlay.bar,\n text: String(automationOverlay.bar.text),\n dismissible: automationOverlay.bar.dismissible !== false,\n contentHash: `automation-${automationOverlay.id}`,\n }}\n hostId={hostId}\n />\n ) : null}\n {automationOverlay?.kind === 'popup' && automationOverlay.popup?.body ? (\n <PopupOverlay\n popup={{\n ...automationOverlay.popup,\n body: String(automationOverlay.popup.body),\n trigger: 'delay',\n triggerValue: 0,\n frequencyDays: Math.max(\n 1,\n Number(automationOverlay.popup.frequencyDays ?? 1),\n ),\n contentHash: `automation-${automationOverlay.id}`,\n }}\n hostId={hostId}\n />\n ) : null}\n </>\n )\n}\n"],"names":["Aglyn","sendAnalyticsBeacon","trackAuthoredEvent","trackEvent","utmTouchField","useEffect","useRef","useState","MarketingModel","sendOverlayBeacon","hostId","overlay","overlayId","overlay_action","overlay_id","ExperimentsRunner","props","experiments","consentHost","experiment","length","undefined","persistence","resolveVisitorIdPersistence","readStoredVisitorConsent","visitorId","storage","localStorage","sessionStorage","getItem","VISITOR_ID_STORAGE_KEY","Math","random","toString","slice","Date","now","setItem","removeItem","variant","assignExperimentVariant","status","variants","winnerVariantId","endAtMs","id","payload","payloads","canvas","setNodes","beacon","kind","fetch","method","headers","body","JSON","stringify","experimentId","variantId","keepalive","catch","experiment_id","variant_id","experiment_action","cleanups","converted","convert","goal","event","onSubmit","document","addEventListener","push","removeEventListener","selector","filter","trim","onClick","target","closest","onScroll","doc","documentElement","max","scrollHeight","window","innerHeight","scrollY","passive","timer","setTimeout","clearTimeout","cleanup","AutomationsEngine","automations","screens","onShowOverlay","showOverlayRef","current","fired","Set","showToast","message","severity","toast","createElement","textContent","setAttribute","Object","assign","style","position","bottom","left","transform","zIndex","padding","borderRadius","fontSize","fontFamily","color","backgroundColor","maxWidth","appendChild","remove","runClientSteps","automation","step","steps","type","targets","querySelectorAll","expandLeafSelector","forEach","element","classList","add","className","toggle","isInteractionAttributeAllowed","name","toLowerCase","value","removeAttribute","runScrollToStep","behavior","offsetPx","runPlayVideoStep","querySelector","HTMLElement","top","container","innerHTML","sanitizeAuthorHtml","html","Function","code","screenSlug","screenId","destination","screenRoutePathToUrl","url","location","ensureElementHiddenStyle","runElementVisibilityStep","delayMs","dismissOn","dispatchDrawerCommand","drawerNodeId","dispatchMenuCommand","menuNodeId","hover","eventName","params","String","error","console","fire","everyTime","has","oncePerVisitor","key","oncePerSession","cooldownMinutes","last","Number","hasServerSteps","actionId","path","pathname","pendingObservers","domObserver","rescan","attach","disconnect","watchLateElements","MutationObserver","observe","childList","subtree","stopWatching","index","indexOf","splice","threshold","percent","min","observer","IntersectionObserver","entries","some","entry","isIntersecting","attachTargets","mouseEvent","onHover","match","related","relatedTarget","contains","onLeave","clientY","map","AnnouncementBar","bar","storageKey","contentHash","hidden","setHidden","Boolean","display","alignItems","justifyContent","gap","textAlign","textColor","text","href","a","textDecoration","span","div","role","aria-label","dismissible","button","right","border","background","lineHeight","cursor","PopupOverlay","popup","open","setOpen","email","setEmail","website","setWebsite","submitted","setSubmitted","startAtMs","suppressed","popupSuppressed","popupCapStore","sessionFlag","lastShownMs","trigger","triggerValue","height","close","handleEmailSubmit","response","door","formName","fields","ok","form_name","form_location","onKey","inset","aria-modal","headline","stopPropagation","width","overflow","boxShadow","imageUrl","isRefusedAuthorImageSrc","img","src","siteRelativeMediaSrc","alt","imageAlt","maxHeight","objectFit","h2","margin","p","whiteSpace","collectEmail","marginTop","fontWeight","form","preventDefault","input","required","placeholder","onChange","flex","tabIndex","autoComplete","aria-hidden","ctaHref","ctaLabel","MarketingSiteRuntime","page","automationOverlay","setAutomationOverlay","announcementBar","clientAutomations","automationOverlays","host","frequencyDays"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,YAAYA,WAAW,eAAc;AACrC,SAASC,mBAAmB,QAAQ,0CAAyC;AAC7E,SACEC,kBAAkB,EAClBC,UAAU,QACL,0CAAyC;AAChD,SAASC,aAAa,QAAQ,mCAAkC;AAChE,SAA6BC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAEvE,YAAYC,oBAAoB,oBAAU;AAQ1C;;;;CAIC,GACD,SAASC,kBACPC,MAA0B,EAC1BC,OAAe,EACfC,SAAkB;IAElB,IAAI,CAACF,QAAQ;IACb,6EAA6E;IAC7E,wEAAwE;IACxE,mEAAmE;IACnE,4EAA4E;IAC5ET,oBAAoB;QAClBS;QACAC;OACIC,YAAY;QAAEA;IAAU,IAAI,CAAC;IAEnC,mEAAmE;IACnE,wDAAwD;IACxD,EAAE;IACF,yEAAyE;IACzE,2EAA2E;IAC3E,kDAAkD;IAClDT,WAAW,iBAAiB;QAC1BU,gBAAgBF;OACZC,YAAY;QAAEE,YAAYF;IAAU,IAAI,CAAC;AAEjD;AAEA;;;;CAIC,GACD;;;;;;;CAOC,GACD,SAASG,kBAAkBC,KAK1B;QA4HmCC;IA3HlC,MAAM,EAAEP,MAAM,EAAEO,WAAW,EAAEC,WAAW,EAAE,GAAGF;IAE7CX,UAAU;;YAwFKc;QAvFb,IAAI,CAACT,UAAU,CAACO,YAAYG,MAAM,EAAE,OAAOC;QAC3C,MAAMF,aAAaF,WAAW,CAAC,EAAE;QACjC,wEAAwE;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,uEAAuE;QACvE,iEAAiE;QACjE,sDAAsD;QACtD,MAAMK,cAActB,MAAMuB,2BAA2B,CACnDL,aACAlB,MAAMwB,wBAAwB,CAACd;QAEjC,IAAIe;QACJ,IAAI;gBAOAC,OAAAA,OAAAA;YANF,MAAMA,UACJJ,gBAAgB,UAAUK,eAAeC;YAC3C,qEAAqE;YACrE,mEAAmE;YACnE,qEAAqE;YACrEH,aACEC,SAAAA,SAAAA,mBAAAA,QAAQG,OAAO,CAAC7B,MAAM8B,sBAAsB,aAA5CJ,mBACAE,eAAeC,OAAO,CAAC7B,MAAM8B,sBAAsB,aADnDJ,QAEAC,aAAaE,OAAO,CAAC7B,MAAM8B,sBAAsB,aAFjDJ,QAGA;YACF,IAAI,CAACD,WAAW;gBACdA,YAAY,CAAC,EAAE,EAAEM,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC,KAAKC,KAAKC,GAAG,GAAGH,QAAQ,CAAC,KAAK;YAClF;YACAP,QAAQW,OAAO,CAACrC,MAAM8B,sBAAsB,EAAEL;YAC9C,sEAAsE;YACtE,wDAAwD;YACxD,IAAIH,gBAAgB,WAAW;gBAC7BK,aAAaW,UAAU,CAACtC,MAAM8B,sBAAsB;YACtD;QACF,EAAE,eAAM;YACN,OAAOT,UAAU,iDAAiD;;QACpE;QACA,MAAMkB,UAAU/B,eAAegC,uBAAuB,CACpD,+DAA+D;QAC/D;YAAEC,QAAQtB,WAAWsB,MAAM;YAAWC,UAAUvB,WAAWuB,QAAQ;WAC7DvB,WAAWwB,eAAe,GAC1B;YAAEA,iBAAiBxB,WAAWwB,eAAe;QAAC,IAC9C,CAAC,GAEDxB,WAAWyB,OAAO,GAAG;YAAEA,SAASzB,WAAWyB,OAAO;QAAC,IAAI,CAAC,IAC9DzB,WAAW0B,EAAE,EACbpB;QAEF,IAAI,CAACc,SAAS,OAAOlB;QACrB,MAAMyB,UAAU3B,WAAW4B,QAAQ,CAACR,QAAQM,EAAE,CAAC;QAC/C,IAAIC,SAAS9C,MAAMgD,MAAM,CAACC,QAAQ,CAACH;QAEnC,MAAMI,SAAS,CAACC;YACd,KAAKC,MAAM,0BAA0B;gBACnCC,QAAQ;gBACRC,SAAS;oBAAE,gBAAgB;gBAAmB;gBAC9CC,MAAMC,KAAKC,SAAS,CAAC;oBACnB/C;oBACAgD,cAAcvC,WAAW0B,EAAE;oBAC3Bc,WAAWpB,QAAQM,EAAE;oBACrBM;gBACF;gBACAS,WAAW;YACb,GAAGC,KAAK,CAAC,IAAMxC;YACf,8DAA8D;YAC9D,sEAAsE;YACtE,oEAAoE;YACpE,qEAAqE;YACrE,yCAAyC;YACzClB,WAAW,oBAAoB;gBAC7B2D,eAAe3C,WAAW0B,EAAE;gBAC5BkB,YAAYxB,QAAQM,EAAE;gBACtBmB,mBAAmBb;YACrB;QACF;QACA,gEAAgE;QAChE,IAAIhC,WAAWsB,MAAM,KAAK,WAAW,OAAOpB;QAC5C6B,OAAO;QAEP,kEAAkE;QAClE,oEAAoE;QACpE,MAAMe,WAA8B,EAAE;QACtC,IAAIC,YAAY;QAChB,MAAMC,UAAU;YACd,IAAID,WAAW;YACfA,YAAY;YACZhB,OAAO;QACT;QACA,MAAMkB,gBAAOjD,mBAAAA,WAAWiD,IAAI,qBAAfjD,iBAAiBkD,KAAK,mBAAI;QACvC,IAAID,SAAS,kBAAkB;YAC7B,MAAME,WAAW,IAAMH;YACvBI,SAASC,gBAAgB,CAAC,UAAUF,UAAU;YAC9CL,SAASQ,IAAI,CAAC,IAAMF,SAASG,mBAAmB,CAAC,UAAUJ,UAAU;QACvE,OAAO,IAAIF,SAAS,gBAAgB;gBACjBjD,yBAAAA;YAAjB,MAAMwD,WAAWxD,EAAAA,oBAAAA,WAAWiD,IAAI,sBAAfjD,0BAAAA,kBAAiByD,MAAM,qBAAvBzD,wBAAyB0D,IAAI,OAAM;YACpD,MAAMC,UAAU,CAACT;oBAEXU;gBADJ,MAAMA,SAASV,MAAMU,MAAM;gBAC3B,IAAIA,2BAAAA,kBAAAA,OAAQC,OAAO,qBAAfD,qBAAAA,QAAkBJ,WAAWR;YACnC;YACAI,SAASC,gBAAgB,CAAC,SAASM,SAAS;YAC5Cb,SAASQ,IAAI,CAAC,IAAMF,SAASG,mBAAmB,CAAC,SAASI,SAAS;QACrE,OAAO,IAAIV,SAAS,eAAe;YACjC,MAAMa,WAAW;gBACf,MAAMC,MAAMX,SAASY,eAAe;gBACpC,MAAMC,MAAMF,IAAIG,YAAY,GAAGC,OAAOC,WAAW;gBACjD,IAAIH,OAAO,KAAK,AAACE,OAAOE,OAAO,GAAGJ,MAAO,OAAO,IAAI;oBAClDjB;oBACAmB,OAAOZ,mBAAmB,CAAC,UAAUO;gBACvC;YACF;YACAK,OAAOd,gBAAgB,CAAC,UAAUS,UAAU;gBAAEQ,SAAS;YAAK;YAC5DxB,SAASQ,IAAI,CAAC,IAAMa,OAAOZ,mBAAmB,CAAC,UAAUO;QAC3D,OAAO,IAAIb,SAAS,cAAc;YAChC,MAAMsB,QAAQC,WAAWxB,SAAS;YAClCF,SAASQ,IAAI,CAAC,IAAMmB,aAAaF;QACnC;QACA,OAAO;YACL,KAAK,MAAMG,WAAW5B,SAAU4B;QAClC;IACA,mDAAmD;IACnD,uDAAuD;IACzD,GAAG;QAACnF;QAAQO,YAAYG,MAAM,MAAIH,gBAAAA,WAAW,CAAC,EAAE,qBAAdA,cAAgB4B,EAAE;KAAC;IAErD,OAAO;AACT;AAEA;;;;;;CAMC,GACD,SAASiD,kBAAkB9E,KAM1B;IACC,MAAM,EAAEN,MAAM,EAAEqF,WAAW,EAAEC,OAAO,EAAEC,aAAa,EAAE,GAAGjF;IACxD,MAAMkF,iBAAiB5F,OAAO2F;IAC9BC,eAAeC,OAAO,GAAGF;IAEzB5F,UAAU;QACR,IAAI,CAACK,UAAU,CAACqF,YAAY3E,MAAM,EAAE,OAAOC;QAC3C,MAAM+E,QAAQ,IAAIC;QAClB,MAAMpC,WAA8B,EAAE;QAEtC,MAAMqC,YAAY,CAChBC,SACAC;YAEA,MAAMC,QAAQlC,SAASmC,aAAa,CAAC;YACrCD,MAAME,WAAW,GAAGJ;YACpBE,MAAMG,YAAY,CAAC,QAAQ;YAC3BC,OAAOC,MAAM,CAACL,MAAMM,KAAK,EAAE;gBACzBC,UAAU;gBACVC,QAAQ;gBACRC,MAAM;gBACNC,WAAW;gBACXC,QAAQ;gBACRC,SAAS;gBACTC,cAAc;gBACdC,UAAU;gBACVC,YAAY;gBACZC,OAAO;gBACPC,iBACElB,aAAa,UACT,YACAA,aAAa,YACX,YACAA,aAAa,YACX,YACA;gBACVmB,UAAU;YACZ;YACApD,SAAShB,IAAI,CAACqE,WAAW,CAACnB;YAC1Bd,WAAW,IAAMc,MAAMoB,MAAM,IAAI;QACnC;QAEA,MAAMC,iBAAiB,CAACC;YACtB,KAAK,MAAMC,QAAQD,WAAWE,KAAK,CAAE;gBACnC,IAAI;oBACF,IACED,KAAKE,IAAI,KAAK,cACdF,KAAKE,IAAI,KAAK,iBACdF,KAAKE,IAAI,KAAK,eACd;wBACA,+DAA+D;wBAC/D,uDAAuD;wBACvD,MAAMC,UAAU5D,SAAS6D,gBAAgB,CACvCpI,MAAMqI,kBAAkB,CAACL,KAAKrD,QAAQ;wBAExCwD,QAAQG,OAAO,CAAC,CAACC;4BACf,IAAIP,KAAKE,IAAI,KAAK,YAAY;gCAC5BK,QAAQC,SAAS,CAACC,GAAG,CAACT,KAAKU,SAAS;4BACtC,OAAO,IAAIV,KAAKE,IAAI,KAAK,eAAe;gCACtCK,QAAQC,SAAS,CAACX,MAAM,CAACG,KAAKU,SAAS;4BACzC,OAAO;gCACLH,QAAQC,SAAS,CAACG,MAAM,CAACX,KAAKU,SAAS;4BACzC;wBACF;oBACF,OAAO,IACLV,KAAKE,IAAI,KAAK,kBACdF,KAAKE,IAAI,KAAK,mBACd;wBACA;;;;;;;;;;;;;;;;;YAiBA,GACA,IAAIlI,MAAM4I,6BAA6B,CAACZ,KAAKa,IAAI,GAAG;4BAClD,MAAMA,OAAOb,KAAKa,IAAI,CAAChE,IAAI,GAAGiE,WAAW;4BACzC,MAAMX,UAAU5D,SAAS6D,gBAAgB,CACvCpI,MAAMqI,kBAAkB,CAACL,KAAKrD,QAAQ;4BAExCwD,QAAQG,OAAO,CAAC,CAACC;gCACf,IAAIP,KAAKE,IAAI,KAAK,gBAAgB;wCACLF;oCAA3BO,QAAQ3B,YAAY,CAACiC,OAAMb,cAAAA,KAAKe,KAAK,YAAVf,cAAc;gCAC3C,OAAO;oCACLO,QAAQS,eAAe,CAACH;gCAC1B;4BACF;wBACF;oBACF,OAAO,IAAIb,KAAKE,IAAI,KAAK,YAAY;wBACnC,gEAAgE;wBAChE,gEAAgE;wBAChE,+CAA+C;wBAC/ClI,MAAMiJ,eAAe,CAACjJ,MAAMqI,kBAAkB,CAACL,KAAKrD,QAAQ,GAAG;4BAC7DuE,UAAUlB,KAAKkB,QAAQ;4BACvBC,UAAUnB,KAAKmB,QAAQ;wBACzB;oBACF,OAAO,IAAInB,KAAKE,IAAI,KAAK,aAAa;wBACpC,iEAAiE;wBACjE,gEAAgE;wBAChE,4CAA4C;wBAC5ClI,MAAMoJ,gBAAgB,CAACpJ,MAAMqI,kBAAkB,CAACL,KAAKrD,QAAQ;oBAC/D,OAAO,IAAIqD,KAAKE,IAAI,KAAK,aAAa;4BAETF;wBAD3B,MAAMjD,SAASR,SAAS8E,aAAa,CACnCrJ,MAAMqI,kBAAkB,CAACL,EAAAA,iBAAAA,KAAKrD,QAAQ,qBAAbqD,eAAenD,IAAI,OAAM;wBAEpD,IAAIE,kBAAkBuE,aAAa;4BACjCvE,OAAOgC,KAAK,CAACC,QAAQ,GAAG;4BACxBjC,OAAOgC,KAAK,CAACwC,GAAG,GAAG;4BACnBxE,OAAOgC,KAAK,CAACK,MAAM,GAAG;wBACxB;oBACF,OAAO,IAAIY,KAAKE,IAAI,KAAK,YAAY;wBACnC,MAAMsB,YAAYjF,SAASmC,aAAa,CAAC;wBACzC,mEAAmE;wBACnE,mEAAmE;wBACnE,gEAAgE;wBAChE,EAAE;wBACF,kEAAkE;wBAClE,+DAA+D;wBAC/D,kEAAkE;wBAClE,kEAAkE;wBAClE,+DAA+D;wBAC/D,+DAA+D;wBAC/D,+DAA+D;wBAC/D,oEAAoE;wBACpE,EAAE;wBACF,mEAAmE;wBACnE,mEAAmE;wBACnE,mEAAmE;wBACnE,kEAAkE;wBAClE,gEAAgE;wBAChE,gCAAgC;wBAChC,EAAE;wBACF,gEAAgE;wBAChE,yDAAyD;wBACzD,iEAAiE;wBACjE,gEAAgE;wBAChE,+DAA+D;wBAC/D,0DAA0D;wBAC1D,kEAAkE;wBAClE,8DAA8D;wBAC9D,mEAAmE;wBACnE,gEAAgE;wBAChE,8BAA8B;wBAC9B,EAAE;wBACF,kEAAkE;wBAClE,oEAAoE;wBACpE,iEAAiE;wBACjE,iEAAiE;wBACjE,kEAAkE;wBAClE,sDAAsD;wBACtD8C,UAAUC,SAAS,GAAGzJ,MAAM0J,kBAAkB,CAAC1B,KAAK2B,IAAI;wBACxDpF,SAAShB,IAAI,CAACqE,WAAW,CAAC4B;oBAC5B,OAAO,IAAIxB,KAAKE,IAAI,KAAK,SAAS;wBAChC,6DAA6D;wBAC7D,uDAAuD;wBACvD,uCAAuC;wBACvC,IAAI0B,SAAS5B,KAAK6B,IAAI;oBACxB,OAAO,IAAI7B,KAAKE,IAAI,KAAK,YAAY;wBACnC,8DAA8D;wBAC9D,8DAA8D;wBAC9D,YAAY;wBACZ,MAAM4B,aACJ,AAAC9B,KAAa+B,QAAQ,IAAI,OACtB/D,2BAAAA,OAAS,CAAC,AAACgC,KAAa+B,QAAQ,CAAC,GACjC1I;wBACN,MAAM2I,cACJF,cAAc,OACV9J,MAAMiK,oBAAoB,CAACH,cAC3B9B,KAAKkC,GAAG;wBACd,IAAIF,aAAa1E,OAAO6E,QAAQ,CAACrD,MAAM,CAACkD;oBAC1C,OAAO,IACLhC,KAAKE,IAAI,KAAK,iBACdF,KAAKE,IAAI,KAAK,iBACdF,KAAKE,IAAI,KAAK,iBACd;wBACA,wDAAwD;wBACxD,6DAA6D;wBAC7D,6DAA6D;wBAC7D,wDAAwD;wBACxD,wDAAwD;wBACxDlI,MAAMoK,wBAAwB;wBAC9BpK,MAAMqK,wBAAwB,CAC5BrC,KAAKE,IAAI,KAAK,gBACV,SACAF,KAAKE,IAAI,KAAK,gBACZ,SACA,UACN,wDAAwD;wBACxD,8DAA8D;wBAC9DlI,MAAMqI,kBAAkB,CAACL,KAAKrD,QAAQ,GACtC;4BACE2F,SAAS,AAACtC,KAA8BsC,OAAO;4BAC/CC,WAAW,AACTvC,KACAuC,SAAS;wBACb;oBAEJ,OAAO,IACLvC,KAAKE,IAAI,KAAK,gBACdF,KAAKE,IAAI,KAAK,iBACdF,KAAKE,IAAI,KAAK,gBACd;wBACA,2DAA2D;wBAC3D,2DAA2D;wBAC3DlI,MAAMwK,qBAAqB,CACzBxC,KAAKE,IAAI,KAAK,eACV,SACAF,KAAKE,IAAI,KAAK,gBACZ,UACA,UACNF,KAAKyC,YAAY,IAAIpJ;oBAEzB,OAAO,IACL2G,KAAKE,IAAI,KAAK,cACdF,KAAKE,IAAI,KAAK,eACdF,KAAKE,IAAI,KAAK,cACd;wBACA,wDAAwD;wBACxD,wDAAwD;wBACxD,2DAA2D;wBAC3D,2DAA2D;wBAC3D,sCAAsC;wBACtClI,MAAM0K,mBAAmB,CACvB1C,KAAKE,IAAI,KAAK,aACV,SACAF,KAAKE,IAAI,KAAK,cACZ,UACA,UACNF,KAAK2C,UAAU,IAAItJ,WACnB;4BAAEuJ,OAAO7C,WAAW1D,KAAK,KAAK;wBAAoB;oBAEtD,OAAO,IAAI2D,KAAKE,IAAI,KAAK,gBAAgB;wBACvC,8DAA8D;wBAC9D,6DAA6D;wBAC7D,8DAA8D;wBAC9D,iEAAiE;wBACjE,wBAAwB;wBACxBhI,mBAAmB8H,KAAK6C,SAAS,EAAE7C,KAAK8C,MAAM;oBAChD,OAAO,IAAI9C,KAAKE,IAAI,KAAK,aAAa;4BAE3BF,eACPA;wBAFF1B,UACEyE,QAAO/C,gBAAAA,KAAKzB,OAAO,YAAZyB,gBAAgB,IAAI9F,KAAK,CAAC,GAAG,OACpC8F,iBAAAA,KAAKxB,QAAQ,YAAbwB,iBAAiB;oBAErB,OAAO,IAAIA,KAAKE,IAAI,KAAK,eAAe;wBACtC,IAAIF,KAAKpH,SAAS,EAAEsF,eAAeC,OAAO,CAAC6B,KAAKpH,SAAS;oBAC3D;gBACF,EAAE,OAAOoK,OAAO;oBACdC,QAAQD,KAAK,CAAC,0BAA0BA;gBAC1C;YACF;QACF;QAEA,MAAME,OAAO,CAACnD;YACZ,mEAAmE;YACnE,gEAAgE;YAChE,IAAI,CAACA,WAAWoD,SAAS,EAAE;gBACzB,IAAI/E,MAAMgF,GAAG,CAACrD,WAAWlF,EAAE,GAAG;gBAC9BuD,MAAMqC,GAAG,CAACV,WAAWlF,EAAE;YACzB;YACA,sEAAsE;YACtE,IAAIkF,WAAWsD,cAAc,EAAE;gBAC7B,MAAMC,MAAM,CAAC,WAAW,EAAEvD,WAAWlF,EAAE,EAAE;gBACzC,IAAI;oBACF,IAAIlB,aAAaE,OAAO,CAACyJ,MAAM;oBAC/B3J,aAAaU,OAAO,CAACiJ,KAAK;gBAC5B,EAAE,eAAM;gBACN,sDAAsD;gBACxD;YACF,OAAO,IAAIvD,WAAWwD,cAAc,EAAE;gBACpC,gEAAgE;gBAChE,MAAMD,MAAM,CAAC,WAAW,EAAEvD,WAAWlF,EAAE,EAAE;gBACzC,IAAI;oBACF,IAAIjB,eAAeC,OAAO,CAACyJ,MAAM;oBACjC1J,eAAeS,OAAO,CAACiJ,KAAK;gBAC9B,EAAE,eAAM;gBACN,sDAAsD;gBACxD;YACF,OAAO,IAAIvD,WAAWyD,eAAe,EAAE;gBACrC,kEAAkE;gBAClE,MAAMF,MAAM,CAAC,WAAW,EAAEvD,WAAWlF,EAAE,CAAC,GAAG,CAAC;gBAC5C,IAAI;wBACkBlB;oBAApB,MAAM8J,OAAOC,QAAO/J,wBAAAA,aAAaE,OAAO,CAACyJ,gBAArB3J,wBAA6B;oBACjD,IACE8J,QACAtJ,KAAKC,GAAG,KAAKqJ,OAAO1D,WAAWyD,eAAe,GAAG,OACjD;wBACA;oBACF;oBACA7J,aAAaU,OAAO,CAACiJ,KAAKP,OAAO5I,KAAKC,GAAG;gBAC3C,EAAE,eAAM;gBACN,sDAAsD;gBACxD;YACF;YACA0F,eAAeC;YACf,IAAIA,WAAW4D,cAAc,EAAE;gBAC7B,KAAKvI,MAAM,wBAAwB;oBACjCC,QAAQ;oBACRC,SAAS;wBAAE,gBAAgB;oBAAmB;oBAC9CC,MAAMC,KAAKC,SAAS,CAAC;wBACnB/C;wBACAkL,UAAU7D,WAAWlF,EAAE;wBACvBwB,OAAO0D,WAAW1D,KAAK;wBACvBvB,SAAS;4BAAE+I,MAAMvG,OAAO6E,QAAQ,CAAC2B,QAAQ;wBAAC;oBAC5C;oBACAlI,WAAW;gBACb,GAAGC,KAAK,CAAC,IAAMxC;YACjB;QACF;QAEA;;;;;;;;;;;;;;;;KAgBC,GACD,MAAM0K,mBAAsC,EAAE;QAC9C,IAAIC,cAAuC;QAC3C,MAAMC,SAAS;YACb,KAAK,MAAMC,UAAU;mBAAIH;aAAiB,CAAEG;YAC5C,IAAI,CAACH,iBAAiB3K,MAAM,EAAE;gBAC5B4K,+BAAAA,YAAaG,UAAU;gBACvBH,cAAc;YAChB;QACF;QACA,MAAMI,oBAAoB,CAACF;YACzBH,iBAAiBtH,IAAI,CAACyH;YACtB,IAAIF,eAAe,OAAOK,qBAAqB,aAAa;YAC5DL,cAAc,IAAIK,iBAAiBJ;YACnCD,YAAYM,OAAO,CAAC/H,SAAShB,IAAI,EAAE;gBAAEgJ,WAAW;gBAAMC,SAAS;YAAK;QACtE;QACA,MAAMC,eAAe,CAACP;YACpB,MAAMQ,QAAQX,iBAAiBY,OAAO,CAACT;YACvC,IAAIQ,SAAS,GAAGX,iBAAiBa,MAAM,CAACF,OAAO;YAC/C,IAAI,CAACX,iBAAiB3K,MAAM,EAAE;gBAC5B4K,+BAAAA,YAAaG,UAAU;gBACvBH,cAAc;YAChB;QACF;QACA/H,SAASQ,IAAI,CAAC;YACZsH,iBAAiB3K,MAAM,GAAG;YAC1B4K,+BAAAA,YAAaG,UAAU;YACvBH,cAAc;QAChB;QAEA,KAAK,MAAMjE,cAAchC,YAAa;YACpC,MAAM,EAAE1B,KAAK,EAAEwI,SAAS,EAAE,GAAG9E;YAC7B,gEAAgE;YAChE,iEAAiE;YACjE,oEAAoE;YACpE,uEAAuE;YACvE,uEAAuE;YACvE,mDAAmD;YACnD,MAAMpD,WAAWoD,WAAWpD,QAAQ,GAChC3E,MAAMqI,kBAAkB,CAACN,WAAWpD,QAAQ,IAC5CoD,WAAWpD,QAAQ;YACvB,IAAIN,UAAU,aAAa;gBACzB6G,KAAKnD;YACP,OAAO,IAAI1D,UAAU,cAAc;gBACjC,MAAMqB,QAAQC,WACZ,IAAMuF,KAAKnD,aACXhG,KAAKqD,GAAG,CAAC,GAAGyH,oBAAAA,YAAa,KAAK;gBAEhC5I,SAASQ,IAAI,CAAC,IAAMmB,aAAaF;YACnC,OAAO,IAAIrB,UAAU,eAAe;gBAClC,MAAMY,WAAW;oBACf,MAAMC,MAAMX,SAASY,eAAe;oBACpC,MAAMC,MAAMF,IAAIG,YAAY,GAAGC,OAAOC,WAAW;oBACjD,MAAMuH,UAAU1H,MAAM,IAAI,AAACE,OAAOE,OAAO,GAAGJ,MAAO,MAAM;oBACzD,IAAI0H,WAAW/K,KAAKgL,GAAG,CAAC,KAAKhL,KAAKqD,GAAG,CAAC,GAAGyH,oBAAAA,YAAa,MAAM;wBAC1D3B,KAAKnD;wBACLzC,OAAOZ,mBAAmB,CAAC,UAAUO;oBACvC;gBACF;gBACAK,OAAOd,gBAAgB,CAAC,UAAUS,UAAU;oBAAEQ,SAAS;gBAAK;gBAC5DxB,SAASQ,IAAI,CAAC,IAAMa,OAAOZ,mBAAmB,CAAC,UAAUO;YAC3D,OAAO,IAAIZ,UAAU,oBAAoBA,UAAU,mBAAmB;gBACpE,IAAI,CAACM,UAAU;gBACf,IAAIyB,QAAQ;gBACZ,MAAM4G,WAAW,IAAIC,qBAAqB,CAACC;oBACzC,IAAI9G,SAAS,CAAC8G,QAAQC,IAAI,CAAC,CAACC,QAAUA,MAAMC,cAAc,GAAG;oBAC7DjH,QAAQ;oBACR8E,KAAKnD;oBACLiF,SAASb,UAAU;oBACnBM,aAAaa;gBACf;gBACA,iEAAiE;gBACjE,sEAAsE;gBACtE,2CAA2C;gBAC3C,MAAMA,gBAAgB;oBACpB,IAAIlH,OAAO,OAAOqG,aAAaa;oBAC/B/I,SACG6D,gBAAgB,CAACzD,UACjB2D,OAAO,CAAC,CAACvD,SAAWiI,SAASV,OAAO,CAACvH;gBAC1C;gBACAuI;gBACAlB,kBAAkBkB;gBAClBrJ,SAASQ,IAAI,CAAC,IAAMuI,SAASb,UAAU;YACzC,OAAO,IAAI9H,UAAU,gBAAgB;gBACnC,IAAI,CAACM,UAAU;gBACf,MAAMG,UAAU,CAACyI;wBAEXxI;oBADJ,MAAMA,SAASwI,WAAWxI,MAAM;oBAChC,IAAIA,2BAAAA,kBAAAA,OAAQC,OAAO,qBAAfD,qBAAAA,QAAkBJ,WAAWuG,KAAKnD;gBACxC;gBACAxD,SAASC,gBAAgB,CAAC,SAASM,SAAS;gBAC5Cb,SAASQ,IAAI,CAAC,IACZF,SAASG,mBAAmB,CAAC,SAASI,SAAS;YAEnD,OAAO,IACLT,UAAU,uBACVA,UAAU,qBACV;gBACA,kEAAkE;gBAClE,gEAAgE;gBAChE,+BAA+B;gBAC/B,IAAI,CAACM,UAAU;gBACf,MAAM6I,UAAU,CAACD;wBAEDxI;oBADd,MAAMA,SAASwI,WAAWxI,MAAM;oBAChC,MAAM0I,QAAQ1I,2BAAAA,kBAAAA,OAAQC,OAAO,qBAAfD,qBAAAA,QAAkBJ;oBAChC,IAAI,CAAC8I,OAAO;oBACZ,MAAMC,UAAUH,WAAWI,aAAa;oBACxC,IAAID,WAAWD,MAAMG,QAAQ,CAACF,UAAU;oBACxCxC,KAAKnD;gBACP;gBACA,MAAMG,OAAO7D,UAAU,sBAAsB,cAAc;gBAC3DE,SAASC,gBAAgB,CAAC0D,MAAMsF,SAAS;gBACzCvJ,SAASQ,IAAI,CAAC,IACZF,SAASG,mBAAmB,CAACwD,MAAMsF,SAAS;YAEhD,OAAO,IAAInJ,UAAU,cAAc;gBACjC,MAAMwJ,UAAU,CAACN;oBACf,IAAIA,WAAWO,OAAO,IAAI,GAAG5C,KAAKnD;gBACpC;gBACAxD,SAASC,gBAAgB,CAAC,cAAcqJ;gBACxC5J,SAASQ,IAAI,CAAC,IAAMF,SAASG,mBAAmB,CAAC,cAAcmJ;YACjE;QACF;QACA,OAAO;YACL,KAAK,MAAMhI,WAAW5B,SAAU4B;QAClC;IACA,mDAAmD;IACnD,uDAAuD;IACvD,uDAAuD;IACzD,GAAG;QACDnF;QACAsF;QACA,uDAAuD;QACvDxC,KAAKC,SAAS,CAACsC,YAAYgI,GAAG,CAAC,CAAChG,aAAeA,WAAWlF,EAAE;KAC7D;IAED,OAAO;AACT;AAEA,SAASmL,gBAAgBhN,KAGxB;IACC,MAAM,EAAEiN,GAAG,EAAEvN,MAAM,EAAE,GAAGM;IACxB,MAAMkN,aAAa,CAAC,WAAW,EAAED,IAAIE,WAAW,EAAE;IAClD,MAAM,CAACC,QAAQC,UAAU,GAAG9N,SAAS;IACrCF,UAAU;QACR,IAAI;YACFgO,UAAUC,QAAQhJ,OAAO3D,YAAY,CAACE,OAAO,CAACqM;QAChD,EAAE,eAAM;YACNG,UAAU;QACZ;IACF,GAAG;QAACH;KAAW;IACf,qEAAqE;IACrE7N,UAAU;QACR,IAAI,CAAC+N,QAAQ3N,kBAAkBC,QAAQ,iBAAiBuN,IAAIrN,SAAS;IACrE,uDAAuD;IACzD,GAAG;QAACwN;KAAO;IACX,IAAIA,QAAQ,OAAO;IACnB,MAAMrH,QAAuB;QAC3BC,UAAU;QACVI,QAAQ;QACRmH,SAAS;QACTC,YAAY;QACZC,gBAAgB;QAChBC,KAAK;QACLrH,SAAS;QACTE,UAAU;QACVC,YAAY;QACZmH,WAAW;QACXlH,OAAOwG,IAAIW,SAAS,IAAI;QACxBlH,iBAAiBuG,IAAIvG,eAAe,IAAI;IAC1C;IACA,MAAMmH,OAAOZ,IAAIa,IAAI,iBACnB,KAACC;QACCD,MAAMb,IAAIa,IAAI;QACdhK,SAAS,IAAMrE,kBAAkBC,QAAQ,YAAYuN,IAAIrN,SAAS;QAClEmG,OAAO;YAAEU,OAAO;YAAWuH,gBAAgB;QAAY;kBAEtDf,IAAIY,IAAI;uBAGX,KAACI;kBAAMhB,IAAIY,IAAI;;IAEjB,qBACE,MAACK;QAAIC,MAAK;QAASC,cAAW;QAAerI,OAAOA;;YACjD8H;YACAZ,IAAIoB,WAAW,iBACd,KAACC;gBACCpH,MAAK;gBACLkH,cAAW;gBACXtK,SAAS;oBACP,IAAI;wBACFQ,OAAO3D,YAAY,CAACU,OAAO,CAAC6L,YAAY;oBAC1C,EAAE,eAAM;oBACN,0DAA0D;oBAC5D;oBACAzN,kBAAkBC,QAAQ,cAAcuN,IAAIrN,SAAS;oBACrDyN,UAAU;gBACZ;gBACAtH,OAAO;oBACLC,UAAU;oBACVuI,OAAO;oBACPhG,KAAK;oBACLpC,WAAW;oBACXqI,QAAQ;oBACRC,YAAY;oBACZhI,OAAO;oBACPF,UAAU;oBACVmI,YAAY;oBACZC,QAAQ;oBACRtI,SAAS;gBACX;0BAEC;iBAED;;;AAGV;AAEA;;;;;CAKC,GACD,SAASuI,aAAa5O,KAGrB;QAkOgB6O;IAjOf,MAAM,EAAEA,KAAK,EAAEnP,MAAM,EAAE,GAAGM;IAC1B,MAAMkN,aAAa,CAAC,YAAY,EAAE2B,MAAM1B,WAAW,EAAE;IACrD,MAAM,CAAC2B,MAAMC,QAAQ,GAAGxP,SAAS;IACjC,oEAAoE;IACpE,yDAAyD;IACzD,MAAM,CAACyP,OAAOC,SAAS,GAAG1P,SAAS;IACnC,uEAAuE;IACvE,uEAAuE;IACvE,iEAAiE;IACjE,0EAA0E;IAC1E,yEAAyE;IACzE,wEAAwE;IACxE,oDAAoD;IACpD,MAAM,CAAC2P,SAASC,WAAW,GAAG5P,SAAS;IACvC,MAAM,CAAC6P,WAAWC,aAAa,GAAG9P,SAAS;IAE3CF,UAAU;QACR,IAAIyP,MAAMrP,kBAAkBC,QAAQ,mBAAmBmP,MAAMjP,SAAS;IACtE,uDAAuD;IACzD,GAAG;QAACkP;QAAMpP;KAAO;IAEjBL,UAAU;QACR,MAAM+B,MAAMD,KAAKC,GAAG;QACpB,IAAIyN,MAAMS,SAAS,IAAIlO,MAAMyN,MAAMS,SAAS,EAAE;QAC9C,IAAIT,MAAMjN,OAAO,IAAIR,MAAMyN,MAAMjN,OAAO,EAAE;QAC1C,IAAI;gBAQ0B0C;YAP5B,mEAAmE;YACnE,qEAAqE;YACrE,uBAAuB;YACvB,MAAMiL,aAAa/P,eAAegQ,eAAe,CAC/CX,OACArP,eAAeiQ,aAAa,CAACZ,WAAW,YACpC;gBAAEa,aAAapL,OAAO1D,cAAc,CAACC,OAAO,CAACqM;YAAY,IACzD;gBAAEyC,aAAajF,QAAOpG,+BAAAA,OAAO3D,YAAY,CAACE,OAAO,CAACqM,uBAA5B5I,+BAA2C;YAAG,GACxElD;YAEF,IAAImO,YAAY;QAClB,EAAE,eAAM;QACN,kDAAkD;QACpD;QACA,IAAI1K;QACJ,IAAIgK,MAAMe,OAAO,KAAK,UAAU;YAC9B,MAAM/D,YAAY9K,KAAKgL,GAAG,CAAC,KAAKhL,KAAKqD,GAAG,CAAC,GAAGyK,MAAMgB,YAAY,KAAK;YACnE,MAAM5L,WAAW;gBACf,MAAM6L,SACJvM,SAASY,eAAe,CAACE,YAAY,GAAGC,OAAOC,WAAW;gBAC5D,IAAIuL,UAAU,KAAKxL,OAAOE,OAAO,GAAGsL,UAAUjE,WAAW;oBACvDkD,QAAQ;gBACV;YACF;YACAzK,OAAOd,gBAAgB,CAAC,UAAUS,UAAU;gBAAEQ,SAAS;YAAK;YAC5DI,UAAU,IAAMP,OAAOZ,mBAAmB,CAAC,UAAUO;QACvD,OAAO,IAAI4K,MAAMe,OAAO,KAAK,QAAQ;YACnC,MAAM/C,UAAU,CAACxJ;gBACf,IAAIA,MAAMyJ,OAAO,IAAI,GAAGiC,QAAQ;YAClC;YACAxL,SAASC,gBAAgB,CAAC,YAAYqJ;YACtChI,UAAU,IAAMtB,SAASG,mBAAmB,CAAC,YAAYmJ;QAC3D,OAAO;YACL,MAAMnI,QAAQJ,OAAOK,UAAU,CAC7B,IAAMoK,QAAQ,OACdhO,KAAKqD,GAAG,CAAC,GAAGyK,MAAMgB,YAAY,IAAI;YAEpChL,UAAU,IAAMP,OAAOM,YAAY,CAACF;QACtC;QACA,OAAOG;IACT,GAAG;QAACgK;QAAO3B;KAAW;IAEtB,MAAM6C,QAAQ,CAAC5N,OAAsC,cAAc;QACjE,IAAI;YACF,gEAAgE;YAChE,oEAAoE;YACpE,2DAA2D;YAC3D,IAAI3C,eAAeiQ,aAAa,CAACZ,WAAW,WAAW;gBACrDvK,OAAO1D,cAAc,CAACS,OAAO,CAAC6L,YAAY;YAC5C,OAAO;gBACL5I,OAAO3D,YAAY,CAACU,OAAO,CAAC6L,YAAYnD,OAAO5I,KAAKC,GAAG;YACzD;QACF,EAAE,eAAM;QACN,6DAA6D;QAC/D;QACA3B,kBAAkBC,QAAQyC,MAAM0M,MAAMjP,SAAS;QAC/CmP,QAAQ;IACV;IAEA,MAAMiB,oBAAoB;QACxB,MAAMjI,QAAQiH,MAAMnL,IAAI;QACxB,IAAI,CAACkE,SAASqH,WAAW;QACzB,IAAI;YACF,MAAMa,WAAW,MAAM7N,MAAM,qBAAqB;gBAChDC,QAAQ;gBACRC,SAAS;oBAAE,gBAAgB;gBAAmB;gBAC9CC,MAAMC,KAAKC,SAAS,CAAC;oBACnB/C;oBACA,iEAAiE;oBACjE,6DAA6D;oBAC7D,+CAA+C;oBAC/CwQ,MAAM;oBACNC,UAAU;oBACVC,QAAQ;wBAAEpB,OAAOjH;oBAAM;oBACvB8C,MAAMvG,OAAO6E,QAAQ,CAAC2B,QAAQ;oBAC9B,mEAAmE;oBACnE,oEAAoE;oBACpE,kEAAkE;oBAClE,kEAAkE;oBAClEoE;mBAIG9P;YAEP;YACA,gEAAgE;YAChE,uEAAuE;YACvE,yEAAyE;YACzE,sEAAsE;YACtE,0DAA0D;YAC1D,EAAE;YACF,qEAAqE;YACrE,wEAAwE;YACxE,qEAAqE;YACrE,qEAAqE;YACrE,wEAAwE;YACxE,gEAAgE;YAChE,EAAE;YACF,sEAAsE;YACtE,uEAAuE;YACvE,IAAI6Q,SAASI,EAAE,EAAE;gBACflR,WAAW,iBAAiB;oBAC1BmR,WAAW;oBACXC,eAAejM,OAAO6E,QAAQ,CAAC2B,QAAQ;gBACzC;YACF;QACF,EAAE,eAAM;QACN,yCAAyC;QAC3C;QACAuE,aAAa;QACb,IAAI;YACF,2DAA2D;YAC3D/K,OAAO3D,YAAY,CAACU,OAAO,CACzB6L,YACAnD,OAAO5I,KAAKC,GAAG,KAAK;QAExB,EAAE,eAAM;QACN,UAAU;QACZ;IACF;IAEA/B,UAAU;QACR,IAAI,CAACyP,MAAM;QACX,MAAM0B,QAAQ,CAACnN;YACb,IAAIA,MAAMiH,GAAG,KAAK,UAAUyF;QAC9B;QACAxM,SAASC,gBAAgB,CAAC,WAAWgN;QACrC,OAAO,IAAMjN,SAASG,mBAAmB,CAAC,WAAW8M;IACrD,uDAAuD;IACzD,GAAG;QAAC1B;KAAK;IAET,IAAI,CAACA,MAAM,OAAO;IAClB,qBACE,KAACZ;QACCpK,SAAS,IAAMiM;QACfhK,OAAO;YACLC,UAAU;YACVyK,OAAO;YACPrK,QAAQ;YACRmH,SAAS;YACTC,YAAY;YACZC,gBAAgB;YAChB/G,iBAAiB;YACjBL,SAAS;QACX;kBAEA,cAAA,MAAC6H;YACCC,MAAK;YACLuC,cAAW;YACXtC,cAAYS,MAAM8B,QAAQ,IAAI;YAC9B7M,SAAS,CAACT,QAAUA,MAAMuN,eAAe;YACzC7K,OAAO;gBACLY,UAAU;gBACVkK,OAAO;gBACPpC,YAAY;gBACZhI,OAAO;gBACPH,cAAc;gBACdwK,UAAU;gBACVC,WAAW;gBACXvK,YAAY;gBACZR,UAAU;YACZ;;8BAEA,KAACsI;oBACCpH,MAAK;oBACLkH,cAAW;oBACXtK,SAAS,IAAMiM;oBACfhK,OAAO;wBACLC,UAAU;wBACVuC,KAAK;wBACLgG,OAAO;wBACPC,QAAQ;wBACRC,YAAY;wBACZnI,cAAc;wBACduK,OAAO;wBACPf,QAAQ;wBACRnB,QAAQ;wBACRpI,UAAU;wBACVmI,YAAY;oBACd;8BAEC;;gBAQFG,MAAMmC,QAAQ,IAAI,CAAChS,MAAMiS,uBAAuB,CAACpC,MAAMmC,QAAQ,IAC9D,qDAAqD;8BACrD,KAACE;oBACCC,KAAKnS,MAAMoS,oBAAoB,CAACvC,MAAMmC,QAAQ,EAAE;wBAAEtR;oBAAO;oBACzD,+DAA+D;oBAC/D,+DAA+D;oBAC/D,iEAAiE;oBACjE,iEAAiE;oBACjE,qDAAqD;oBACrD2R,GAAG,GAAExC,kBAAAA,MAAMyC,QAAQ,YAAdzC,kBAAkB;oBACvB9I,OAAO;wBACL8K,OAAO;wBACPU,WAAW;wBACXC,WAAW;wBACXjE,SAAS;oBACX;qBAEA;8BACJ,MAACW;oBAAInI,OAAO;wBAAEM,SAAS;wBAAIsH,WAAW;oBAAS;;wBAC5CkB,MAAM8B,QAAQ,iBACb,KAACc;4BAAG1L,OAAO;gCAAE2L,QAAQ;gCAAWnL,UAAU;4BAAG;sCAC1CsI,MAAM8B,QAAQ;6BAEf;sCACJ,KAACgB;4BAAE5L,OAAO;gCAAE2L,QAAQ;gCAAGnL,UAAU;gCAAIqL,YAAY;4BAAW;sCACzD/C,MAAMtM,IAAI;;wBAEZsM,MAAMgD,YAAY,iBACjB,KAAC3D;4BAAInI,OAAO;gCAAE+L,WAAW;4BAAG;sCACzB1C,0BACC,KAACuC;gCAAE5L,OAAO;oCAAE2L,QAAQ;oCAAGnL,UAAU;oCAAIwL,YAAY;gCAAI;0CAClD;+CAGH,MAACC;gCACC1O,UAAU,CAACD;oCACTA,MAAM4O,cAAc;oCACpB,KAAKjC;gCACP;gCACAjK,OAAO;oCAAEwH,SAAS;oCAAQG,KAAK;oCAAGD,gBAAgB;gCAAS;;kDAE3D,KAACyE;wCACChL,MAAK;wCACLiL,QAAQ;wCACRC,aAAY;wCACZ,qDAAqD;wCACrD,yDAAyD;wCACzD,mDAAmD;wCACnD,8BAA8B;wCAC9BhE,cAAW;wCACXrG,OAAOiH;wCACPqD,UAAU,CAAChP,QAAU4L,SAAS5L,MAAMU,MAAM,CAACgE,KAAK;wCAChDhC,OAAO;4CACLuM,MAAM;4CACN3L,UAAU;4CACVN,SAAS;4CACTC,cAAc;4CACdkI,QAAQ;4CACRjI,UAAU;wCACZ;;kDASF,KAAC2L;wCACChL,MAAK;wCACLW,MAAK;wCACL0K,UAAU,CAAC;wCACXC,cAAa;wCACbC,eAAY;wCACZ1K,OAAOmH;wCACPmD,UAAU,CAAChP,QAAU8L,WAAW9L,MAAMU,MAAM,CAACgE,KAAK;wCAClDhC,OAAO;4CACLC,UAAU;4CACVE,MAAM;4CACN4J,QAAQ;4CACRe,OAAO;wCACT;;kDAEF,KAACvC;wCACCpH,MAAK;wCACLnB,OAAO;4CACLM,SAAS;4CACTC,cAAc;4CACdkI,QAAQ;4CACRC,YAAY;4CACZhI,OAAO;4CACPF,UAAU;4CACVoI,QAAQ;wCACV;kDAEC;;;;6BAKP;wBACHE,MAAM6D,OAAO,IAAI7D,MAAM8D,QAAQ,iBAC9B,KAAC5E;4BACCD,MAAMe,MAAM6D,OAAO;4BACnB5O,SAAS,IAAMiM,MAAM;4BACrBhK,OAAO;gCACLwH,SAAS;gCACTuE,WAAW;gCACXzL,SAAS;gCACTC,cAAc;gCACdmI,YAAY;gCACZhI,OAAO;gCACPuH,gBAAgB;gCAChBzH,UAAU;4BACZ;sCAECsI,MAAM8D,QAAQ;6BAEf;;;;;;AAKd;AAGA;;;;;;CAMC,GACD,OAAO,SAASC,qBAAqB,EAAElT,MAAM,EAAEsF,OAAO,EAAE6N,IAAI,EAAoB;QAIzDA,mBACMA,yBAiDRC;QAnCED,YAeqBC,wBAWEA;IA5C5C,MAAM,CAACA,mBAAmBC,qBAAqB,GAAGxT,SAAc;IAChE,MAAMyT,kBAAkBH,IAAI,CAAC,kBAAkB;IAC/C,MAAMhE,QAAQgE,IAAI,CAAC,QAAQ;IAC3B,MAAM5S,eAAe4S,oBAAAA,IAAI,CAAC,cAAc,YAAnBA,oBAAuB,EAAE;IAC9C,MAAMI,qBAAqBJ,0BAAAA,IAAI,CAAC,oBAAoB,YAAzBA,0BAA6B,EAAE;IAC1D,MAAMK,qBAAqBL,IAAI,CAAC,qBAAqB;IAErD,qBACE;;YACGG,gCACC,KAAChG;gBAAgBC,KAAK+F;gBAAiBtT,QAAQA;iBAC7C;YACHmP,sBAAQ,KAACD;gBAAaC,OAAOA;gBAAOnP,QAAQA;iBAAa;YAEzDO,YAAYG,MAAM,iBACjB,KAACL;gBACCL,QAAQA;gBACRO,aAAaA;gBACbC,WAAW,GAAE2S,aAAAA,IAAI,CAAC,OAAO,qBAAZA,WAAcM,IAAI;iBAE/B;YAEHF,kBAAkB7S,MAAM,iBACvB,KAAC0E;gBACCpF,QAAQA;gBACRqF,aAAakO;gBACbjO,SAASA;gBACTC,eAAe,CAACrF;oBACd,MAAMD,UAAUuT,sCAAAA,kBAAoB,CAACtT,UAAU;oBAC/C,IAAID,SAASoT,qBAAqB;wBAAElR,IAAIjC;uBAAcD;gBACxD;iBAEA;YACHmT,CAAAA,qCAAAA,kBAAmB3Q,IAAI,MAAK,WAAS2Q,yBAAAA,kBAAkB7F,GAAG,qBAArB6F,uBAAuBjF,IAAI,kBAC/D,KAACb;gBACCC,KAAK,aACA6F,kBAAkB7F,GAAG;oBACxBY,MAAM9D,OAAO+I,kBAAkB7F,GAAG,CAACY,IAAI;oBACvCQ,aAAayE,kBAAkB7F,GAAG,CAACoB,WAAW,KAAK;oBACnDlB,aAAa,CAAC,WAAW,EAAE2F,kBAAkBjR,EAAE,EAAE;;gBAEnDnC,QAAQA;iBAER;YACHoT,CAAAA,qCAAAA,kBAAmB3Q,IAAI,MAAK,aAAW2Q,2BAAAA,kBAAkBjE,KAAK,qBAAvBiE,yBAAyBvQ,IAAI,kBACnE,KAACqM;gBACCC,OAAO,aACFiE,kBAAkBjE,KAAK;oBAC1BtM,MAAMwH,OAAO+I,kBAAkBjE,KAAK,CAACtM,IAAI;oBACzCqN,SAAS;oBACTC,cAAc;oBACduD,eAAerS,KAAKqD,GAAG,CACrB,GACAsG,QAAOoI,yCAAAA,kBAAkBjE,KAAK,CAACuE,aAAa,YAArCN,yCAAyC;oBAElD3F,aAAa,CAAC,WAAW,EAAE2F,kBAAkBjR,EAAE,EAAE;;gBAEnDnC,QAAQA;iBAER;;;AAGV"}
@@ -20,5 +20,14 @@
20
20
  * so Staff → Operator alerts lists them before the first one is raised, and
21
21
  * its overlay beacons, which the site collector hands it on any published
22
22
  * page. The counting code and the Admin SDK load with the first beacon.
23
+ *
24
+ * And the conversion creditor (`plugin-conversion-credit`): every door that
25
+ * produces an outcome — a form, a booking, a sign-up, an order, a sequence's
26
+ * mail — asks it which campaign to credit, in any process, before any of
27
+ * this plugin's surfaces has loaded. The joins load with the first credit.
28
+ * Beside it, the tally the site's unsubscribe page tells when a recipient
29
+ * leaves from a campaign send's mail (`plugin-send-tallies`), and the
30
+ * `emailSend` record index another plugin names a send by — a person's
31
+ * timeline listing the campaign mail they were sent (`plugin-record-index`).
23
32
  */
24
33
  export declare function registerMarketingServerDeclarations(): void;
@@ -16,8 +16,14 @@
16
16
  */ // The seam from its own module, not the plugin-manager barrel: boot needs the
17
17
  // registry and nothing else, and the barrel reaches the client contexts.
18
18
  import { registerOperatorAlerts } from "@aglyn/aglyn/plugin-manager/operator-alerts";
19
+ import { registerPluginConversionCreditor } from "@aglyn/aglyn/plugin-manager/plugin-conversion-credit";
20
+ import { registerPluginSendTally } from "@aglyn/aglyn/plugin-manager/plugin-send-tallies";
21
+ import { registerPluginRecordIndex } from "@aglyn/aglyn/plugin-manager/plugin-record-index";
19
22
  import { registerPluginSiteBeacon } from "@aglyn/aglyn/plugin-manager/plugin-site-beacons";
23
+ import { registerPluginTransferResource } from "@aglyn/aglyn/plugin-manager/plugin-transfer-resources";
20
24
  import { BUNDLE_ID } from "./constants/bundle-common.js";
25
+ import { CAMPAIGN_PACKAGE_RULES, CAMPAIGNS_TRANSFER_KEY, campaignDependencies, campaignPackageContent, remapCampaignIds } from "./transfer/campaigns-package.js";
26
+ /** The campaigns package's server half (AGL-3535), loaded when an import or export first asks. */ const campaignsPackage = async ()=>(await import("./transfer/campaigns-package.server.js")).createCampaignsPackage();
21
27
  import { MARKETING_OPERATOR_ALERTS } from "./constants/operator-alerts.js";
22
28
  /**
23
29
  * The marketing plugin's server declarations: the light registrations core
@@ -25,7 +31,30 @@ import { MARKETING_OPERATOR_ALERTS } from "./constants/operator-alerts.js";
25
31
  * so Staff → Operator alerts lists them before the first one is raised, and
26
32
  * its overlay beacons, which the site collector hands it on any published
27
33
  * page. The counting code and the Admin SDK load with the first beacon.
34
+ *
35
+ * And the conversion creditor (`plugin-conversion-credit`): every door that
36
+ * produces an outcome — a form, a booking, a sign-up, an order, a sequence's
37
+ * mail — asks it which campaign to credit, in any process, before any of
38
+ * this plugin's surfaces has loaded. The joins load with the first credit.
39
+ * Beside it, the tally the site's unsubscribe page tells when a recipient
40
+ * leaves from a campaign send's mail (`plugin-send-tallies`), and the
41
+ * `emailSend` record index another plugin names a send by — a person's
42
+ * timeline listing the campaign mail they were sent (`plugin-record-index`).
28
43
  */ export function registerMarketingServerDeclarations() {
44
+ // Campaigns in a workspace package (AGL-3535).
45
+ registerPluginTransferResource(CAMPAIGNS_TRANSFER_KEY, {
46
+ items: async (ctx)=>(await campaignsPackage()).items(ctx),
47
+ dependencies: (item)=>campaignDependencies(campaignPackageContent(item)),
48
+ remapIds: (item, idMap)=>remapCampaignIds(campaignPackageContent(item), idMap),
49
+ readItems: async (ctx, ids)=>(await campaignsPackage()).readItems(ctx, ids),
50
+ writeItems: async (ctx, items, writer)=>(await campaignsPackage()).writeItems(ctx, items, writer),
51
+ revertItems: async (ctx, steps)=>(await campaignsPackage()).revertItems(ctx, steps),
52
+ problems: async (ctx, write)=>(await campaignsPackage()).problems(ctx, write),
53
+ referenceTargets: async (ctx, kinds)=>(await campaignsPackage()).referenceTargets(ctx, kinds),
54
+ rules: CAMPAIGN_PACKAGE_RULES
55
+ }, {
56
+ pluginId: BUNDLE_ID
57
+ });
29
58
  registerOperatorAlerts(MARKETING_OPERATOR_ALERTS, {
30
59
  pluginId: BUNDLE_ID
31
60
  });
@@ -42,6 +71,39 @@ import { MARKETING_OPERATOR_ALERTS } from "./constants/operator-alerts.js";
42
71
  }, {
43
72
  pluginId: BUNDLE_ID
44
73
  });
74
+ registerPluginConversionCreditor(lazyConversionCreditor(), {
75
+ pluginId: BUNDLE_ID
76
+ });
77
+ registerPluginSendTally({
78
+ async unsubscribed (request) {
79
+ const { countCampaignSendUnsubscribe } = await import("./server/send-tally.js");
80
+ return countCampaignSendUnsubscribe(request);
81
+ }
82
+ }, {
83
+ pluginId: BUNDLE_ID
84
+ });
85
+ registerPluginRecordIndex('emailSend', {
86
+ list: async (request)=>(await import("./server/email-send-record-index.js")).emailSendRecordIndex.list(request),
87
+ get: async (request)=>(await import("./server/email-send-record-index.js")).emailSendRecordIndex.get(request)
88
+ }, {
89
+ pluginId: BUNDLE_ID
90
+ });
91
+ }
92
+ /**
93
+ * The creditor, its module loaded on the first call: the plugin's own module,
94
+ * which brings the data layer with it, for the reason the beacon's counter
95
+ * is loaded that way.
96
+ */ function lazyConversionCreditor() {
97
+ const load = async ()=>(await import("./server/conversion-creditor.js")).marketingConversionCreditor;
98
+ return {
99
+ resolveTouch: async (request)=>(await load()).resolveTouch(request),
100
+ creditConversion: async (request)=>(await load()).creditConversion(request),
101
+ creditOrder: async (request)=>(await load()).creditOrder(request),
102
+ reverseOrder: async (request)=>(await load()).reverseOrder(request),
103
+ recordClick: async (click)=>(await load()).recordClick(click),
104
+ creditOutcome: async (request)=>(await load()).creditOutcome(request),
105
+ erasePerson: async (key)=>(await load()).erasePerson(key)
106
+ };
45
107
  }
46
108
 
47
109
  //# sourceMappingURL=declarations.server.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/plugins/marketing/src/lib/declarations.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// The seam from its own module, not the plugin-manager barrel: boot needs the\n// registry and nothing else, and the barrel reaches the client contexts.\nimport { registerOperatorAlerts } from '@aglyn/aglyn/plugin-manager/operator-alerts'\nimport { registerPluginSiteBeacon } from '@aglyn/aglyn/plugin-manager/plugin-site-beacons'\nimport { BUNDLE_ID } from './constants/bundle-common'\nimport { MARKETING_OPERATOR_ALERTS } from './constants/operator-alerts'\n\n/**\n * The marketing plugin's server declarations: the light registrations core\n * reads at boot, before any surface loads — its operator alerts (AGL-3377),\n * so Staff → Operator alerts lists them before the first one is raised, and\n * its overlay beacons, which the site collector hands it on any published\n * page. The counting code and the Admin SDK load with the first beacon.\n */\nexport function registerMarketingServerDeclarations(): void {\n registerOperatorAlerts(MARKETING_OPERATOR_ALERTS, { pluginId: BUNDLE_ID })\n registerPluginSiteBeacon(\n {\n field: 'overlay',\n // The plugin's own module, which brings the Admin SDK with it: a lazy\n // import of the data layer from here would make every static import of\n // it in this plugin, and in each app that loads these declarations, a\n // static import of a library loaded lazily.\n async count(request) {\n const { countOverlayBeaconOnPlatform } = await import('./server/overlay-beacon')\n await countOverlayBeaconOnPlatform(request)\n },\n },\n { pluginId: BUNDLE_ID },\n )\n}\n"],"names":["registerOperatorAlerts","registerPluginSiteBeacon","BUNDLE_ID","MARKETING_OPERATOR_ALERTS","registerMarketingServerDeclarations","pluginId","field","count","request","countOverlayBeaconOnPlatform"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,8EAA8E;AAC9E,yEAAyE;AACzE,SAASA,sBAAsB,QAAQ,8CAA6C;AACpF,SAASC,wBAAwB,QAAQ,kDAAiD;AAC1F,SAASC,SAAS,QAAQ,+BAA2B;AACrD,SAASC,yBAAyB,QAAQ,iCAA6B;AAEvE;;;;;;CAMC,GACD,OAAO,SAASC;IACdJ,uBAAuBG,2BAA2B;QAAEE,UAAUH;IAAU;IACxED,yBACE;QACEK,OAAO;QACP,sEAAsE;QACtE,uEAAuE;QACvE,sEAAsE;QACtE,4CAA4C;QAC5C,MAAMC,OAAMC,OAAO;YACjB,MAAM,EAAEC,4BAA4B,EAAE,GAAG,MAAM,MAAM,CAAC;YACtD,MAAMA,6BAA6BD;QACrC;IACF,GACA;QAAEH,UAAUH;IAAU;AAE1B"}
1
+ {"version":3,"sources":["../../../../../../libs/plugins/marketing/src/lib/declarations.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// The seam from its own module, not the plugin-manager barrel: boot needs the\n// registry and nothing else, and the barrel reaches the client contexts.\nimport { registerOperatorAlerts } from '@aglyn/aglyn/plugin-manager/operator-alerts'\nimport {\n registerPluginConversionCreditor,\n type PluginConversionCreditor,\n} from '@aglyn/aglyn/plugin-manager/plugin-conversion-credit'\nimport { registerPluginSendTally } from '@aglyn/aglyn/plugin-manager/plugin-send-tallies'\nimport { registerPluginRecordIndex } from '@aglyn/aglyn/plugin-manager/plugin-record-index'\nimport { registerPluginSiteBeacon } from '@aglyn/aglyn/plugin-manager/plugin-site-beacons'\nimport { registerPluginTransferResource } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { BUNDLE_ID } from './constants/bundle-common'\nimport {\n CAMPAIGN_PACKAGE_RULES,\n CAMPAIGNS_TRANSFER_KEY,\n campaignDependencies,\n campaignPackageContent,\n remapCampaignIds,\n} from './transfer/campaigns-package'\n\n/** The campaigns package's server half (AGL-3535), loaded when an import or export first asks. */\nconst campaignsPackage = async () => (await import('./transfer/campaigns-package.server')).createCampaignsPackage()\nimport { MARKETING_OPERATOR_ALERTS } from './constants/operator-alerts'\n\n/**\n * The marketing plugin's server declarations: the light registrations core\n * reads at boot, before any surface loads — its operator alerts (AGL-3377),\n * so Staff → Operator alerts lists them before the first one is raised, and\n * its overlay beacons, which the site collector hands it on any published\n * page. The counting code and the Admin SDK load with the first beacon.\n *\n * And the conversion creditor (`plugin-conversion-credit`): every door that\n * produces an outcome — a form, a booking, a sign-up, an order, a sequence's\n * mail — asks it which campaign to credit, in any process, before any of\n * this plugin's surfaces has loaded. The joins load with the first credit.\n * Beside it, the tally the site's unsubscribe page tells when a recipient\n * leaves from a campaign send's mail (`plugin-send-tallies`), and the\n * `emailSend` record index another plugin names a send by — a person's\n * timeline listing the campaign mail they were sent (`plugin-record-index`).\n */\nexport function registerMarketingServerDeclarations(): void {\n // Campaigns in a workspace package (AGL-3535).\n registerPluginTransferResource(\n CAMPAIGNS_TRANSFER_KEY,\n {\n items: async (ctx) => (await campaignsPackage()).items(ctx),\n dependencies: (item) => campaignDependencies(campaignPackageContent(item)),\n remapIds: (item, idMap) => remapCampaignIds(campaignPackageContent(item), idMap),\n readItems: async (ctx, ids) => (await campaignsPackage()).readItems(ctx, ids),\n writeItems: async (ctx, items, writer) => (await campaignsPackage()).writeItems(ctx, items as never, writer),\n revertItems: async (ctx, steps) => (await campaignsPackage()).revertItems(ctx, steps as never),\n problems: async (ctx, write) => (await campaignsPackage()).problems(ctx, write as never),\n referenceTargets: async (ctx, kinds) => (await campaignsPackage()).referenceTargets(ctx, kinds),\n rules: CAMPAIGN_PACKAGE_RULES,\n },\n { pluginId: BUNDLE_ID },\n )\n registerOperatorAlerts(MARKETING_OPERATOR_ALERTS, { pluginId: BUNDLE_ID })\n registerPluginSiteBeacon(\n {\n field: 'overlay',\n // The plugin's own module, which brings the Admin SDK with it: a lazy\n // import of the data layer from here would make every static import of\n // it in this plugin, and in each app that loads these declarations, a\n // static import of a library loaded lazily.\n async count(request) {\n const { countOverlayBeaconOnPlatform } = await import('./server/overlay-beacon')\n await countOverlayBeaconOnPlatform(request)\n },\n },\n { pluginId: BUNDLE_ID },\n )\n registerPluginConversionCreditor(lazyConversionCreditor(), { pluginId: BUNDLE_ID })\n registerPluginSendTally(\n {\n async unsubscribed(request) {\n const { countCampaignSendUnsubscribe } = await import('./server/send-tally')\n return countCampaignSendUnsubscribe(request)\n },\n },\n { pluginId: BUNDLE_ID },\n )\n registerPluginRecordIndex(\n 'emailSend',\n {\n list: async (request) => (await import('./server/email-send-record-index')).emailSendRecordIndex.list(request),\n get: async (request) => (await import('./server/email-send-record-index')).emailSendRecordIndex.get(request),\n },\n { pluginId: BUNDLE_ID },\n )\n}\n\n/**\n * The creditor, its module loaded on the first call: the plugin's own module,\n * which brings the data layer with it, for the reason the beacon's counter\n * is loaded that way.\n */\nfunction lazyConversionCreditor(): PluginConversionCreditor {\n const load = async () => (await import('./server/conversion-creditor')).marketingConversionCreditor\n return {\n resolveTouch: async (request) => (await load()).resolveTouch(request),\n creditConversion: async (request) => (await load()).creditConversion(request),\n creditOrder: async (request) => (await load()).creditOrder(request),\n reverseOrder: async (request) => (await load()).reverseOrder(request),\n recordClick: async (click) => (await load()).recordClick(click),\n creditOutcome: async (request) => (await load()).creditOutcome(request),\n erasePerson: async (key) => (await load()).erasePerson(key),\n }\n}\n"],"names":["registerOperatorAlerts","registerPluginConversionCreditor","registerPluginSendTally","registerPluginRecordIndex","registerPluginSiteBeacon","registerPluginTransferResource","BUNDLE_ID","CAMPAIGN_PACKAGE_RULES","CAMPAIGNS_TRANSFER_KEY","campaignDependencies","campaignPackageContent","remapCampaignIds","campaignsPackage","createCampaignsPackage","MARKETING_OPERATOR_ALERTS","registerMarketingServerDeclarations","items","ctx","dependencies","item","remapIds","idMap","readItems","ids","writeItems","writer","revertItems","steps","problems","write","referenceTargets","kinds","rules","pluginId","field","count","request","countOverlayBeaconOnPlatform","lazyConversionCreditor","unsubscribed","countCampaignSendUnsubscribe","list","emailSendRecordIndex","get","load","marketingConversionCreditor","resolveTouch","creditConversion","creditOrder","reverseOrder","recordClick","click","creditOutcome","erasePerson","key"],"mappings":"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"}