@tn3w/openage 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openage.min.js","sources":["../src/ui.js","../src/constants.js","../src/widget.js","../src/face-tracker.js","../src/age-estimator.js","../src/liveness.js","../src/transport.js","../src/vm-client.js","../src/challenge.js","../src/positioning.js","../src/index.js"],"sourcesContent":["export const FACE_SVG = `<svg viewBox=\"0 0 100 120\"\n fill=\"none\" class=\"oa-face-svg\">\n <ellipse cx=\"50\" cy=\"55\" rx=\"35\" ry=\"45\"\n stroke=\"currentColor\" stroke-width=\"1.8\"/>\n <ellipse cx=\"36\" cy=\"45\" rx=\"5\" ry=\"3.5\"\n fill=\"currentColor\" class=\"oa-eye\"/>\n <ellipse cx=\"64\" cy=\"45\" rx=\"5\" ry=\"3.5\"\n fill=\"currentColor\" class=\"oa-eye\"/>\n <line x1=\"50\" y1=\"52\" x2=\"48\" y2=\"62\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\"/>\n <path d=\"M40 72 Q50 79 60 72\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" fill=\"none\"/>\n</svg>`;\n\nexport const FACE_ICON_SVG = `<svg viewBox=\"0 0 100 120\"\n fill=\"none\" class=\"oa-face-icon-svg\">\n <ellipse cx=\"50\" cy=\"55\" rx=\"35\" ry=\"45\"\n stroke=\"currentColor\" stroke-width=\"2\"/>\n <ellipse cx=\"36\" cy=\"45\" rx=\"5\" ry=\"3.5\"\n fill=\"currentColor\" class=\"oa-eye\"/>\n <ellipse cx=\"64\" cy=\"45\" rx=\"5\" ry=\"3.5\"\n fill=\"currentColor\" class=\"oa-eye\"/>\n <line x1=\"50\" y1=\"52\" x2=\"48\" y2=\"62\"\n stroke=\"currentColor\" stroke-width=\"1.65\"\n stroke-linecap=\"round\"/>\n <path d=\"M40 72 Q50 79 60 72\"\n stroke=\"currentColor\" stroke-width=\"1.65\"\n stroke-linecap=\"round\" fill=\"none\"/>\n</svg>`;\n\nexport const FACE_GUIDE_SVG = `<svg viewBox=\"0 0 100 120\"\n fill=\"none\" class=\"oa-face-svg\">\n <ellipse cx=\"50\" cy=\"55\" rx=\"35\" ry=\"45\"\n stroke=\"currentColor\" stroke-width=\"1.8\"\n stroke-dasharray=\"6 4\"/>\n <ellipse cx=\"36\" cy=\"45\" rx=\"5\" ry=\"3.5\"\n fill=\"currentColor\" class=\"oa-eye\"/>\n <ellipse cx=\"64\" cy=\"45\" rx=\"5\" ry=\"3.5\"\n fill=\"currentColor\" class=\"oa-eye\"/>\n <line x1=\"50\" y1=\"52\" x2=\"48\" y2=\"62\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\"/>\n <path d=\"M40 72 Q50 79 60 72\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" fill=\"none\"/>\n</svg>`;\n\nexport const CHECK_SVG = `<svg viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n</svg>`;\n\nexport const CLOSE_SVG = `<svg viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n</svg>`;\n\nexport const RETRY_SVG = `<svg viewBox=\"0 0 16 16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"currentColor\">\n <path d=\"m14.955 7.986.116.01a1 1 0 0 1 .85 1.13 8 8 0 0 1-13.374 4.728l-.84.84c-.63.63-1.707.184-1.707-.707V10h3.987c.89 0 1.337 1.077.707 1.707l-.731.731a6 6 0 0 0 8.347-.264 6 6 0 0 0 1.63-3.33 1 1 0 0 1 1.131-.848zM11.514.813a8 8 0 0 1 1.942 1.336l.837-.837c.63-.63 1.707-.184 1.707.707V6h-3.981c-.89 0-1.337-1.077-.707-1.707l.728-.729a6 6 0 0 0-9.98 3.591 1 1 0 1 1-1.98-.281A8 8 0 0 1 11.514.813\"/>\n</svg>`;\n\nexport const SPINNER_SVG = `<svg viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" opacity=\"0.2\"/>\n <path d=\"M12 2 A10 10 0 0 1 22 12\"\n stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\"\n type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n</svg>`;\n\nexport const SHIELD_SVG = `<svg viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <path d=\"M12 2l8 4v6c0 5.5-3.8 10-8 12\n C7.8 22 4 17.5 4 12V6l8-4z\"/>\n <path d=\"M9 12l2 2 4-4\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>`;\n\nexport function resolveTheme(theme) {\n if (theme === 'light' || theme === 'dark') return theme;\n return resolveAutoTheme();\n}\n\nexport function watchTheme(host, theme) {\n if (theme === 'light' || theme === 'dark') return;\n if (typeof window === 'undefined') return;\n\n const update = () => {\n host.setAttribute('data-theme', resolveAutoTheme());\n };\n\n const cleanups = [];\n\n for (const query of ['(prefers-color-scheme: dark)', '(prefers-color-scheme: light)']) {\n const cleanup = watchMediaQuery(query, update);\n if (cleanup) cleanups.push(cleanup);\n }\n\n if (typeof MutationObserver === 'function') {\n const observer = new MutationObserver(update);\n const options = {\n attributes: true,\n attributeFilter: ['class', 'data-theme', 'style'],\n };\n\n if (document.documentElement) {\n observer.observe(document.documentElement, options);\n }\n\n if (document.body) {\n observer.observe(document.body, options);\n }\n\n cleanups.push(() => observer.disconnect());\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\nfunction resolveAutoTheme() {\n if (typeof window === 'undefined') return 'dark';\n\n const documentTheme = resolveDocumentTheme();\n if (documentTheme) return documentTheme;\n\n const systemTheme = resolveSystemTheme();\n if (systemTheme) return systemTheme;\n\n return 'dark';\n}\n\nfunction resolveSystemTheme() {\n if (typeof window.matchMedia !== 'function') {\n return null;\n }\n\n if (window.matchMedia('(prefers-color-scheme: dark)').matches) {\n return 'dark';\n }\n\n if (window.matchMedia('(prefers-color-scheme: light)').matches) {\n return 'light';\n }\n\n return null;\n}\n\nfunction resolveDocumentTheme() {\n if (typeof document === 'undefined') return null;\n\n for (const element of [document.documentElement, document.body]) {\n const theme = readThemeHint(element);\n if (theme) return theme;\n }\n\n return null;\n}\n\nfunction readThemeHint(element) {\n if (!element || typeof window.getComputedStyle !== 'function') {\n return null;\n }\n\n const explicit = readExplicitTheme(element);\n if (explicit) return explicit;\n\n const styles = window.getComputedStyle(element);\n const scheme = parseColorScheme(styles.colorScheme);\n if (scheme) return scheme;\n\n return parseBackgroundTheme(styles.backgroundColor);\n}\n\nfunction readExplicitTheme(element) {\n const attrTheme = element.getAttribute('data-theme');\n if (attrTheme === 'light' || attrTheme === 'dark') {\n return attrTheme;\n }\n\n const className = element.className;\n if (typeof className !== 'string') return null;\n\n if (/\\bdark\\b|theme-dark|dark-theme/i.test(className)) {\n return 'dark';\n }\n\n if (/\\blight\\b|theme-light|light-theme/i.test(className)) {\n return 'light';\n }\n\n return null;\n}\n\nfunction parseColorScheme(value) {\n if (!value || value === 'normal') return null;\n\n const normalized = value.toLowerCase();\n const hasDark = normalized.includes('dark');\n const hasLight = normalized.includes('light');\n\n if (hasDark && !hasLight) return 'dark';\n if (hasLight && !hasDark) return 'light';\n\n return null;\n}\n\nfunction parseBackgroundTheme(value) {\n if (!value || value === 'transparent') return null;\n\n const match = value.match(/rgba?\\(([^)]+)\\)/i);\n if (!match) return null;\n\n const parts = match[1]\n .split(',')\n .slice(0, 3)\n .map((part) => Number.parseFloat(part.trim()));\n\n if (parts.length !== 3 || parts.some(Number.isNaN)) {\n return null;\n }\n\n const [red, green, blue] = parts;\n const brightness = (red * 299 + green * 587 + blue * 114) / 1000;\n\n if (brightness <= 140) return 'dark';\n if (brightness >= 180) return 'light';\n\n return null;\n}\n\nfunction watchMediaQuery(query, listener) {\n if (typeof window.matchMedia !== 'function') {\n return null;\n }\n\n const mediaQuery = window.matchMedia(query);\n\n if (typeof mediaQuery.addEventListener === 'function') {\n mediaQuery.addEventListener('change', listener);\n return () => {\n mediaQuery.removeEventListener('change', listener);\n };\n }\n\n if (typeof mediaQuery.addListener === 'function') {\n mediaQuery.addListener(listener);\n return () => {\n mediaQuery.removeListener(listener);\n };\n }\n\n return null;\n}\n\nexport const STYLES = `\n:host {\n --oa-bg: #0b0d11;\n --oa-surface: #14161d;\n --oa-border: #1f2230;\n --oa-text: #e8e8ed;\n --oa-text-muted: #7a7d8c;\n --oa-accent: #4ae68a;\n --oa-accent-dim: rgba(74, 230, 138, 0.12);\n --oa-danger: #ef4444;\n --oa-warn: #f59e0b;\n --oa-radius: 16px;\n --oa-font: 'DM Sans', system-ui, -apple-system,\n sans-serif;\n --oa-mono: 'Space Mono', monospace;\n\n display: block;\n font-family: var(--oa-font);\n color: var(--oa-text);\n line-height: 1.4;\n}\n\n:host([data-theme=\"light\"]) {\n --oa-bg: #f8f9fb;\n --oa-surface: #ffffff;\n --oa-border: #e2e4ea;\n --oa-text: #1a1c24;\n --oa-text-muted: #6b6e7b;\n --oa-accent: #22c55e;\n --oa-accent-dim: rgba(34, 197, 94, 0.1);\n}\n\n* { box-sizing: border-box; margin: 0; padding: 0; }\n\n/* ── Checkbox ────────────────────────────────── */\n\n.oa-checkbox {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n background: var(--oa-surface);\n border: 2px solid var(--oa-border);\n border-radius: var(--oa-radius);\n cursor: pointer;\n user-select: none;\n transition: border-color 0.2s, box-shadow 0.2s;\n}\n\n.oa-checkbox:hover {\n border-color: var(--oa-text-muted);\n}\n\n.oa-checkbox.oa-verified {\n border-color: var(--oa-accent);\n cursor: default;\n}\n\n.oa-checkbox.oa-failed {\n border-color: var(--oa-danger);\n}\n\n.oa-checkbox.oa-retry {\n border-color: var(--oa-danger);\n}\n\n.oa-checkbox.oa-expired {\n border-color: var(--oa-warn);\n}\n\n.oa-checkbox.oa-loading {\n align-items: center;\n}\n\n.oa-check-box {\n width: 24px;\n height: 24px;\n border: 2px solid var(--oa-border);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all 0.2s;\n}\n\n.oa-loading .oa-check-box {\n border-color: transparent;\n background: transparent;\n}\n\n.oa-loading .oa-check-box .oa-spinner {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n transform: translateY(2px);\n}\n\n.oa-verified .oa-check-box {\n background: var(--oa-accent);\n border-color: var(--oa-accent);\n color: var(--oa-bg);\n}\n\n.oa-failed .oa-check-box {\n background: var(--oa-danger);\n border-color: var(--oa-danger);\n color: white;\n}\n\n.oa-retry .oa-check-box {\n background: var(--oa-danger);\n border-color: var(--oa-danger);\n color: white;\n}\n\n.oa-check-box svg {\n width: 14px;\n height: 14px;\n}\n\n.oa-check-box .oa-spinner svg {\n width: 18px;\n height: 18px;\n}\n\n.oa-label {\n display: flex;\n flex-direction: column;\n gap: 1px;\n flex: 1;\n min-width: 0;\n}\n\n.oa-label-text {\n font-size: 13px;\n font-weight: 600;\n}\n\n.oa-right-section {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n margin-left: auto;\n}\n\n.oa-face-icon-wrap {\n width: 18px;\n height: 22px;\n color: var(--oa-text-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.oa-face-icon-wrap .oa-face-icon-svg {\n width: 100%;\n height: 100%;\n}\n\n.oa-face-icon-wrap .oa-eye {\n transform-box: fill-box;\n transform-origin: center;\n animation: oa-idle-blink 5s ease-in-out infinite;\n}\n\n.oa-face-icon-wrap .oa-face-icon-svg {\n animation: oa-breathe 4s ease-in-out infinite;\n}\n\n.oa-branding-row {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n}\n\n.oa-branding-link {\n font-size: 10px;\n font-weight: 700;\n font-family: var(--oa-mono);\n color: var(--oa-text-muted);\n text-decoration: none;\n letter-spacing: -0.02em;\n cursor: pointer;\n}\n\n.oa-branding-link:hover {\n color: var(--oa-text);\n}\n\n.oa-links-row {\n display: flex;\n gap: 6px;\n justify-content: center;\n}\n\n.oa-links-row a {\n font-size: 9px;\n color: var(--oa-text-muted);\n text-decoration: none;\n opacity: 0.7;\n cursor: pointer;\n}\n\n.oa-links-row a:hover {\n opacity: 1;\n text-decoration: underline;\n}\n\n.oa-compact .oa-label-text {\n font-size: 11px;\n}\n\n.oa-compact .oa-face-icon-wrap {\n width: 16px;\n height: 20px;\n}\n\n/* ── Error banner (inline in checkbox) ───────── */\n\n.oa-error-banner {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n margin-top: 6px;\n background: rgba(239, 68, 68, 0.08);\n border: 1px solid rgba(239, 68, 68, 0.2);\n border-radius: 8px;\n font-size: 12px;\n color: var(--oa-danger);\n animation: oa-fade-in 0.3s ease;\n}\n\n.oa-error-banner button {\n margin-left: auto;\n background: none;\n border: 1px solid var(--oa-danger);\n border-radius: 6px;\n color: var(--oa-danger);\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n cursor: pointer;\n font-family: var(--oa-font);\n flex-shrink: 0;\n}\n\n.oa-error-banner button:hover {\n background: rgba(239, 68, 68, 0.1);\n}\n\n/* ── Popup / Modal shell ─────────────────────── */\n\n.oa-popup {\n position: fixed;\n z-index: 100000;\n background: var(--oa-bg);\n border: 1px solid var(--oa-border);\n border-radius: var(--oa-radius);\n box-shadow: 0 20px 60px rgba(0,0,0,0.4),\n 0 0 0 1px rgba(0,0,0,0.08);\n width: 340px;\n max-height: 90vh;\n overflow: hidden;\n animation: oa-popup-in 0.25s ease;\n display: flex;\n flex-direction: column;\n}\n\n.oa-modal-overlay {\n position: fixed;\n inset: 0;\n z-index: 99999;\n background: rgba(0,0,0,0.65);\n display: flex;\n align-items: center;\n justify-content: center;\n animation: oa-fade-in 0.2s ease;\n backdrop-filter: blur(6px);\n}\n\n.oa-modal {\n background: var(--oa-bg);\n border: 1px solid var(--oa-border);\n border-radius: var(--oa-radius);\n width: 360px;\n max-width: 95vw;\n max-height: 95vh;\n overflow: hidden;\n animation: oa-slide-in 0.3s ease;\n display: flex;\n flex-direction: column;\n}\n\n/* ── Header ──────────────────────────────────── */\n\n.oa-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n border-bottom: 1px solid var(--oa-border);\n flex-shrink: 0;\n}\n\n.oa-logo {\n font-family: var(--oa-mono);\n font-size: 0.85rem;\n letter-spacing: -0.03em;\n color: var(--oa-text-muted);\n text-decoration: none;\n cursor: pointer;\n}\n\n.oa-logo:hover {\n color: var(--oa-text);\n}\n\n.oa-logo strong {\n color: var(--oa-text);\n font-weight: 700;\n}\n\n.oa-badge {\n font-size: 0.55rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--oa-accent);\n background: var(--oa-accent-dim);\n padding: 2px 6px;\n border-radius: 100px;\n margin-left: 6px;\n}\n\n.oa-title {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.oa-close-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n color: var(--oa-text-muted);\n transition: background 0.15s, color 0.15s;\n}\n\n.oa-close-btn:hover {\n background: var(--oa-border);\n color: var(--oa-text);\n}\n\n.oa-close-btn svg {\n width: 16px;\n height: 16px;\n}\n\n/* ── Body (viewport) ─────────────────────────── */\n\n.oa-body {\n flex: 1;\n position: relative;\n overflow: hidden;\n}\n\n/* ── Hero / start screen ─────────────────────── */\n\n.oa-hero {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 1rem;\n padding: 2rem 1.2rem 1.2rem;\n background: var(--oa-surface);\n border: 1px solid var(--oa-border);\n border-radius: var(--oa-radius);\n margin: 10px;\n animation: oa-fade-in 0.4s ease;\n}\n\n.oa-hero-icon {\n width: 80px;\n height: 96px;\n color: var(--oa-text-muted);\n}\n\n.oa-hero-icon .oa-face-svg.oa-idle {\n animation: oa-breathe 4s ease-in-out infinite;\n}\n\n.oa-hero-icon .oa-eye {\n transform-box: fill-box;\n transform-origin: center;\n animation: oa-idle-blink 5s ease-in-out infinite;\n}\n\n.oa-hero-status {\n color: var(--oa-text-muted);\n font-size: 0.8rem;\n font-weight: 500;\n text-align: center;\n min-height: 1.4em;\n}\n\n.oa-hero-privacy {\n font-size: 0.68rem;\n color: var(--oa-text-muted);\n text-align: center;\n line-height: 1.5;\n max-width: 260px;\n opacity: 0.7;\n}\n\n.oa-hero-privacy svg {\n width: 10px;\n height: 10px;\n vertical-align: -2px;\n margin-right: 2px;\n}\n\n/* ── Start / Retry button ────────────────────── */\n\n.oa-actions {\n display: flex;\n justify-content: center;\n padding: 0 14px 14px;\n flex-shrink: 0;\n}\n\n.oa-btn {\n font-family: var(--oa-font);\n padding: 0.55rem 1.5rem;\n border: none;\n border-radius: 10px;\n font-size: 0.8rem;\n font-weight: 600;\n cursor: pointer;\n background: var(--oa-accent);\n color: var(--oa-bg);\n transition: transform 0.12s, opacity 0.15s;\n width: 100%;\n max-width: 240px;\n}\n\n.oa-btn:hover { opacity: 0.88; }\n.oa-btn:active { transform: scale(0.97); }\n\n/* ── Video area ──────────────────────────────── */\n\n.oa-video-area {\n position: relative;\n width: 100%;\n aspect-ratio: 3/4;\n max-height: 55vh;\n background: var(--oa-surface);\n overflow: hidden;\n border-radius: var(--oa-radius);\n margin: 10px;\n width: calc(100% - 20px);\n border: 1px solid var(--oa-border);\n animation: oa-fade-in 0.3s ease;\n}\n\n.oa-video-area video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transform: scaleX(-1);\n}\n\n/* ── Face guide overlay ──────────────────────── */\n\n.oa-face-guide {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 80%;\n max-width: 360px;\n aspect-ratio: 5/6;\n perspective: 400px;\n color: rgba(255, 255, 255, 0.45);\n pointer-events: none;\n z-index: 2;\n transition: opacity 0.4s ease;\n}\n\n.oa-face-guide .oa-face-svg {\n width: 100%;\n height: 100%;\n transform-origin: center center;\n filter: drop-shadow(\n 0 0 16px rgba(15, 23, 42, 0.16)\n );\n}\n\n.oa-face-guide .oa-eye {\n transform-box: fill-box;\n transform-origin: center;\n}\n\n.oa-face-guide[data-task=\"turn-left\"] .oa-face-svg {\n animation: oa-turn-left 2s ease-in-out infinite;\n}\n.oa-face-guide[data-task=\"turn-right\"] .oa-face-svg {\n animation: oa-turn-right 2s ease-in-out infinite;\n}\n.oa-face-guide[data-task=\"nod\"] .oa-face-svg {\n animation: oa-nod 2s ease-in-out infinite;\n}\n.oa-face-guide[data-task=\"blink-twice\"] .oa-eye {\n animation: oa-blink 2.4s ease-in-out infinite;\n}\n.oa-face-guide[data-task=\"move-closer\"] .oa-face-svg {\n animation: oa-closer 2.5s ease-in-out infinite;\n}\n\n/* ── Challenge HUD (bottom gradient overlay) ── */\n\n.oa-challenge-hud {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 1rem 0.8rem 0.6rem;\n background: linear-gradient(\n to top,\n rgba(11, 13, 17, 0.92) 0%,\n rgba(11, 13, 17, 0) 100%\n );\n z-index: 3;\n pointer-events: none;\n}\n\n.oa-challenge-text {\n font-size: 0.85rem;\n font-weight: 600;\n text-align: center;\n color: var(--oa-text);\n text-shadow: 0 1px 6px rgba(0, 0, 0, 0.7);\n margin-bottom: 0.4rem;\n}\n\n.oa-challenge-bar {\n height: 3px;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 2px;\n overflow: hidden;\n}\n\n.oa-challenge-fill {\n height: 100%;\n background: var(--oa-accent);\n border-radius: 2px;\n transition: width 0.25s ease;\n}\n\n/* ── Video status (top gradient overlay) ─────── */\n\n.oa-video-status {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n padding: 0.8rem 0.8rem 1.2rem;\n background: linear-gradient(\n to bottom,\n rgba(11, 13, 17, 0.85) 0%,\n rgba(11, 13, 17, 0) 100%\n );\n z-index: 3;\n pointer-events: none;\n}\n\n.oa-video-status p {\n font-size: 0.75rem;\n font-weight: 500;\n text-align: center;\n color: var(--oa-text-muted);\n text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);\n}\n\n/* ── Result area ─────────────────────────────── */\n\n.oa-result {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5rem;\n padding: 2rem 1.2rem;\n background: var(--oa-surface);\n border: 1px solid var(--oa-border);\n border-radius: var(--oa-radius);\n margin: 10px;\n animation: oa-fade-in 0.4s ease;\n}\n\n.oa-result-icon {\n font-size: 2.4rem;\n line-height: 1;\n}\n\n.oa-result-text {\n font-size: 0.85rem;\n font-weight: 500;\n text-align: center;\n}\n\n.oa-result-pass { color: var(--oa-accent); }\n.oa-result-fail { color: var(--oa-danger); }\n.oa-result-retry { color: var(--oa-warn); }\n\n.oa-hidden { display: none !important; }\n\n/* ── Animations ──────────────────────────────── */\n\n@keyframes oa-popup-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n@keyframes oa-fade-in {\n from { opacity: 0; transform: translateY(6px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes oa-slide-in {\n from { opacity: 0; transform: translateY(16px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes oa-breathe {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(1.04); }\n}\n\n@keyframes oa-idle-blink {\n 0%, 42%, 48%, 100% { transform: scaleY(1); }\n 44%, 46% { transform: scaleY(0.05); }\n}\n\n@keyframes oa-turn-left {\n 0%, 100% { transform: rotateY(0); }\n 35%, 65% { transform: rotateY(-30deg); }\n}\n\n@keyframes oa-turn-right {\n 0%, 100% { transform: rotateY(0); }\n 35%, 65% { transform: rotateY(30deg); }\n}\n\n@keyframes oa-nod {\n 0%, 100% { transform: rotateX(0); }\n 30%, 50% { transform: rotateX(25deg); }\n}\n\n@keyframes oa-blink {\n 0%, 18%, 32%, 50%, 100% { transform: scaleY(1); }\n 22%, 28% { transform: scaleY(0.05); }\n 40%, 46% { transform: scaleY(0.05); }\n}\n\n@keyframes oa-closer {\n 0%, 100% { transform: scale(1); }\n 35%, 55% { transform: scale(1.3); }\n}\n`;\n\nexport function checkboxTemplate(labelText) {\n return `\n <div class=\"oa-widget-wrap\">\n <div class=\"oa-checkbox\" role=\"checkbox\"\n aria-checked=\"false\" tabindex=\"0\">\n <div class=\"oa-check-box\"></div>\n <div class=\"oa-label\">\n <span class=\"oa-label-text\">${labelText}</span>\n </div>\n <div class=\"oa-right-section\">\n <div class=\"oa-branding-row\">\n <div class=\"oa-face-icon-wrap\">\n ${FACE_ICON_SVG}\n </div>\n <a class=\"oa-branding-link\"\n href=\"https://github.com/tn3w/OpenAge\"\n target=\"_blank\" rel=\"noopener\">OpenAge</a>\n </div>\n <div class=\"oa-links-row\">\n <a href=\"https://github.com/tn3w/OpenAge\"\n target=\"_blank\"\n rel=\"noopener\">Terms</a>\n <a href=\"https://github.com/tn3w/OpenAge\"\n target=\"_blank\"\n rel=\"noopener\">Privacy</a>\n </div>\n </div>\n </div>\n <div class=\"oa-error-slot\"></div>\n </div>\n `;\n}\n\nexport function heroTemplate(statusText) {\n return `\n <div class=\"oa-hero\">\n <div class=\"oa-hero-icon\">\n ${FACE_SVG.replace('class=\"oa-face-svg\"', 'class=\"oa-face-svg oa-idle\"')}\n </div>\n <p class=\"oa-hero-status\">${statusText}</p>\n <p class=\"oa-hero-privacy\">\n ${SHIELD_SVG}\n Open-source &amp; privacy-focused.\n No photos or camera data leave your device.\n </p>\n </div>\n `;\n}\n\nexport function challengeTemplate() {\n return `\n <div class=\"oa-video-area\">\n <video autoplay playsinline muted></video>\n <div class=\"oa-face-guide\">\n ${FACE_GUIDE_SVG}\n </div>\n <div class=\"oa-challenge-hud oa-hidden\">\n <p class=\"oa-challenge-text\"></p>\n <div class=\"oa-challenge-bar\">\n <div class=\"oa-challenge-fill\"\n style=\"width:0%\"></div>\n </div>\n </div>\n <div class=\"oa-video-status\">\n <p></p>\n </div>\n </div>\n `;\n}\n\nexport function resultTemplate(outcome, message) {\n const icons = {\n fail: '✕',\n retry: '↻',\n };\n const classes = {\n fail: 'oa-result-fail',\n retry: 'oa-result-retry',\n };\n return `\n <div class=\"oa-result ${classes[outcome] || ''}\">\n <div class=\"oa-result-icon\">\n ${icons[outcome] || '?'}\n </div>\n <div class=\"oa-result-text\">${message}</div>\n </div>\n `;\n}\n\nexport function errorBannerTemplate(message) {\n return `\n <div class=\"oa-error-banner\">\n <span>${message}</span>\n <button class=\"oa-retry-btn\">Retry</button>\n </div>\n `;\n}\n","export const VERSION = '1.0.0';\n\nexport const MEDIAPIPE_CDN = 'https://cdn.jsdelivr.net/npm/' + '@mediapipe/tasks-vision@0.10.17';\n\nexport const MEDIAPIPE_WASM = `${MEDIAPIPE_CDN}/wasm`;\n\nexport const MEDIAPIPE_VISION = `${MEDIAPIPE_CDN}/vision_bundle.mjs`;\n\nexport const MEDIAPIPE_MODEL =\n 'https://storage.googleapis.com/mediapipe-models/' +\n 'face_landmarker/face_landmarker/float16/latest/' +\n 'face_landmarker.task';\n\nexport const FACEAPI_CDN =\n 'https://cdn.jsdelivr.net/npm/' + 'face-api.js@0.22.2/dist/face-api.min.js';\n\nexport const FACEAPI_MODEL_CDN = 'https://cdn.jsdelivr.net/npm/' + 'face-api.js@0.22.2/weights';\n\nexport const MAX_RETRIES = 3;\nexport const BURST_FRAMES = 5;\nexport const BURST_INTERVAL_MS = 200;\nexport const POSITION_CHECK_MS = 100;\nexport const MOTION_CAPTURE_MS = 3000;\nexport const MOTION_SAMPLE_MS = 100;\nexport const TOKEN_EXPIRY_S = 300;\nexport const STABLE_FRAMES_REQUIRED = 10;\n\nexport const TASK_TIMEOUT_MS = 8000;\nexport const MIN_TASK_TIME_MS = 500;\nexport const TASK_COUNT = 3;\nexport const REQUIRED_TASK_PASSES = 2;\n\nexport const POPUP_MIN_WIDTH = 340;\nexport const POPUP_MIN_HEIGHT = 520;\nexport const POPUP_MARGIN = 12;\n","import {\n STYLES,\n checkboxTemplate,\n heroTemplate,\n challengeTemplate,\n resultTemplate,\n resolveTheme,\n watchTheme,\n SPINNER_SVG,\n CHECK_SVG,\n CLOSE_SVG,\n RETRY_SVG,\n} from './ui.js';\nimport { POPUP_MIN_WIDTH, POPUP_MIN_HEIGHT, POPUP_MARGIN } from './constants.js';\n\nlet widgetCounter = 0;\n\nexport class Widget {\n constructor(container, params) {\n this.id = `oa-${++widgetCounter}`;\n this.params = params;\n this.container = resolveContainer(container);\n this.anchorElement = null;\n this.state = 'idle';\n this.token = null;\n this.popup = null;\n this.shadow = null;\n this.elements = {};\n this.onChallenge = null;\n this.onStartClick = null;\n this.popupFrame = 0;\n this.themeCleanup = null;\n\n this.render();\n }\n\n render() {\n const host = document.createElement('div');\n host.id = this.id;\n this.shadow = host.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = STYLES;\n this.shadow.appendChild(style);\n\n const theme = resolveTheme(this.params.theme);\n host.setAttribute('data-theme', theme);\n this.themeCleanup = watchTheme(host, this.params.theme);\n\n if (this.params.size === 'invisible') {\n host.style.display = 'none';\n this.container.appendChild(host);\n this.host = host;\n return;\n }\n\n const label = 'I am of age';\n\n const wrapper = document.createElement('div');\n wrapper.innerHTML = checkboxTemplate(label);\n this.shadow.appendChild(wrapper.firstElementChild);\n\n const checkbox = this.shadow.querySelector('.oa-checkbox');\n\n if (this.params.size === 'compact') {\n checkbox.classList.add('oa-compact');\n }\n\n checkbox.addEventListener('click', (event) => {\n if (event.target.closest('a')) return;\n if (this.state === 'verified') return;\n if (this.state === 'loading') return;\n this.clearError();\n this.startChallenge();\n });\n\n checkbox.addEventListener('keydown', (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n checkbox.click();\n }\n });\n\n this.elements.checkbox = checkbox;\n this.elements.checkBox = this.shadow.querySelector('.oa-check-box');\n this.elements.errorSlot = this.shadow.querySelector('.oa-error-slot');\n\n this.container.appendChild(host);\n this.host = host;\n }\n\n startChallenge() {\n this.setState('loading');\n\n if (this.onChallenge) {\n this.onChallenge(this);\n }\n }\n\n createPopupShell() {\n const theme = resolveTheme(this.params.theme);\n const popupHost = document.createElement('div');\n popupHost.setAttribute('data-theme', theme);\n const popupShadow = popupHost.attachShadow({\n mode: 'open',\n });\n\n const style = document.createElement('style');\n style.textContent = STYLES;\n popupShadow.appendChild(style);\n\n const themeCleanup = watchTheme(popupHost, this.params.theme);\n\n return {\n popupHost,\n popupShadow,\n themeCleanup,\n };\n }\n\n openPopup() {\n if (this.popup) return this.getVideo();\n\n const anchor = this.getPopupAnchor();\n\n if (!anchor) {\n return this.openModal();\n }\n\n const { popupHost, popupShadow, themeCleanup } = this.createPopupShell();\n\n const popup = document.createElement('div');\n popup.className = 'oa-popup';\n popup.innerHTML = this.buildPopupContent();\n popup.style.visibility = 'hidden';\n popup.style.pointerEvents = 'none';\n\n popupShadow.appendChild(popup);\n document.body.appendChild(popupHost);\n\n this.popup = {\n anchor,\n host: popupHost,\n root: popup,\n themeCleanup,\n };\n\n const anchorRect = anchor.getBoundingClientRect();\n const popupRect = popup.getBoundingClientRect();\n const position = findPopupPosition(anchorRect, popupRect);\n\n if (position.mode === 'modal') {\n popupHost.remove();\n themeCleanup?.();\n this.popup = null;\n return this.openModal();\n }\n\n this.bindPopupEvents(popup, popupShadow);\n this.updatePopupPosition();\n this.startPopupTracking();\n return this.getVideo();\n }\n\n openModal() {\n const { popupHost, popupShadow, themeCleanup } = this.createPopupShell();\n\n const overlay = document.createElement('div');\n overlay.className = 'oa-modal-overlay';\n\n const modal = document.createElement('div');\n modal.className = 'oa-modal';\n modal.innerHTML = this.buildPopupContent();\n\n overlay.appendChild(modal);\n popupShadow.appendChild(overlay);\n document.body.appendChild(popupHost);\n\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) this.closePopup();\n });\n\n this.popup = {\n host: popupHost,\n root: modal,\n overlay,\n themeCleanup,\n };\n this.bindPopupEvents(modal, popupShadow);\n return this.getVideo();\n }\n\n getPopupAnchor() {\n return this.anchorElement || this.elements.checkbox || this.host || null;\n }\n\n startPopupTracking() {\n if (!this.popup || this.popup.overlay) return;\n\n const schedule = () => {\n this.schedulePopupPosition();\n };\n\n const cleanups = [];\n const addWindowListener = (name, options) => {\n window.addEventListener(name, schedule, options);\n cleanups.push(() => {\n window.removeEventListener(name, schedule, options);\n });\n };\n\n addWindowListener('resize', { passive: true });\n addWindowListener('scroll', {\n capture: true,\n passive: true,\n });\n\n if (window.visualViewport) {\n const viewport = window.visualViewport;\n viewport.addEventListener('resize', schedule);\n viewport.addEventListener('scroll', schedule);\n cleanups.push(() => {\n viewport.removeEventListener('resize', schedule);\n viewport.removeEventListener('scroll', schedule);\n });\n }\n\n if (typeof ResizeObserver === 'function') {\n const observer = new ResizeObserver(() => {\n schedule();\n });\n observer.observe(this.popup.root);\n observer.observe(this.popup.anchor);\n observer.observe(document.documentElement);\n if (document.body) {\n observer.observe(document.body);\n }\n cleanups.push(() => observer.disconnect());\n }\n\n this.popup.cleanup = () => {\n if (this.popupFrame) {\n cancelAnimationFrame(this.popupFrame);\n this.popupFrame = 0;\n }\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n schedulePopupPosition() {\n if (!this.popup || this.popup.overlay) return;\n if (this.popupFrame) return;\n\n this.popupFrame = requestAnimationFrame(() => {\n this.popupFrame = 0;\n this.updatePopupPosition();\n });\n }\n\n updatePopupPosition() {\n if (!this.popup || this.popup.overlay) return;\n\n const anchor = this.getPopupAnchor();\n if (!anchor || !anchor.isConnected) {\n this.closePopup();\n return;\n }\n\n this.popup.anchor = anchor;\n\n const anchorRect = anchor.getBoundingClientRect();\n const popupRect = this.popup.root.getBoundingClientRect();\n const position = findPopupPosition(anchorRect, popupRect);\n\n if (position.mode === 'modal') {\n this.closePopup();\n this.openModal();\n return;\n }\n\n const top = `${Math.round(position.top)}px`;\n const left = `${Math.round(position.left)}px`;\n\n if (this.popup.root.style.top !== top) {\n this.popup.root.style.top = top;\n }\n\n if (this.popup.root.style.left !== left) {\n this.popup.root.style.left = left;\n }\n\n this.popup.root.dataset.placement = position.placement;\n this.popup.root.style.visibility = 'visible';\n this.popup.root.style.pointerEvents = 'auto';\n }\n\n buildPopupContent() {\n return `\n <div class=\"oa-header\">\n <div class=\"oa-title\">\n <a class=\"oa-logo\"\n href=\"https://github.com/tn3w/OpenAge\"\n target=\"_blank\" rel=\"noopener\">\n Open<strong>Age</strong>\n </a>\n <span class=\"oa-badge\">on-device</span>\n </div>\n <button class=\"oa-close-btn\"\n aria-label=\"Close\">\n ${CLOSE_SVG}\n </button>\n </div>\n <div class=\"oa-body\">\n ${heroTemplate('Initializing…')}\n </div>\n <div class=\"oa-actions oa-hidden\">\n <button class=\"oa-btn oa-start-btn\">\n Begin Verification\n </button>\n </div>\n `;\n }\n\n bindPopupEvents(root, shadow) {\n const closeBtn = root.querySelector('.oa-close-btn');\n if (closeBtn) {\n closeBtn.addEventListener('click', () => {\n this.closePopup();\n this.params.closeCallback?.();\n });\n }\n\n const startBtn = root.querySelector('.oa-start-btn');\n if (startBtn) {\n startBtn.addEventListener('click', () => {\n if (this.onStartClick) this.onStartClick();\n });\n }\n\n this.popupElements = {\n body: root.querySelector('.oa-body'),\n actions: root.querySelector('.oa-actions'),\n startBtn,\n heroStatus: root.querySelector('.oa-hero-status'),\n };\n }\n\n getVideo() {\n if (!this.popup) return null;\n return this.popup.root.querySelector('video');\n }\n\n showHero(statusText) {\n if (!this.popupElements?.body) return;\n this.popupElements.body.innerHTML = heroTemplate(statusText);\n this.popupElements.heroStatus = this.popupElements.body.querySelector('.oa-hero-status');\n this.hideActions();\n }\n\n showReady() {\n this.setHeroStatus('Ready to verify your age.');\n this.showActions('Begin Verification');\n }\n\n showCamera() {\n if (!this.popupElements?.body) return;\n this.popupElements.body.innerHTML = challengeTemplate();\n\n this.popupElements.video = this.popupElements.body.querySelector('video');\n this.popupElements.faceGuide = this.popupElements.body.querySelector('.oa-face-guide');\n this.popupElements.challengeHud =\n this.popupElements.body.querySelector('.oa-challenge-hud');\n this.popupElements.challengeText =\n this.popupElements.body.querySelector('.oa-challenge-text');\n this.popupElements.challengeFill =\n this.popupElements.body.querySelector('.oa-challenge-fill');\n this.popupElements.videoStatus =\n this.popupElements.body.querySelector('.oa-video-status p');\n\n this.hideActions();\n return this.popupElements.video;\n }\n\n showLiveness() {\n if (this.popupElements?.faceGuide) {\n this.popupElements.faceGuide.classList.remove('oa-hidden');\n }\n if (this.popupElements?.challengeHud) {\n this.popupElements.challengeHud.classList.remove('oa-hidden');\n }\n }\n\n setHeroStatus(text) {\n if (this.popupElements?.heroStatus) {\n this.popupElements.heroStatus.textContent = text;\n }\n }\n\n setVideoStatus(text) {\n if (this.popupElements?.videoStatus) {\n this.popupElements.videoStatus.textContent = text;\n }\n }\n\n setInstruction(text) {\n if (this.popupElements?.challengeText) {\n this.popupElements.challengeText.textContent = text;\n }\n }\n\n setStatus(text) {\n this.setVideoStatus(text);\n }\n\n setProgress(fraction) {\n if (this.popupElements?.challengeFill) {\n this.popupElements.challengeFill.style.width = `${Math.round(fraction * 100)}%`;\n }\n }\n\n setTask(taskId) {\n if (this.popupElements?.faceGuide) {\n this.popupElements.faceGuide.setAttribute('data-task', taskId || '');\n }\n }\n\n showActions(label) {\n if (!this.popupElements?.actions) return;\n this.popupElements.actions.classList.remove('oa-hidden');\n if (this.popupElements.startBtn) {\n this.popupElements.startBtn.textContent = label;\n }\n }\n\n hideActions() {\n if (this.popupElements?.actions) {\n this.popupElements.actions.classList.add('oa-hidden');\n }\n }\n\n showResult(outcome, message) {\n if (outcome === 'pass') {\n this.closePopup();\n this.setState('verified');\n return;\n }\n\n if (outcome === 'fail') {\n if (this.params.size === 'invisible') {\n if (this.popupElements?.body) {\n this.popupElements.body.innerHTML = resultTemplate(outcome, message);\n }\n this.hideActions();\n this.showActions('Try Again');\n } else {\n this.closePopup();\n this.setState('retry');\n }\n return;\n }\n\n if (outcome === 'retry') {\n if (this.params.size !== 'invisible') {\n this.closePopup();\n this.setState('retry');\n return;\n }\n\n if (this.popupElements?.body) {\n this.popupElements.body.innerHTML = resultTemplate(outcome, message);\n }\n this.hideActions();\n this.showActions('Try Again');\n }\n }\n\n showError() {\n this.setState('retry');\n }\n\n clearError() {\n if (this.elements.errorSlot) {\n this.elements.errorSlot.innerHTML = '';\n }\n }\n\n closePopup() {\n if (!this.popup) return;\n this.popup.cleanup?.();\n this.popup.themeCleanup?.();\n this.popup.host.remove();\n this.popup = null;\n this.popupElements = null;\n\n if (this.state === 'loading') {\n this.setState('idle');\n }\n }\n\n setState(newState) {\n this.state = newState;\n const cb = this.elements.checkbox;\n const box = this.elements.checkBox;\n if (!cb || !box) return;\n\n cb.classList.remove('oa-loading', 'oa-verified', 'oa-failed', 'oa-retry', 'oa-expired');\n cb.setAttribute('aria-checked', 'false');\n box.innerHTML = '';\n\n switch (newState) {\n case 'loading':\n cb.classList.add('oa-loading');\n box.innerHTML = `<span class=\"oa-spinner\">` + `${SPINNER_SVG}</span>`;\n break;\n case 'verified':\n cb.classList.add('oa-verified');\n cb.setAttribute('aria-checked', 'true');\n box.innerHTML = CHECK_SVG;\n break;\n case 'failed':\n cb.classList.add('oa-failed');\n box.innerHTML = '✕';\n break;\n case 'retry':\n cb.classList.add('oa-retry');\n box.innerHTML = RETRY_SVG;\n break;\n case 'expired':\n cb.classList.add('oa-expired');\n cb.setAttribute('aria-checked', 'false');\n break;\n default:\n break;\n }\n }\n\n getToken() {\n return this.token;\n }\n\n reset() {\n this.token = null;\n this.closePopup();\n this.setState('idle');\n }\n\n destroy() {\n this.closePopup();\n this.themeCleanup?.();\n this.host?.remove();\n }\n}\n\nexport function createModalWidget(params) {\n const widget = new Widget(document.createElement('div'), { ...params, size: 'invisible' });\n return widget;\n}\n\nfunction resolveContainer(container) {\n if (typeof container === 'string') {\n return document.querySelector(container);\n }\n return container;\n}\n\nfunction findPopupPosition(anchorRect, popupRect) {\n const viewport = {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n\n const popupWidth = Math.max(popupRect.width || 0, POPUP_MIN_WIDTH);\n const popupHeight = Math.max(popupRect.height || 0, POPUP_MIN_HEIGHT);\n const availableWidth = viewport.width - POPUP_MARGIN * 2;\n const availableHeight = viewport.height - POPUP_MARGIN * 2;\n\n if (popupWidth > availableWidth || popupHeight > availableHeight) {\n return { mode: 'modal' };\n }\n\n const left = clampLeft(\n anchorRect.left + anchorRect.width / 2 - popupWidth / 2,\n viewport.width,\n popupWidth\n );\n\n const topBelow = anchorRect.bottom + POPUP_MARGIN;\n const topAbove = anchorRect.top - popupHeight - POPUP_MARGIN;\n const fitsBelow = topBelow + popupHeight <= viewport.height - POPUP_MARGIN;\n const fitsAbove = topAbove >= POPUP_MARGIN;\n\n if (fitsBelow || !fitsAbove) {\n return {\n mode: 'popup',\n placement: 'below',\n top: clampTop(topBelow, viewport.height, popupHeight),\n left,\n };\n }\n\n return {\n mode: 'popup',\n placement: 'above',\n top: clampTop(topAbove, viewport.height, popupHeight),\n left,\n };\n}\n\nfunction clampLeft(left, viewportWidth, popupWidth) {\n return Math.min(Math.max(POPUP_MARGIN, left), viewportWidth - popupWidth - POPUP_MARGIN);\n}\n\nfunction clampTop(top, viewportHeight, popupHeight) {\n return Math.min(Math.max(POPUP_MARGIN, top), viewportHeight - popupHeight - POPUP_MARGIN);\n}\n","import { MEDIAPIPE_CDN, MEDIAPIPE_WASM, MEDIAPIPE_VISION, MEDIAPIPE_MODEL } from './constants.js';\n\nlet FaceLandmarker = null;\nlet landmarker = null;\nlet lastTimestampMs = -1;\nlet visionModule = null;\n\nexport async function loadVision() {\n if (visionModule) return visionModule;\n visionModule = await import(MEDIAPIPE_VISION);\n FaceLandmarker = visionModule.FaceLandmarker;\n return visionModule;\n}\n\nexport async function loadModel() {\n const response = await fetch(MEDIAPIPE_MODEL);\n if (!response.ok) {\n throw new Error('Failed to load face landmarker model');\n }\n return new Uint8Array(await response.arrayBuffer());\n}\n\nexport async function initTracker(modelBuffer) {\n const vision = await loadVision();\n const resolver = await vision.FilesetResolver.forVisionTasks(MEDIAPIPE_WASM);\n\n if (landmarker) {\n landmarker.close();\n }\n lastTimestampMs = -1;\n\n landmarker = await FaceLandmarker.createFromOptions(resolver, {\n baseOptions: {\n modelAssetBuffer: new Uint8Array(modelBuffer),\n delegate: 'GPU',\n },\n runningMode: 'VIDEO',\n numFaces: 2,\n outputFaceBlendshapes: true,\n outputFacialTransformationMatrixes: true,\n });\n}\n\nexport function track(video, timestampMs) {\n if (!landmarker) return null;\n\n const normalized = normalizeTimestamp(timestampMs);\n const result = landmarker.detectForVideo(video, normalized);\n const faceCount = result.faceLandmarks?.length ?? 0;\n\n if (faceCount === 0) {\n return { faceCount: 0, timestampMs: normalized };\n }\n\n const landmarks = result.faceLandmarks[0];\n\n return {\n faceCount,\n timestampMs: normalized,\n landmarks,\n blendshapes: parseBlendshapes(result.faceBlendshapes?.[0]),\n headPose: extractHeadPose(result.facialTransformationMatrixes?.[0]),\n boundingBox: computeBoundingBox(landmarks),\n };\n}\n\nexport function destroyTracker() {\n if (landmarker) {\n landmarker.close();\n landmarker = null;\n }\n lastTimestampMs = -1;\n}\n\nexport function isTrackerReady() {\n return landmarker !== null;\n}\n\nfunction normalizeTimestamp(timestampMs) {\n const safe = Number.isFinite(timestampMs) ? timestampMs : performance.now();\n const whole = Math.floor(safe);\n const normalized = Math.max(whole, lastTimestampMs + 1);\n lastTimestampMs = normalized;\n return normalized;\n}\n\nfunction parseBlendshapes(blendshapeResult) {\n if (!blendshapeResult?.categories) return {};\n const map = {};\n for (const category of blendshapeResult.categories) {\n map[category.categoryName] = category.score;\n }\n return map;\n}\n\nfunction extractHeadPose(matrix) {\n if (!matrix?.data || matrix.data.length < 16) {\n return { yaw: 0, pitch: 0, roll: 0 };\n }\n const m = matrix.data;\n const deg = 180 / Math.PI;\n return {\n yaw: Math.atan2(m[8], m[10]) * deg,\n pitch: Math.asin(-Math.max(-1, Math.min(1, m[9]))) * deg,\n roll: Math.atan2(m[1], m[5]) * deg,\n };\n}\n\nfunction computeBoundingBox(landmarks) {\n let minX = 1,\n minY = 1,\n maxX = 0,\n maxY = 0;\n\n for (const point of landmarks) {\n if (point.x < minX) minX = point.x;\n if (point.y < minY) minY = point.y;\n if (point.x > maxX) maxX = point.x;\n if (point.y > maxY) maxY = point.y;\n }\n\n const width = maxX - minX;\n const height = maxY - minY;\n\n return {\n x: minX,\n y: minY,\n width,\n height,\n area: width * height,\n };\n}\n","import { FACEAPI_CDN, FACEAPI_MODEL_CDN } from './constants.js';\n\nlet initialized = false;\nlet faceapi = null;\n\nfunction loadScript(url) {\n return new Promise((resolve, reject) => {\n if (typeof window === 'undefined') {\n return reject(new Error('No DOM available'));\n }\n\n const existing = document.querySelector(`script[src=\"${url}\"]`);\n if (existing) {\n if (window.faceapi) return resolve(window.faceapi);\n existing.addEventListener('load', () => resolve(window.faceapi));\n return;\n }\n\n const script = document.createElement('script');\n script.src = url;\n script.crossOrigin = 'anonymous';\n script.onload = () => resolve(window.faceapi);\n script.onerror = () => reject(new Error(`Failed to load ${url}`));\n document.head.appendChild(script);\n });\n}\n\nexport async function initAgeEstimator() {\n if (initialized) return;\n\n faceapi = await loadScript(FACEAPI_CDN);\n\n await Promise.all([\n faceapi.nets.tinyFaceDetector.loadFromUri(FACEAPI_MODEL_CDN),\n faceapi.nets.faceLandmark68TinyNet.loadFromUri(FACEAPI_MODEL_CDN),\n faceapi.nets.ageGenderNet.loadFromUri(FACEAPI_MODEL_CDN),\n ]);\n\n initialized = true;\n}\n\nexport async function estimateAge(canvas) {\n if (!faceapi) {\n throw new Error('Age estimator not initialized');\n }\n\n const detection = await faceapi\n .detectSingleFace(\n canvas,\n new faceapi.TinyFaceDetectorOptions({\n inputSize: 224,\n })\n )\n .withFaceLandmarks(true)\n .withAgeAndGender();\n\n if (!detection) return null;\n\n return {\n age: detection.age,\n gender: detection.gender,\n confidence: detection.detection.score,\n };\n}\n\nexport async function estimateAgeBurst(frames) {\n const results = [];\n for (const frame of frames) {\n const result = await estimateAge(frame);\n if (result) results.push(result);\n }\n return results;\n}\n\nexport function isInitialized() {\n return initialized;\n}\n","import {\n TASK_TIMEOUT_MS,\n MIN_TASK_TIME_MS,\n TASK_COUNT,\n REQUIRED_TASK_PASSES,\n} from './constants.js';\n\nconst TASKS = [\n {\n id: 'turn-left',\n instruction: 'Turn your head to the left',\n check: (h) => detectYawShift(h, 20),\n },\n {\n id: 'turn-right',\n instruction: 'Turn your head to the right',\n check: (h) => detectYawShift(h, -20),\n },\n {\n id: 'nod',\n instruction: 'Nod your head down then up',\n check: (h) => detectNod(h),\n },\n {\n id: 'blink-twice',\n instruction: 'Blink twice',\n check: (h) => detectDoubleBlink(h),\n },\n {\n id: 'move-closer',\n instruction: 'Move closer then back',\n check: (h) => detectDistanceChange(h),\n },\n];\n\nexport function pickTasks(count = TASK_COUNT) {\n const shuffled = [...TASKS].sort(() => Math.random() - 0.5);\n return shuffled.slice(0, count);\n}\n\nexport function createSession(tasks) {\n return {\n tasks: tasks || pickTasks(),\n currentIndex: 0,\n history: [],\n taskStartTime: 0,\n completedTasks: 0,\n requiredPasses: REQUIRED_TASK_PASSES,\n failed: false,\n failReason: null,\n };\n}\n\nexport function processFrame(session, trackingResult) {\n if (session.failed || isComplete(session)) return;\n if (session.currentIndex >= session.tasks.length) return;\n if (!trackingResult || trackingResult.faceCount === 0) return;\n\n if (trackingResult.faceCount > 1) {\n session.failed = true;\n session.failReason = null;\n return;\n }\n\n const entry = {\n timestamp: trackingResult.timestampMs,\n headPose: trackingResult.headPose,\n blendshapes: trackingResult.blendshapes,\n boundingBox: trackingResult.boundingBox,\n };\n\n if (session.history.length === 0) {\n session.taskStartTime = trackingResult.timestampMs;\n }\n\n session.history.push(entry);\n\n const elapsed = trackingResult.timestampMs - session.taskStartTime;\n\n if (elapsed > TASK_TIMEOUT_MS) {\n advanceTask(session);\n return;\n }\n\n if (elapsed < MIN_TASK_TIME_MS) return;\n\n const task = session.tasks[session.currentIndex];\n if (!task.check(session.history)) return;\n\n if (isSuspicious(session.history)) {\n session.failed = true;\n session.failReason = null;\n return;\n }\n\n session.completedTasks++;\n advanceTask(session);\n}\n\nexport function isComplete(session) {\n return session.currentIndex >= session.tasks.length;\n}\n\nexport function isPassed(session) {\n return session.completedTasks >= session.requiredPasses;\n}\n\nexport function currentInstruction(session) {\n if (session.currentIndex >= session.tasks.length) {\n return null;\n }\n return session.tasks[session.currentIndex].instruction;\n}\n\nexport function currentTaskId(session) {\n if (session.currentIndex >= session.tasks.length) {\n return null;\n }\n return session.tasks[session.currentIndex].id;\n}\n\nexport function progress(session) {\n if (session.tasks.length === 0) return 1;\n return Math.min(session.currentIndex / session.tasks.length, 1);\n}\n\nfunction advanceTask(session) {\n session.currentIndex++;\n session.history = [];\n session.taskStartTime = 0;\n\n const remaining = session.tasks.length - session.currentIndex;\n const canStillPass = session.completedTasks + remaining >= session.requiredPasses;\n\n if (!canStillPass) {\n session.failed = true;\n session.failReason = null;\n }\n}\n\nfunction detectYawShift(history, targetDelta) {\n if (history.length < 5) return false;\n const baseYaw = history[0].headPose.yaw;\n const direction = Math.sign(targetDelta);\n const threshold = Math.abs(targetDelta);\n\n return history.some((entry) => {\n const delta = (entry.headPose.yaw - baseYaw) * direction;\n return delta > threshold;\n });\n}\n\nfunction detectNod(history) {\n if (history.length < 10) return false;\n const basePitch = history[0].headPose.pitch;\n let wentDown = false;\n let cameBack = false;\n\n for (const entry of history) {\n const delta = entry.headPose.pitch - basePitch;\n if (delta > 15) wentDown = true;\n if (wentDown && Math.abs(delta) < 8) cameBack = true;\n }\n\n return wentDown && cameBack;\n}\n\nfunction detectDoubleBlink(history) {\n if (history.length < 10) return false;\n let blinkCount = 0;\n let eyesClosed = false;\n\n for (const entry of history) {\n const left = entry.blendshapes.eyeBlinkLeft ?? 0;\n const right = entry.blendshapes.eyeBlinkRight ?? 0;\n const bothClosed = left > 0.6 && right > 0.6;\n\n if (bothClosed && !eyesClosed) {\n blinkCount++;\n eyesClosed = true;\n } else if (!bothClosed) {\n eyesClosed = false;\n }\n }\n\n return blinkCount >= 2;\n}\n\nfunction detectDistanceChange(history) {\n if (history.length < 10) return false;\n const baseArea = history[0].boundingBox.area;\n let wentCloser = false;\n let cameBack = false;\n\n for (const entry of history) {\n const ratio = entry.boundingBox.area / baseArea;\n if (ratio > 1.3) wentCloser = true;\n if (wentCloser && ratio < 1.15) cameBack = true;\n }\n\n return wentCloser && cameBack;\n}\n\nexport function isSuspicious(history) {\n if (history.length < 5) return false;\n\n const deltas = [];\n for (let i = 1; i < history.length; i++) {\n const dy = Math.abs(history[i].headPose.yaw - history[i - 1].headPose.yaw);\n const dp = Math.abs(history[i].headPose.pitch - history[i - 1].headPose.pitch);\n deltas.push(dy + dp);\n }\n\n if (deltas.every((d) => d < 0.1)) return true;\n\n const mean = deltas.reduce((a, b) => a + b, 0) / deltas.length;\n const variance = deltas.reduce((s, d) => s + (d - mean) ** 2, 0) / deltas.length;\n\n return variance < 0.01 && mean > 0.5;\n}\n","import { TOKEN_EXPIRY_S } from './constants.js';\n\nfunction base64UrlEncode(data) {\n const text = typeof data === 'string' ? data : String.fromCharCode(...new Uint8Array(data));\n return btoa(text).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction base64UrlDecode(str) {\n const padded = str + '='.repeat((4 - (str.length % 4)) % 4);\n const binary = atob(padded.replace(/-/g, '+').replace(/_/g, '/'));\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n\nasync function getSigningKey() {\n const raw = crypto.getRandomValues(new Uint8Array(32));\n return crypto.subtle.importKey('raw', raw, { name: 'HMAC', hash: 'SHA-256' }, false, [\n 'sign',\n 'verify',\n ]);\n}\n\nlet cachedKey = null;\n\nasync function ensureKey() {\n if (!cachedKey) cachedKey = await getSigningKey();\n return cachedKey;\n}\n\nexport async function createToken(payload) {\n const key = await ensureKey();\n\n const header = base64UrlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));\n\n const body = base64UrlEncode(\n JSON.stringify({\n ...payload,\n iat: Math.floor(Date.now() / 1000),\n exp: Math.floor(Date.now() / 1000) + TOKEN_EXPIRY_S,\n })\n );\n\n const data = new TextEncoder().encode(`${header}.${body}`);\n const signature = await crypto.subtle.sign('HMAC', key, data);\n\n return `${header}.${body}.${base64UrlEncode(signature)}`;\n}\n\nexport async function verifyToken(token) {\n const key = await ensureKey();\n const [header, body, sig] = token.split('.');\n\n if (!header || !body || !sig) return null;\n\n let signature;\n let data;\n try {\n data = new TextEncoder().encode(`${header}.${body}`);\n signature = base64UrlDecode(sig);\n } catch {\n return null;\n }\n\n const valid = await crypto.subtle.verify('HMAC', key, signature, data);\n\n if (!valid) return null;\n\n const decoded = JSON.parse(new TextDecoder().decode(base64UrlDecode(body)));\n\n if (decoded.exp && decoded.exp < Date.now() / 1000) {\n return null;\n }\n\n return decoded;\n}\n\nexport function decodeToken(token) {\n const [, body] = token.split('.');\n if (!body) return null;\n return JSON.parse(new TextDecoder().decode(base64UrlDecode(body)));\n}\n\nexport function createTransport(mode, options = {}) {\n if (mode === 'serverless') {\n return createServerlessTransport(options);\n }\n\n const baseUrl = mode === 'custom' ? options.server : 'https://api.openage.dev';\n\n return createServerTransport(baseUrl, options);\n}\n\nfunction createServerlessTransport(options) {\n return {\n async verify(payload) {\n const { estimatedAge, livenessOk } = payload;\n\n if (!livenessOk) {\n return { success: false, token: null };\n }\n\n const token = await createToken({\n estimatedAge,\n livenessOk: true,\n mode: 'serverless',\n });\n\n return { success: true, token };\n },\n close() {},\n };\n}\n\nfunction createServerTransport(baseUrl, options) {\n let session = null;\n let channel = null;\n\n return {\n async createSession() {\n const transports = [];\n if (typeof WebSocket !== 'undefined') {\n transports.push('websocket');\n }\n transports.push('poll');\n\n const response = await fetch(`${baseUrl}/api/session`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n sitekey: options.sitekey,\n action: options.action,\n supportedTransports: transports,\n }),\n });\n\n if (!response.ok) {\n throw new Error('Request failed');\n }\n\n session = await response.json();\n return session;\n },\n\n openChannel() {\n if (!session) {\n throw new Error('No session');\n }\n\n if (session.transport === 'websocket') {\n channel = createWsChannel(baseUrl, session.sessionId);\n } else {\n channel = createPollChannel(baseUrl, session.sessionId);\n }\n },\n\n async receive() {\n if (!channel) return null;\n return channel.receive();\n },\n\n async send(data) {\n if (!channel) return;\n return channel.send(data);\n },\n\n async sendAndReceive(data) {\n if (!channel) return null;\n return channel.sendAndReceive(data);\n },\n\n async verify(payload) {\n if (channel) {\n return this.verifyViaChannel(payload);\n }\n\n const response = await fetch(`${baseUrl}/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n response: payload.token,\n sitekey: options.sitekey,\n action: options.action,\n }),\n });\n\n if (!response.ok) {\n return {\n success: false,\n token: null,\n };\n }\n\n return response.json();\n },\n\n async verifyViaChannel(payload) {\n await channel.send(payload);\n return channel.receive();\n },\n\n getSession() {\n return session;\n },\n\n close() {\n channel?.close();\n channel = null;\n session = null;\n },\n };\n}\n\nfunction createWsChannel(baseUrl, sessionId) {\n const wsUrl = baseUrl.replace(/^http/, 'ws').replace(/\\/$/, '');\n const url = `${wsUrl}/api/ws/${sessionId}`;\n const ws = new WebSocket(url);\n let pending = [];\n let ready = false;\n let closed = false;\n\n const waitReady = new Promise((resolve, reject) => {\n ws.onopen = () => {\n ready = true;\n resolve();\n };\n ws.onerror = () => {\n reject(new Error('Connection failed'));\n };\n });\n\n ws.onmessage = (event) => {\n const message = JSON.parse(event.data);\n const resolver = pending.shift();\n if (resolver) resolver(message);\n };\n\n ws.onclose = () => {\n closed = true;\n for (const resolver of pending) resolver(null);\n pending = [];\n };\n\n return {\n receive() {\n if (closed) return Promise.resolve(null);\n return new Promise((resolve) => {\n pending.push(resolve);\n });\n },\n async send(data) {\n await waitReady;\n ws.send(JSON.stringify(data));\n },\n async sendAndReceive(data) {\n await waitReady;\n ws.send(JSON.stringify(data));\n return this.receive();\n },\n close() {\n closed = true;\n ws.close();\n },\n };\n}\n\nfunction createPollChannel(baseUrl, sessionId) {\n return {\n async receive() {\n const response = await fetch(`${baseUrl}/api/poll/${sessionId}`);\n if (!response.ok) {\n throw new Error('Request failed');\n }\n return response.json();\n },\n async send(data) {\n const response = await fetch(`${baseUrl}/api/verify/${sessionId}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n if (!response.ok) {\n throw new Error('Request failed');\n }\n },\n async sendAndReceive(data) {\n const response = await fetch(`${baseUrl}/api/verify/${sessionId}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n if (!response.ok) {\n throw new Error('Request failed');\n }\n return response.json();\n },\n close() {},\n };\n}\n","let wasmModule = null;\nlet vmSession = null;\nlet challengeBundle = null;\nlet _faceData = null;\nlet _challengeParams = null;\nlet _bridge = null;\n\nfunction loadScript(url) {\n return new Promise((resolve, reject) => {\n const existing = document.querySelector(`script[src=\"${url}\"]`);\n if (existing) return resolve();\n\n const script = document.createElement('script');\n script.src = url;\n script.onload = resolve;\n script.onerror = () => {\n reject(new Error(`Failed to load ${url}`));\n };\n document.head.appendChild(script);\n });\n}\n\nexport async function initVM(session) {\n vmSession = session;\n\n await loadScript(session.wasmJs);\n\n const loaderModule = await import(session.loaderJs);\n wasmModule = await loaderModule.initModule(session.wasmBin);\n\n const initFn = session.exports.vm_init;\n const result = wasmModule[`_${initFn}`]();\n if (result !== 0) throw new Error('VM init failed');\n\n const bundleResponse = await fetch(session.challengeVmbc);\n challengeBundle = new Uint8Array(await bundleResponse.arrayBuffer());\n}\n\nexport async function decryptModel(session, modelId) {\n if (!wasmModule || !vmSession) {\n throw new Error('VM not loaded');\n }\n\n const modelInfo = session.models[modelId];\n if (!modelInfo) {\n throw new Error(`Unknown model: ${modelId}`);\n }\n\n const response = await fetch(modelInfo.url);\n if (!response.ok) {\n throw new Error(`Failed to fetch model: ${modelId}`);\n }\n\n const encrypted = new Uint8Array(await response.arrayBuffer());\n\n const decryptFn = session.exports.vm_decrypt_blob;\n const freeFn = session.exports.vm_free;\n const length = encrypted.length;\n\n const inputPtr = wasmModule._malloc(length);\n wasmModule.HEAPU8.set(encrypted, inputPtr);\n\n const outLenPtr = wasmModule._malloc(4);\n const outPtr = wasmModule[`_${decryptFn}`](inputPtr, length, outLenPtr);\n wasmModule._free(inputPtr);\n\n if (!outPtr) {\n wasmModule._free(outLenPtr);\n throw new Error(`Decryption failed: ${modelId}`);\n }\n\n const outLen = readU32(wasmModule, outLenPtr);\n wasmModule._free(outLenPtr);\n\n const result = new Uint8Array(outLen);\n result.set(wasmModule.HEAPU8.subarray(outPtr, outPtr + outLen));\n wasmModule[`_${freeFn}`](outPtr);\n return result.buffer;\n}\n\nfunction readU32(mod, ptr) {\n return (\n mod.HEAPU8[ptr] |\n (mod.HEAPU8[ptr + 1] << 8) |\n (mod.HEAPU8[ptr + 2] << 16) |\n (mod.HEAPU8[ptr + 3] << 24)\n );\n}\n\nfunction defineVmGlobal(name, getter) {\n try {\n delete window[name];\n } catch (_) {}\n Object.defineProperty(window, name, {\n get: getter,\n set() {},\n configurable: true,\n });\n}\n\nexport function setFaceData(faceData) {\n _faceData = faceData;\n defineVmGlobal('__vmFaceData', () => _faceData);\n}\n\nexport function setChallengeParams(params) {\n _challengeParams = params;\n defineVmGlobal('__vmChallenge', () => _challengeParams);\n}\n\nexport function registerBridge(bridge) {\n _bridge = Object.freeze({ ...bridge });\n defineVmGlobal('__vmBridge', () => _bridge);\n}\n\nexport function unregisterBridge() {\n _bridge = null;\n try {\n delete window.__vmBridge;\n } catch (_) {}\n}\n\nexport function executeChallenge() {\n if (!wasmModule || !challengeBundle) {\n throw new Error('VM not loaded');\n }\n\n const execFn = vmSession.exports.vm_exec_bytecode;\n const freeFn = vmSession.exports.vm_free;\n const length = challengeBundle.length;\n\n const inputPtr = wasmModule._malloc(length);\n wasmModule.HEAPU8.set(challengeBundle, inputPtr);\n\n const outLenPtr = wasmModule._malloc(4);\n const outPtr = wasmModule[`_${execFn}`](inputPtr, length, outLenPtr);\n wasmModule._free(inputPtr);\n\n if (!outPtr) {\n wasmModule._free(outLenPtr);\n const errFn = vmSession.exports.vm_last_error;\n let message = 'VM execution failed';\n if (errFn) {\n const errPtr = wasmModule[`_${errFn}`]();\n if (errPtr) {\n const detail = wasmModule.UTF8ToString(errPtr);\n if (detail) message = detail;\n }\n }\n throw new Error(message);\n }\n\n const outLen = readU32(wasmModule, outLenPtr);\n wasmModule._free(outLenPtr);\n\n const result = new Uint8Array(outLen);\n result.set(wasmModule.HEAPU8.subarray(outPtr, outPtr + outLen));\n wasmModule[`_${freeFn}`](outPtr);\n return result;\n}\n\nexport function toBase64(bytes) {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nexport function destroyVM() {\n if (!wasmModule || !vmSession) return;\n\n const destroyFn = vmSession.exports.vm_destroy;\n if (destroyFn) {\n wasmModule[`_${destroyFn}`]();\n }\n\n wasmModule = null;\n vmSession = null;\n challengeBundle = null;\n _faceData = null;\n _challengeParams = null;\n _bridge = null;\n\n for (const name of ['__vmFaceData', '__vmChallenge', '__vmBridge']) {\n try {\n delete window[name];\n } catch (_) {}\n }\n}\n\nexport function isVMLoaded() {\n return wasmModule !== null && vmSession !== null;\n}\n\nconst decryptedCache = new Map();\n\nasync function decryptAndCache(session, modelId) {\n if (decryptedCache.has(modelId)) {\n return decryptedCache.get(modelId);\n }\n\n const buffer = await decryptModel(session, modelId);\n decryptedCache.set(modelId, buffer);\n return buffer;\n}\n\nexport async function ensureModels(session, onProgress) {\n await decryptAndCache(session, 'mediapipe');\n onProgress?.(1);\n}\n\nexport async function getMediaPipeModelBuffer(session) {\n return decryptAndCache(session, 'mediapipe');\n}\n\nexport function clearModelCache() {\n decryptedCache.clear();\n}\n","import { loadVision, loadModel, initTracker, track, destroyTracker } from './face-tracker.js';\nimport { startPositioning } from './positioning.js';\nimport { initAgeEstimator, estimateAgeBurst } from './age-estimator.js';\nimport {\n createSession as createLivenessSession,\n processFrame,\n isComplete,\n isPassed,\n currentInstruction,\n currentTaskId,\n progress,\n} from './liveness.js';\nimport { createTransport } from './transport.js';\nimport {\n initVM,\n setFaceData,\n setChallengeParams,\n executeChallenge as execVM,\n registerBridge,\n unregisterBridge,\n destroyVM,\n toBase64,\n ensureModels,\n getMediaPipeModelBuffer,\n clearModelCache,\n} from './vm-client.js';\nimport {\n BURST_FRAMES,\n BURST_INTERVAL_MS,\n MAX_RETRIES,\n MOTION_CAPTURE_MS,\n MOTION_SAMPLE_MS,\n} from './constants.js';\n\nlet stream = null;\nlet videoElement = null;\n\nconst CAMERA_CONSTRAINTS = {\n video: {\n facingMode: 'user',\n width: { ideal: 640 },\n height: { ideal: 480 },\n },\n};\n\nexport function startCamera(video) {\n return navigator.mediaDevices.getUserMedia(CAMERA_CONSTRAINTS).then((s) => {\n stream = s;\n video.srcObject = stream;\n videoElement = video;\n\n return new Promise((resolve) => {\n video.onloadedmetadata = () => {\n video.play();\n resolve({\n width: video.videoWidth,\n height: video.videoHeight,\n });\n };\n });\n });\n}\n\nexport function captureFrame() {\n if (!videoElement) return null;\n\n const canvas = document.createElement('canvas');\n canvas.width = videoElement.videoWidth;\n canvas.height = videoElement.videoHeight;\n\n const context = canvas.getContext('2d');\n context.drawImage(videoElement, 0, 0);\n return canvas;\n}\n\nexport function stopCamera() {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n stream = null;\n }\n if (videoElement) {\n videoElement.srcObject = null;\n videoElement = null;\n }\n}\n\nexport function isCameraActive() {\n return stream !== null && videoElement !== null;\n}\n\nfunction computeAge(ageResults) {\n if (!ageResults || ageResults.length === 0) return null;\n\n const ages = ageResults.map((r) => r.age).sort((a, b) => a - b);\n\n const trimmed = ages.length >= 3 ? ages.slice(1, -1) : ages;\n\n return trimmed.reduce((s, a) => s + a, 0) / trimmed.length;\n}\n\nconst TASK_LABELS = {\n 'turn-left': 'Turn your head left',\n 'turn-right': 'Turn your head right',\n nod: 'Nod your head',\n 'blink-twice': 'Blink twice',\n 'move-closer': 'Move closer then back',\n};\n\nfunction sleep(ms) {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nexport async function runChallenge(widget, emitter) {\n const mode = widget.params.mode || 'serverless';\n\n if (mode !== 'serverless' && !widget.params.sitekey) {\n const err = new Error('Configuration error');\n widget.showResult?.('fail', 'Verification failed');\n emitter.emit('error', err, widget.id);\n widget.params.errorCallback?.(err);\n return;\n }\n\n if (mode === 'serverless') {\n return runServerless(widget, emitter);\n }\n return runServer(widget, emitter);\n}\n\nasync function runServerless(widget, emitter) {\n const params = widget.params;\n let retryCount = 0;\n let modelBuffer = null;\n\n try {\n widget.openPopup();\n widget.setHeroStatus('Loading…');\n\n await Promise.all([loadVision(), initAgeEstimator()]);\n\n modelBuffer = await loadModel();\n widget.showReady();\n\n await waitForStart(widget);\n await startCameraFlow(widget, modelBuffer);\n\n const transport = createTransport('serverless', params);\n\n const attempt = async () => {\n widget.showLiveness();\n widget.setInstruction('');\n widget.setVideoStatus('Verifying…');\n\n const session = createLivenessSession();\n await runLivenessLoop(widget.popupElements.video, session, widget);\n\n if (session.failed || !isPassed(session)) {\n return { outcome: 'retry' };\n }\n\n widget.setInstruction('Hold still…');\n widget.setVideoStatus('Processing…');\n const frames = await captureFrameBurst(BURST_FRAMES, BURST_INTERVAL_MS);\n\n const ageResults = await estimateAgeBurst(frames);\n const estimatedAge = computeAge(ageResults);\n\n const result = await transport.verify({\n estimatedAge,\n livenessOk: true,\n });\n\n return {\n outcome: result.token ? 'pass' : 'fail',\n token: result.token,\n };\n };\n\n let result = await attempt();\n\n while (result.outcome === 'retry' && retryCount < MAX_RETRIES) {\n retryCount++;\n widget.showResult('retry', 'Please try again');\n await waitForStart(widget);\n await startCameraFlow(widget, modelBuffer);\n result = await attempt();\n }\n\n cleanupLocal();\n emitResult(widget, emitter, result);\n } catch (error) {\n cleanupLocal();\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', error, widget.id);\n params.errorCallback?.(error);\n }\n}\n\nasync function runServer(widget, emitter) {\n const params = widget.params;\n\n try {\n widget.openPopup();\n widget.setHeroStatus('Connecting…');\n\n const transport = createTransport(params.mode, params);\n const session = await transport.createSession();\n\n widget.setHeroStatus('Loading…');\n await initVM(session);\n\n widget.setHeroStatus('Preparing…');\n await ensureModels(session, () => {});\n\n await loadVision();\n const buf = await getMediaPipeModelBuffer(session);\n await initTracker(buf);\n\n registerBridge({\n trackFace: () => {\n const video = widget.popupElements?.video;\n if (!video) return 'null';\n const r = track(video, performance.now());\n if (!r) return 'null';\n return JSON.stringify({\n ts: r.timestampMs ?? performance.now(),\n faceCount: r.faceCount,\n headPose: r.headPose || null,\n blendshapes: r.blendshapes || null,\n boundingBox: r.boundingBox || null,\n });\n },\n captureFrame: () => (captureFrame() ? 'true' : 'null'),\n });\n\n widget.showReady();\n await waitForStart(widget);\n\n const video = widget.showCamera();\n widget.setVideoStatus('Requesting camera…');\n await startCamera(video);\n exposeMirrorVideo(video);\n\n widget.setVideoStatus('Position your face');\n await waitForPositioning(video, widget);\n\n widget.showLiveness();\n transport.openChannel();\n\n let challenge = await transport.receive();\n const rounds = session.rounds;\n\n for (let i = 0; i < rounds; i++) {\n if (!challenge) {\n cleanupVM(transport);\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', 'failed', widget.id);\n return;\n }\n\n if (challenge.type === 'verdict') {\n cleanupVM(transport);\n emitVerdict(widget, emitter, challenge);\n return;\n }\n\n if (challenge.type === 'timeout') {\n cleanupVM(transport);\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', 'failed', widget.id);\n return;\n }\n\n widget.setVideoStatus(`Step ${i + 1} of ${rounds}`);\n\n const task = challenge.token?.task;\n widget.setInstruction(TASK_LABELS[task] ?? 'Look at the camera');\n widget.setTask(task);\n widget.setProgress(i / rounds);\n\n const faceData = await captureMotion(widget);\n setFaceData(faceData);\n setChallengeParams(challenge.token);\n\n let vmOut;\n try {\n vmOut = execVM();\n } catch {\n cleanupVM(transport);\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', 'failed', widget.id);\n return;\n }\n\n const payload = {\n token: challenge.token,\n tokenSignature: challenge.tokenSignature,\n response: toBase64(vmOut),\n };\n\n const result = await transport.sendAndReceive(payload);\n\n if (!result) {\n cleanupVM(transport);\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', 'failed', widget.id);\n return;\n }\n\n if (result.complete) {\n cleanupVM(transport);\n emitVerdict(widget, emitter, result);\n return;\n }\n\n if (result.hint) {\n widget.setVideoStatus(result.hint);\n await sleep(1000);\n }\n\n challenge = result.nextChallenge || null;\n }\n\n cleanupVM(transport);\n } catch (error) {\n cleanupVM();\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', error, widget.id);\n params.errorCallback?.(error);\n }\n}\n\nfunction emitVerdict(widget, emitter, response) {\n const verdict = response?.verdict || response;\n const token = verdict?.token || null;\n const params = widget.params;\n\n if (token) {\n widget.token = token;\n widget.showResult('pass', 'Verified');\n emitter.emit('verified', token, widget.id);\n params.callback?.(token);\n return;\n }\n\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', 'failed', widget.id);\n params.errorCallback?.('failed');\n}\n\nasync function captureMotion(widget) {\n const video = widget.popupElements?.video;\n const history = [];\n const start = performance.now();\n\n while (performance.now() - start < MOTION_CAPTURE_MS) {\n const r = track(video, performance.now());\n if (r && r.faceCount === 1) {\n history.push({\n ts: r.timestampMs,\n headPose: r.headPose,\n blendshapes: r.blendshapes,\n boundingBox: r.boundingBox,\n });\n }\n await sleep(MOTION_SAMPLE_MS);\n }\n\n return {\n faceCount: history.length > 0 ? 1 : 0,\n motionHistory: history,\n };\n}\n\nfunction emitResult(widget, emitter, result) {\n const params = widget.params;\n\n if (result.outcome === 'pass') {\n widget.token = result.token || null;\n widget.showResult('pass', 'Verified');\n emitter.emit('verified', result.token, widget.id);\n params.callback?.(result.token);\n } else {\n widget.showResult('fail', 'Verification failed');\n emitter.emit('error', 'failed', widget.id);\n params.errorCallback?.('failed');\n }\n}\n\nfunction waitForStart(widget) {\n return new Promise((resolve) => {\n widget.onStartClick = () => {\n widget.onStartClick = null;\n resolve();\n };\n });\n}\n\nasync function startCameraFlow(widget, modelBuffer) {\n const video = widget.showCamera();\n widget.setVideoStatus('Requesting camera…');\n await startCamera(video);\n\n widget.setVideoStatus('Preparing…');\n await initTracker(modelBuffer);\n\n widget.setVideoStatus('Position your face');\n await waitForPositioning(video, widget);\n}\n\nfunction waitForPositioning(video, widget) {\n return new Promise((resolve, reject) => {\n const handle = startPositioning(video, {\n onStatus: (text) => widget.setVideoStatus(text),\n onReady: () => resolve(),\n });\n\n setTimeout(() => {\n handle.cancel();\n reject(new Error('Positioning timeout'));\n }, 30000);\n });\n}\n\nasync function runLivenessLoop(video, session, widget) {\n return new Promise((resolve) => {\n const loop = () => {\n const tracking = track(video, performance.now());\n if (tracking) processFrame(session, tracking);\n\n widget.setInstruction(currentInstruction(session) || 'Done');\n widget.setTask(currentTaskId(session));\n widget.setProgress(progress(session));\n widget.setVideoStatus(\n `Check ` +\n `${Math.min(session.currentIndex + 1, session.tasks.length)}` +\n ` of ${session.tasks.length}`\n );\n\n if (session.failed || isComplete(session)) {\n resolve();\n return;\n }\n\n requestAnimationFrame(loop);\n };\n\n requestAnimationFrame(loop);\n });\n}\n\nasync function captureFrameBurst(count, interval) {\n const frames = [];\n for (let i = 0; i < count; i++) {\n const frame = captureFrame();\n if (frame) frames.push(frame);\n if (i < count - 1) await sleep(interval);\n }\n return frames;\n}\n\nfunction cleanupLocal() {\n stopCamera();\n destroyTracker();\n}\n\nfunction cleanupVM(transport) {\n stopCamera();\n removeMirrorVideo();\n destroyTracker();\n unregisterBridge();\n destroyVM();\n clearModelCache();\n transport?.close();\n}\n\nfunction exposeMirrorVideo(source) {\n removeMirrorVideo();\n if (!source?.srcObject) return;\n const mirror = document.createElement('video');\n mirror.id = '__openage_mirror';\n mirror.srcObject = source.srcObject;\n mirror.autoplay = true;\n mirror.muted = true;\n mirror.playsInline = true;\n mirror.style.cssText =\n 'position:fixed;width:1px;height:1px;' + 'opacity:0;pointer-events:none;z-index:-1;';\n document.body.appendChild(mirror);\n}\n\nfunction removeMirrorVideo() {\n document.getElementById('__openage_mirror')?.remove();\n}\n","import { track } from './face-tracker.js';\nimport { STABLE_FRAMES_REQUIRED, POSITION_CHECK_MS } from './constants.js';\n\nexport function startPositioning(video, callbacks) {\n let stableFrames = 0;\n let cancelled = false;\n\n const check = () => {\n if (cancelled) return;\n\n const result = track(video, performance.now());\n\n if (!result || result.faceCount === 0) {\n callbacks.onStatus?.('Look at the camera');\n stableFrames = 0;\n } else if (result.faceCount > 1) {\n callbacks.onStatus?.('Only one person please');\n stableFrames = 0;\n } else {\n callbacks.onStatus?.('Hold still…');\n stableFrames++;\n }\n\n if (stableFrames >= STABLE_FRAMES_REQUIRED) {\n callbacks.onReady?.();\n return;\n }\n\n setTimeout(check, POSITION_CHECK_MS);\n };\n\n check();\n\n return {\n cancel: () => {\n cancelled = true;\n },\n };\n}\n","import { Widget, createModalWidget } from './widget.js';\nimport { runChallenge } from './challenge.js';\nimport { verifyToken, decodeToken } from './transport.js';\nimport { VERSION } from './constants.js';\n\nexport class EventEmitter {\n constructor() {\n this.listeners = new Map();\n }\n\n on(event, handler) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event).add(handler);\n return this;\n }\n\n off(event, handler) {\n const handlers = this.listeners.get(event);\n if (handlers) handlers.delete(handler);\n return this;\n }\n\n once(event, handler) {\n const wrapper = (...args) => {\n this.off(event, wrapper);\n handler(...args);\n };\n wrapper._original = handler;\n return this.on(event, wrapper);\n }\n\n emit(event, ...args) {\n const handlers = this.listeners.get(event);\n if (!handlers) return;\n for (const handler of [...handlers]) {\n handler(...args);\n }\n }\n\n removeAllListeners(event) {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n return this;\n }\n}\n\nconst emitter = new EventEmitter();\nconst widgets = new Map();\n\nfunction normalizeParams(params) {\n const globalConfig = typeof window !== 'undefined' ? window.openage || {} : {};\n\n return {\n mode: 'serverless',\n theme: 'auto',\n size: 'normal',\n minAge: 18,\n ...globalConfig,\n ...params,\n };\n}\n\nfunction startWidget(widget) {\n widget.onChallenge = () => {\n emitter.emit('opened', widget.id);\n runChallenge(widget, emitter);\n };\n}\n\nfunction render(container, params = {}) {\n const normalized = normalizeParams(params);\n const widget = new Widget(container, normalized);\n widgets.set(widget.id, widget);\n startWidget(widget);\n return widget.id;\n}\n\nfunction open(params = {}) {\n const normalized = normalizeParams(params);\n const widget = createModalWidget(normalized);\n widget.anchorElement = normalized.anchorElement || null;\n widgets.set(widget.id, widget);\n\n widget.onChallenge = () => {\n emitter.emit('opened', widget.id);\n runChallenge(widget, emitter);\n };\n\n widget.startChallenge();\n return widget.id;\n}\n\nfunction bind(element, params = {}) {\n const normalized = normalizeParams(params);\n const target = typeof element === 'string' ? document.querySelector(element) : element;\n\n if (!target) {\n throw new Error('OpenAge: element not found');\n }\n\n let isReplayingClick = false;\n let activeWidgetId = null;\n\n const replayTargetClick = () => {\n isReplayingClick = true;\n try {\n target.click();\n } finally {\n isReplayingClick = false;\n }\n };\n\n const clearActiveWidget = () => {\n activeWidgetId = null;\n };\n\n const handler = (event) => {\n if (isReplayingClick || activeWidgetId) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation?.();\n\n const widgetId = open({\n ...normalized,\n anchorElement: target,\n callback: (token) => {\n normalized.callback?.(token);\n clearActiveWidget();\n replayTargetClick();\n },\n errorCallback: (error) => {\n clearActiveWidget();\n normalized.errorCallback?.(error);\n },\n closeCallback: () => {\n clearActiveWidget();\n normalized.closeCallback?.();\n },\n });\n\n activeWidgetId = widgetId;\n\n return widgetId;\n };\n\n target.addEventListener('click', handler, true);\n\n return () => {\n target.removeEventListener('click', handler, true);\n };\n}\n\nfunction reset(widgetId) {\n widgets.get(widgetId)?.reset();\n}\n\nfunction remove(widgetId) {\n const widget = widgets.get(widgetId);\n if (!widget) return;\n widget.destroy();\n widgets.delete(widgetId);\n}\n\nfunction getToken(widgetId) {\n return widgets.get(widgetId)?.getToken() || null;\n}\n\nfunction execute(widgetId) {\n const widget = widgets.get(widgetId);\n if (!widget) return;\n widget.startChallenge();\n}\n\nfunction challenge(params = {}) {\n return new Promise((resolve, reject) => {\n open({\n ...params,\n callback: (token) => resolve(token),\n errorCallback: (error) => reject(typeof error === 'string' ? new Error(error) : error),\n closeCallback: () => reject(new Error('User dismissed')),\n });\n });\n}\n\nfunction on(event, handler) {\n emitter.on(event, handler);\n}\n\nfunction off(event, handler) {\n emitter.off(event, handler);\n}\n\nfunction once(event, handler) {\n emitter.once(event, handler);\n}\n\nfunction autoRender() {\n if (typeof document === 'undefined') return;\n\n const globalConfig = typeof window !== 'undefined' ? window.openage || {} : {};\n\n if (globalConfig.render === 'explicit') return;\n\n const elements = document.querySelectorAll('.openage');\n\n for (const element of elements) {\n const params = {\n sitekey: element.dataset.sitekey,\n theme: element.dataset.theme,\n size: element.dataset.size,\n action: element.dataset.action,\n mode: element.dataset.mode,\n server: element.dataset.server,\n };\n\n if (element.dataset.callback) {\n params.callback = (token) => {\n const fn = window[element.dataset.callback];\n if (typeof fn === 'function') fn(token);\n };\n }\n\n if (element.dataset.errorCallback) {\n params.errorCallback = (error) => {\n const fn = window[element.dataset.errorCallback];\n if (typeof fn === 'function') fn(error);\n };\n }\n\n if (element.dataset.expiredCallback) {\n params.expiredCallback = () => {\n const fn = window[element.dataset.expiredCallback];\n if (typeof fn === 'function') fn();\n };\n }\n\n if (element.dataset.bind) {\n const target = document.getElementById(element.dataset.bind);\n if (target) {\n bind(target, params);\n continue;\n }\n }\n\n render(element, params);\n }\n\n const onloadName = document.currentScript?.dataset?.onload;\n if (onloadName && typeof window[onloadName] === 'function') {\n window[onloadName]();\n }\n}\n\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', autoRender);\n } else {\n autoRender();\n }\n}\n\nconst OpenAge = {\n render,\n open,\n bind,\n reset,\n remove,\n getToken,\n execute,\n challenge,\n on,\n off,\n once,\n verify: verifyToken,\n decode: decodeToken,\n version: VERSION,\n};\n\nexport default OpenAge;\nexport {\n render,\n open,\n bind,\n reset,\n remove,\n getToken,\n execute,\n challenge,\n on,\n off,\n once,\n verifyToken as verify,\n decodeToken as decode,\n VERSION as version,\n};\n"],"names":["FACE_SVG","resolveTheme","theme","resolveAutoTheme","watchTheme","host","window","update","setAttribute","cleanups","query","cleanup","watchMediaQuery","push","MutationObserver","observer","options","attributes","attributeFilter","document","documentElement","observe","body","disconnect","documentTheme","element","readThemeHint","resolveDocumentTheme","systemTheme","matchMedia","matches","resolveSystemTheme","getComputedStyle","explicit","attrTheme","getAttribute","className","test","readExplicitTheme","styles","scheme","value","normalized","toLowerCase","hasDark","includes","hasLight","parseColorScheme","colorScheme","match","parts","split","slice","map","part","Number","parseFloat","trim","length","some","isNaN","red","green","blue","brightness","parseBackgroundTheme","backgroundColor","listener","mediaQuery","addEventListener","removeEventListener","addListener","removeListener","STYLES","heroTemplate","statusText","replace","resultTemplate","outcome","message","fail","retry","VERSION","MEDIAPIPE_CDN","MEDIAPIPE_WASM","MEDIAPIPE_VISION","FACEAPI_MODEL_CDN","POPUP_MARGIN","widgetCounter","Widget","constructor","container","params","this","id","querySelector","resolveContainer","anchorElement","state","token","popup","shadow","elements","onChallenge","onStartClick","popupFrame","themeCleanup","render","createElement","attachShadow","mode","style","textContent","appendChild","size","display","wrapper","innerHTML","firstElementChild","checkbox","classList","add","event","target","closest","clearError","startChallenge","key","preventDefault","click","checkBox","errorSlot","setState","createPopupShell","popupHost","popupShadow","openPopup","getVideo","anchor","getPopupAnchor","openModal","buildPopupContent","visibility","pointerEvents","root","findPopupPosition","getBoundingClientRect","remove","bindPopupEvents","updatePopupPosition","startPopupTracking","overlay","modal","closePopup","schedule","schedulePopupPosition","addWindowListener","name","passive","capture","visualViewport","viewport","ResizeObserver","cancelAnimationFrame","requestAnimationFrame","isConnected","position","top","Math","round","left","dataset","placement","closeBtn","closeCallback","startBtn","popupElements","actions","heroStatus","showHero","hideActions","showReady","setHeroStatus","showActions","showCamera","video","faceGuide","challengeHud","challengeText","challengeFill","videoStatus","showLiveness","text","setVideoStatus","setInstruction","setStatus","setProgress","fraction","width","setTask","taskId","label","showResult","showError","newState","cb","box","getToken","reset","destroy","anchorRect","popupRect","innerWidth","height","innerHeight","popupWidth","max","popupHeight","viewportWidth","min","clampLeft","topBelow","bottom","topAbove","clampTop","viewportHeight","FaceLandmarker","landmarker","lastTimestampMs","visionModule","async","loadVision","import","initTracker","modelBuffer","vision","resolver","FilesetResolver","forVisionTasks","close","createFromOptions","baseOptions","modelAssetBuffer","Uint8Array","delegate","runningMode","numFaces","outputFaceBlendshapes","outputFacialTransformationMatrixes","track","timestampMs","safe","isFinite","performance","now","whole","floor","normalizeTimestamp","result","detectForVideo","faceCount","faceLandmarks","landmarks","blendshapes","parseBlendshapes","faceBlendshapes","headPose","extractHeadPose","facialTransformationMatrixes","boundingBox","computeBoundingBox","destroyTracker","blendshapeResult","categories","category","categoryName","score","matrix","data","yaw","pitch","roll","m","deg","PI","atan2","asin","minX","minY","maxX","maxY","point","x","y","area","initialized","faceapi","initAgeEstimator","url","Promise","resolve","reject","Error","existing","script","src","crossOrigin","onload","onerror","head","all","nets","tinyFaceDetector","loadFromUri","faceLandmark68TinyNet","ageGenderNet","estimateAge","canvas","detection","detectSingleFace","TinyFaceDetectorOptions","inputSize","withFaceLandmarks","withAgeAndGender","age","gender","confidence","TASKS","instruction","check","h","detectYawShift","history","basePitch","wentDown","cameBack","entry","delta","abs","detectNod","blinkCount","eyesClosed","eyeBlinkLeft","right","eyeBlinkRight","bothClosed","detectDoubleBlink","baseArea","wentCloser","ratio","detectDistanceChange","pickTasks","count","sort","random","processFrame","session","trackingResult","failed","isComplete","currentIndex","tasks","failReason","timestamp","taskStartTime","elapsed","advanceTask","deltas","i","dy","dp","every","d","mean","reduce","a","b","s","isSuspicious","completedTasks","remaining","requiredPasses","targetDelta","baseYaw","direction","sign","threshold","base64UrlEncode","String","fromCharCode","btoa","base64UrlDecode","str","padded","repeat","binary","atob","from","c","charCodeAt","cachedKey","ensureKey","raw","crypto","getRandomValues","subtle","importKey","hash","getSigningKey","verifyToken","header","sig","signature","TextEncoder","encode","verify","decoded","JSON","parse","TextDecoder","decode","exp","Date","decodeToken","createTransport","payload","estimatedAge","livenessOk","success","stringify","alg","typ","iat","createToken","baseUrl","channel","createSession","transports","WebSocket","response","fetch","method","headers","sitekey","action","supportedTransports","ok","json","openChannel","transport","sessionId","wsUrl","ws","pending","closed","waitReady","onopen","onmessage","shift","onclose","receive","send","sendAndReceive","createWsChannel","createPollChannel","verifyViaChannel","getSession","createServerTransport","server","wasmModule","vmSession","challengeBundle","_faceData","_challengeParams","_bridge","initVM","wasmJs","loaderModule","loaderJs","initModule","wasmBin","initFn","exports","vm_init","bundleResponse","challengeVmbc","arrayBuffer","readU32","mod","ptr","HEAPU8","defineVmGlobal","getter","_","Object","defineProperty","get","set","configurable","setFaceData","faceData","setChallengeParams","executeChallenge","execFn","vm_exec_bytecode","freeFn","vm_free","inputPtr","_malloc","outLenPtr","outPtr","_free","errFn","vm_last_error","errPtr","detail","UTF8ToString","outLen","subarray","toBase64","bytes","decryptedCache","Map","decryptAndCache","modelId","has","buffer","modelInfo","models","encrypted","decryptFn","vm_decrypt_blob","decryptModel","stream","videoElement","CAMERA_CONSTRAINTS","facingMode","ideal","startCamera","navigator","mediaDevices","getUserMedia","then","srcObject","onloadedmetadata","play","videoWidth","videoHeight","captureFrame","getContext","drawImage","stopCamera","getTracks","forEach","stop","TASK_LABELS","nod","sleep","ms","r","setTimeout","runChallenge","widget","emitter","err","emit","errorCallback","retryCount","loadModel","waitForStart","startCameraFlow","attempt","loop","tracking","currentInstruction","currentTaskId","progress","runLivenessLoop","isPassed","frames","interval","frame","captureFrameBurst","ageResults","results","estimateAgeBurst","ages","trimmed","computeAge","cleanupLocal","callback","emitResult","error","runServerless","ensureModels","buf","getMediaPipeModelBuffer","bridge","trackFace","ts","freeze","source","removeMirrorVideo","mirror","autoplay","muted","playsInline","cssText","exposeMirrorVideo","waitForPositioning","challenge","rounds","cleanupVM","type","emitVerdict","task","vmOut","captureMotion","execVM","tokenSignature","complete","hint","nextChallenge","runServer","verdict","start","motionHistory","handle","callbacks","stableFrames","cancelled","onStatus","onReady","cancel","startPositioning","__vmBridge","unregisterBridge","destroyFn","vm_destroy","destroyVM","clear","getElementById","EventEmitter","listeners","on","handler","Set","off","handlers","delete","once","args","_original","removeAllListeners","widgets","normalizeParams","minAge","openage","startWidget","open","createModalWidget","bind","isReplayingClick","activeWidgetId","clearActiveWidget","stopPropagation","stopImmediatePropagation","widgetId","replayTargetClick","execute","autoRender","querySelectorAll","fn","expiredCallback","onloadName","currentScript","readyState","OpenAge","version"],"mappings":"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"}