@trymellon/js 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular.cjs +1 -1
- package/dist/angular.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.global.js +1 -1
- package/dist/index.js +1 -1
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +11 -8
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/domain/fsm/fsm.ts","../../src/ui/domain/fsm/constants.ts","../../src/ui/domain/validators/constants.ts","../../src/ui/domain/validators/validators-state.ts","../../src/ui/domain/contracts/constants.ts","../../src/ui/domain/validators/validators-attributes.ts","../../src/ui/application/transition.use-case.ts","../../src/ui/domain/viewmodels/auth-viewmodels.ts","../../src/ui/application/evaluate-env.use-case.ts","../../src/ui/application/auth-ui.application-service.ts","../../src/ui/adapters/attributes/parse.utils.ts","../../src/ui/adapters/attributes/inline.adapter.ts","../../src/ui/adapters/render/constants.ts","../../src/ui/adapters/render/shadow.adapter.ts","../../src/ui/adapters/render/auth.adapter.ts","../../src/ui/adapters/interactions/constants.ts","../../src/ui/adapters/interactions/dom.adapter.ts","../../src/ui/adapters/render/styles.adapter.ts","../../src/utils/result.ts","../../src/errors.ts","../../src/core/validators/helpers.ts","../../src/core/validators/register-auth.ts","../../src/core/validators/session.ts","../../src/core/validators/email.ts","../../src/core/validators/onboarding.ts","../../src/core/validators/cross-device.ts","../../src/core/validators/recovery.ts","../../src/core/api.ts","../../src/core/fetch-client.ts","../../src/utils/base64url.ts","../../src/core/webauthn-utils.ts","../../src/utils/support.ts","../../src/utils/validation.ts","../../src/core/ceremony.ts","../../src/core/webauthn.ts","../../src/core/polling-utils.ts","../../src/core/onboarding-manager.ts","../../src/core/cross-device-manager.ts","../../src/core/events.ts","../../src/core/constants.ts","../../src/core/adapters/telemetry-sender.ts","../../src/core/ports/telemetry.ts","../../src/core/services/auth-service.ts","../../src/core/recover.ts","../../src/core/services/recovery-service.ts","../../src/core/trymellon.ts","../../src/ui/adapters/infra/core-factory.adapter.ts","../../src/ui/adapters/infra/constants.ts","../../src/ui/adapters/infra/event-bridge.adapter.ts","../../src/ui/adapters/infra/env-status.adapter.ts","../../src/ui/presentation/ui-events.ts","../../src/ui/presentation/auth-controller.ts","../../src/ui/presentation/auth-element-base.ts","../../src/ui/adapters/attributes/modal.adapter.ts","../../src/ui/adapters/render/modal-structure.adapter.ts","../../src/ui/adapters/interactions/focus-trap.adapter.ts","../../src/ui/presentation/constants.ts","../../src/ui/presentation/trymellon-auth-modal.element.ts","../../src/ui/presentation/trymellon-auth.element.ts","../../src/ui/index.ts"],"sourcesContent":["/**\n * Pure UI FSM — no DOM, no I/O. (currentState, event) → nextState.\n * Transitions per 02-fsm-estado-modal.\n */\nimport type { UIState, FSMEvent, EnvResolvedPayload } from './types';\n\nfunction resolveEnvState(payload: EnvResolvedPayload): UIState {\n if (payload.recommendedFlow === 'fallback') {\n if (payload.fallbackType === 'email') return 'FALLBACK_EMAIL';\n if (payload.fallbackType === 'qr') return 'FALLBACK_QR';\n return 'FALLBACK';\n }\n switch (payload.mode) {\n case 'login':\n return 'READY_LOGIN';\n case 'register':\n return 'READY_REGISTER';\n case 'auto':\n default:\n return 'READY';\n }\n}\n\nfunction tabToReadyState(tab: 'register' | 'login'): UIState {\n return tab === 'register' ? 'READY_REGISTER' : 'READY_LOGIN';\n}\n\n/**\n * Next FSM state from current state and event. RESET from any state → IDLE.\n * Undefined transitions leave state unchanged (idempotent).\n */\nexport function getNextState(currentState: UIState, event: FSMEvent): UIState {\n if (currentState == null || event == null) return 'IDLE';\n if (event.type === 'RESET') return 'IDLE';\n\n if (event.type === 'TAB_CHANGE') {\n const tab = event.payload?.tab;\n if (tab !== 'register' && tab !== 'login') return currentState;\n const nextReady = tabToReadyState(tab);\n switch (currentState) {\n case 'READY':\n case 'READY_REGISTER':\n case 'READY_LOGIN':\n case 'FALLBACK':\n case 'FALLBACK_EMAIL':\n case 'FALLBACK_QR':\n case 'AUTHENTICATING':\n case 'ERROR':\n return nextReady;\n default:\n return currentState;\n }\n }\n\n switch (currentState) {\n case 'IDLE':\n if (event.type === 'ENV_EVAL_START') return 'EVALUATING_ENV';\n break;\n\n case 'EVALUATING_ENV':\n if (event.type === 'ENV_RESOLVED') return resolveEnvState(event.payload);\n if (event.type === 'ENV_DETACH') return 'IDLE';\n if (event.type === 'ENV_ERROR') return 'ERROR';\n break;\n\n case 'READY':\n case 'READY_REGISTER':\n case 'READY_LOGIN':\n if (event.type === 'START_AUTH') return 'AUTHENTICATING';\n break;\n\n case 'AUTHENTICATING':\n if (event.type === 'AUTH_SUCCESS') return 'SUCCESS';\n if (event.type === 'AUTH_ERROR') return 'ERROR';\n if (event.type === 'AUTH_FALLBACK') return 'FALLBACK';\n if (event.type === 'AUTH_FALLBACK_EMAIL') return 'FALLBACK_EMAIL';\n if (event.type === 'AUTH_FALLBACK_QR') return 'FALLBACK_QR';\n break;\n\n default:\n break;\n }\n\n return currentState;\n}\n","/**\n * FSM constants. Single source for initial state.\n */\n/** Initial FSM state (pre-attach). */\nexport const INITIAL_UI_STATE = 'IDLE' as const;\n","/**\n * Validator constants: enum arrays for type guards and parseEnum. Single source of truth.\n */\nimport type { UIState } from '../fsm/types';\nimport type {\n ThemeKind,\n ModalDisplayMode,\n ButtonAction,\n ButtonVariant,\n ModalVariant,\n} from '../contracts/types';\n\nexport const UI_STATES: readonly UIState[] = [\n 'IDLE',\n 'EVALUATING_ENV',\n 'READY',\n 'READY_REGISTER',\n 'READY_LOGIN',\n 'AUTHENTICATING',\n 'SUCCESS',\n 'ERROR',\n 'FALLBACK',\n 'FALLBACK_EMAIL',\n 'FALLBACK_QR',\n];\n\nexport const UI_MODES = ['login', 'register', 'auto'] as const;\nexport const THEME_KINDS: readonly ThemeKind[] = ['light', 'dark'];\nexport const TAB_KINDS = ['register', 'login'] as const;\nexport const MODAL_DISPLAY_MODES: readonly ModalDisplayMode[] = ['modal', 'inline'];\nexport const FALLBACK_TYPES = ['email', 'qr'] as const;\nexport const BUTTON_ACTIONS: readonly ButtonAction[] = ['direct-auth', 'open-modal'];\nexport const BUTTON_VARIANTS: readonly ButtonVariant[] = ['default', 'pill'];\nexport const MODAL_VARIANTS: readonly ModalVariant[] = ['default', 'minimal'];\n\nexport const RECOMMENDED_FLOWS = ['passkey', 'fallback'] as const;\n","/**\n * FSM state and event validators. Pure type guards and HOFs; no dependencies outside domain.\n */\nimport type {\n UIState,\n UIMode,\n EnvResolvedPayload,\n TabKind,\n FSMEvent,\n UIClientStatus,\n} from '../fsm/types';\nimport type {\n ThemeKind,\n ModalDisplayMode,\n ButtonAction,\n ButtonVariant,\n ModalVariant,\n} from '../contracts/types';\nimport { INITIAL_UI_STATE } from '../fsm/constants';\nimport {\n UI_STATES,\n UI_MODES,\n THEME_KINDS,\n TAB_KINDS,\n MODAL_DISPLAY_MODES,\n FALLBACK_TYPES,\n BUTTON_ACTIONS,\n BUTTON_VARIANTS,\n MODAL_VARIANTS,\n RECOMMENDED_FLOWS,\n} from './constants';\n\nexport {\n UI_STATES,\n UI_MODES,\n THEME_KINDS,\n TAB_KINDS,\n MODAL_DISPLAY_MODES,\n FALLBACK_TYPES,\n BUTTON_ACTIONS,\n BUTTON_VARIANTS,\n MODAL_VARIANTS,\n};\n\n/** Type guard: getClientStatus result (port) as UIClientStatus. */\nexport function isClientStatus(value: unknown): value is UIClientStatus {\n if (value == null || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n if (typeof v.isPasskeySupported !== 'boolean') return false;\n if (typeof v.platformAuthenticatorAvailable !== 'boolean') return false;\n if (v.recommendedFlow !== 'passkey' && v.recommendedFlow !== 'fallback') return false;\n return true;\n}\n\nfunction isOneOf<T extends string>(value: unknown, allowed: readonly T[]): value is T {\n return typeof value === 'string' && (allowed as readonly string[]).includes(value);\n}\n\nexport function isUIState(value: unknown): value is UIState {\n return isOneOf(value, UI_STATES);\n}\n\nexport function ensureUIState(value: unknown): UIState {\n return isUIState(value) ? value : (INITIAL_UI_STATE as UIState);\n}\n\nexport function isUIMode(value: unknown): value is UIMode {\n return isOneOf(value, UI_MODES);\n}\n\nexport function isThemeKind(value: unknown): value is ThemeKind {\n return isOneOf(value, THEME_KINDS);\n}\n\nexport function isTabKind(value: unknown): value is TabKind {\n return isOneOf(value, TAB_KINDS);\n}\n\nexport function isModalDisplayMode(value: unknown): value is ModalDisplayMode {\n return isOneOf(value, MODAL_DISPLAY_MODES);\n}\n\nexport function isButtonAction(value: unknown): value is ButtonAction {\n return isOneOf(value, BUTTON_ACTIONS);\n}\n\nexport function isButtonVariant(value: unknown): value is ButtonVariant {\n return isOneOf(value, BUTTON_VARIANTS);\n}\n\nexport function isModalVariant(value: unknown): value is ModalVariant {\n return isOneOf(value, MODAL_VARIANTS);\n}\n\nexport function isEnvResolvedPayload(value: unknown): value is EnvResolvedPayload {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n isOneOf(o.recommendedFlow, RECOMMENDED_FLOWS) &&\n isUIMode(o.mode) &&\n (o.fallbackType === undefined || isOneOf(o.fallbackType, FALLBACK_TYPES))\n );\n}\n\nexport function isFSMEvent(value: unknown): value is FSMEvent {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n const t = o.type;\n if (typeof t !== 'string') return false;\n switch (t) {\n case 'ENV_EVAL_START':\n case 'ENV_DETACH':\n case 'ENV_ERROR':\n case 'RESET':\n case 'START_AUTH':\n case 'AUTH_SUCCESS':\n case 'AUTH_ERROR':\n case 'AUTH_FALLBACK':\n case 'AUTH_FALLBACK_EMAIL':\n case 'AUTH_FALLBACK_QR':\n return true;\n case 'ENV_RESOLVED':\n return isEnvResolvedPayload(o.payload);\n case 'TAB_CHANGE':\n return (\n o.payload != null &&\n typeof o.payload === 'object' &&\n isTabKind((o.payload as Record<string, unknown>).tab)\n );\n default:\n return false;\n }\n}\n","/**\n * Contract constants: default values for parsed attributes. Single source of truth.\n */\nimport type { UIMode } from '../fsm/types';\nimport type {\n ThemeKind,\n ModalDisplayMode,\n ModalTabKind,\n TabLabels,\n ButtonAction,\n ButtonVariant,\n ModalVariant,\n ParsedAttributes,\n ParsedModalAttributes,\n} from './types';\n\nexport const DEFAULT_UI_MODE: UIMode = 'login';\nexport const DEFAULT_THEME: ThemeKind = 'light';\nexport const DEFAULT_MODAL_DISPLAY_MODE: ModalDisplayMode = 'modal';\nexport const DEFAULT_TAB: ModalTabKind = 'register';\n/** Register tab = \"Register\" to avoid duplicating \"Create account\" with slot content (e.g. label above QR). */\nexport const DEFAULT_TAB_LABELS: TabLabels = { register: 'Register', login: 'Sign in' };\n\nexport const DEFAULT_BUTTON_ACTION: ButtonAction = 'open-modal';\nexport const DEFAULT_BUTTON_VARIANT: ButtonVariant = 'default';\nexport const DEFAULT_MODAL_VARIANT: ModalVariant = 'default';\n\n/** Safe default for ParsedAttributes. */\nexport const DEFAULT_PARSED_ATTRIBUTES: ParsedAttributes = {\n appId: '',\n publishableKey: '',\n mode: DEFAULT_UI_MODE,\n externalUserId: null,\n theme: DEFAULT_THEME,\n action: DEFAULT_BUTTON_ACTION,\n triggerOnly: false,\n buttonVariant: DEFAULT_BUTTON_VARIANT,\n};\n\n/** Safe default for ParsedModalAttributes. */\nexport const DEFAULT_PARSED_MODAL_ATTRIBUTES: ParsedModalAttributes = {\n open: false,\n mode: DEFAULT_MODAL_DISPLAY_MODE,\n tab: DEFAULT_TAB,\n tabLabels: DEFAULT_TAB_LABELS,\n theme: DEFAULT_THEME,\n sessionId: null,\n onboardingUrl: null,\n isMobileOverride: null,\n appId: '',\n publishableKey: '',\n appName: null,\n dialogTitle: null,\n dialogDescription: null,\n externalUserId: null,\n modalVariant: DEFAULT_MODAL_VARIANT,\n};\n","/**\n * Validators for parsed attributes (root and modal). Pure type guards and HOFs.\n */\nimport type { ParsedAttributes, TabLabels, ParsedModalAttributes } from '../contracts/types';\nimport { DEFAULT_PARSED_ATTRIBUTES, DEFAULT_PARSED_MODAL_ATTRIBUTES } from '../contracts/constants';\nimport {\n isUIMode,\n isThemeKind,\n isTabKind,\n isModalDisplayMode,\n isButtonAction,\n isButtonVariant,\n isModalVariant,\n} from './validators-state';\n\nexport function isParsedAttributes(value: unknown): value is ParsedAttributes {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.appId === 'string' &&\n typeof o.publishableKey === 'string' &&\n isUIMode(o.mode) &&\n (o.externalUserId === null || typeof o.externalUserId === 'string') &&\n isThemeKind(o.theme) &&\n isButtonAction(o.action) &&\n typeof o.triggerOnly === 'boolean' &&\n isButtonVariant(o.buttonVariant)\n );\n}\n\nexport function isTabLabels(value: unknown): value is TabLabels {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return typeof o.register === 'string' && typeof o.login === 'string';\n}\n\nexport function isParsedModalAttributes(value: unknown): value is ParsedModalAttributes {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.open === 'boolean' &&\n isModalDisplayMode(o.mode) &&\n isTabKind(o.tab) &&\n isTabLabels(o.tabLabels) &&\n isThemeKind(o.theme) &&\n (o.sessionId === null || typeof o.sessionId === 'string') &&\n (o.onboardingUrl === null || typeof o.onboardingUrl === 'string') &&\n (o.isMobileOverride === null || typeof o.isMobileOverride === 'boolean') &&\n (o.fallbackType === undefined || o.fallbackType === 'email' || o.fallbackType === 'qr') &&\n typeof o.appId === 'string' &&\n typeof o.publishableKey === 'string' &&\n (o.appName == null || typeof o.appName === 'string') &&\n (o.dialogTitle == null || typeof o.dialogTitle === 'string') &&\n (o.dialogDescription == null || typeof o.dialogDescription === 'string') &&\n (o.externalUserId == null || typeof o.externalUserId === 'string') &&\n isModalVariant(o.modalVariant)\n );\n}\n\nexport function defaultParsedAttributes(): ParsedAttributes {\n return DEFAULT_PARSED_ATTRIBUTES;\n}\n\nexport function defaultParsedModalAttributes(): ParsedModalAttributes {\n return DEFAULT_PARSED_MODAL_ATTRIBUTES;\n}\n\nexport function ensureParsedAttributes(value: unknown): ParsedAttributes {\n return isParsedAttributes(value) ? value : defaultParsedAttributes();\n}\n\nexport function ensureParsedModalAttributes(value: unknown): ParsedModalAttributes {\n return isParsedModalAttributes(value) ? value : defaultParsedModalAttributes();\n}\n","/**\n * Use case: pure FSM transition. Validates types at boundary; delegates to domain getNextState.\n */\nimport { getNextState } from '../domain/fsm/fsm';\nimport type { UIState } from '../domain';\nimport { ensureUIState, isFSMEvent } from '../domain/validators';\n\n/** Applies event to FSM and returns next state. Invalid input → idempotent safe state. */\nexport function applyTransition(currentState: unknown, event: unknown): UIState {\n const state = ensureUIState(currentState);\n if (!isFSMEvent(event)) return state;\n return getNextState(state, event);\n}\n","/**\n * ViewModels for auth presentation. Group UIState + props needed for render.\n * No DOM dependencies; built from parsed attributes.\n */\nimport type { UIState, UIMode } from '../fsm/types';\nimport type {\n ThemeKind,\n ButtonVariant,\n ParsedAttributes,\n ParsedModalAttributes,\n TabLabels,\n ModalTabKind,\n} from '../contracts/types';\n\n/** ViewModel for the auth button/trigger content (trymellon-auth). */\nexport type AuthButtonViewModel = {\n state: UIState;\n theme: ThemeKind;\n mode: UIMode;\n buttonVariant: ButtonVariant;\n registerSessionReady?: boolean;\n primaryButtonLabel?: string;\n primaryButtonAriaLabel?: string;\n};\n\n/** ViewModel for the modal FSM content (trymellon-auth-modal). */\nexport type AuthModalViewModel = {\n state: UIState;\n theme: ThemeKind;\n tab: ModalTabKind;\n tabLabels: TabLabels;\n registerSessionReady?: boolean;\n primaryButtonLabel: string;\n primaryButtonAriaLabel: string;\n};\n\nexport function buildAuthButtonViewModel(\n state: UIState,\n parsed: ParsedAttributes,\n options?: {\n registerSessionReady?: boolean;\n primaryButtonLabel?: string;\n primaryButtonAriaLabel?: string;\n }\n): AuthButtonViewModel {\n return {\n state,\n theme: parsed.theme,\n mode: parsed.mode,\n buttonVariant: parsed.buttonVariant,\n ...(parsed.mode === 'register' &&\n options?.registerSessionReady !== undefined && {\n registerSessionReady: options.registerSessionReady,\n }),\n ...(options?.primaryButtonLabel !== undefined && {\n primaryButtonLabel: options.primaryButtonLabel,\n }),\n ...(options?.primaryButtonAriaLabel !== undefined && {\n primaryButtonAriaLabel: options.primaryButtonAriaLabel,\n }),\n };\n}\n\nexport function buildAuthModalViewModel(\n state: UIState,\n parsed: ParsedModalAttributes,\n options?: {\n registerSessionReady?: boolean;\n primaryButtonLabel?: string;\n primaryButtonAriaLabel?: string;\n }\n): AuthModalViewModel {\n return {\n state,\n theme: parsed.theme,\n tab: parsed.tab,\n tabLabels: parsed.tabLabels,\n ...(parsed.tab === 'register' &&\n options?.registerSessionReady !== undefined && {\n registerSessionReady: options.registerSessionReady,\n }),\n primaryButtonLabel: options?.primaryButtonLabel ?? 'Try Passkey',\n primaryButtonAriaLabel: options?.primaryButtonAriaLabel ?? 'Try Passkey, use this device',\n };\n}\n","/**\n * Use case: evaluate environment (getClientStatus) and return next FSM state. Validates params and port response at boundary; domain + EnvStatusPort only. No DOM.\n */\nimport type { EnvResolvedPayload, UIState, UIMode, UIClientStatus } from '../domain/types';\nimport type { EnvStatusPort } from '../ports/env-evaluator.port';\nimport { ensureUIState, isClientStatus, isUIMode } from '../domain/validators';\nimport { INITIAL_UI_STATE } from '../domain';\nimport { applyTransition } from './transition.use-case';\n\nexport type RunEnvEvalParams = {\n envStatusPort: EnvStatusPort;\n currentState: UIState;\n mode: UIMode;\n isMobileOverride?: boolean;\n /** When recommendedFlow is fallback, allows fixing FALLBACK_EMAIL vs FALLBACK_QR (e.g. modal). */\n fallbackType?: 'email' | 'qr';\n};\n\n/** Type guard: value has getClientStatus (EnvStatusPort). Invalid params/port → IDLE. */\nfunction hasGetClientStatus(x: unknown): x is EnvStatusPort {\n return typeof (x as Record<string, unknown>)?.getClientStatus === 'function';\n}\n\nexport async function runEnvEval(params: RunEnvEvalParams): Promise<UIState> {\n if (!hasGetClientStatus(params.envStatusPort)) return INITIAL_UI_STATE;\n\n const envStatusPort = params.envStatusPort;\n const currentState = ensureUIState(params.currentState);\n const mode = isUIMode(params.mode) ? params.mode : 'login';\n const isMobileOverride = params.isMobileOverride === true;\n const fallbackType =\n params.fallbackType === 'email' || params.fallbackType === 'qr'\n ? params.fallbackType\n : undefined;\n\n const stateEvaluating = applyTransition(currentState, { type: 'ENV_EVAL_START' });\n\n let status: UIClientStatus;\n try {\n const rawStatus = await envStatusPort.getClientStatus();\n if (!isClientStatus(rawStatus)) {\n return applyTransition(stateEvaluating, { type: 'ENV_ERROR' });\n }\n status = rawStatus;\n } catch {\n return applyTransition(stateEvaluating, { type: 'ENV_ERROR' });\n }\n\n const effectiveRecommendedFlow =\n isMobileOverride === true ? ('fallback' as const) : status.recommendedFlow;\n\n const payload: EnvResolvedPayload = {\n recommendedFlow: effectiveRecommendedFlow,\n mode,\n ...(effectiveRecommendedFlow === 'fallback' && fallbackType != null && { fallbackType }),\n };\n\n return applyTransition(stateEvaluating, { type: 'ENV_RESOLVED', payload });\n}\n","/**\n * Application facade: orchestrates use cases (applyTransition, runEnvEval) and core delegation. One method per UC; domain + ports only. Stale-response token: caller (WC) responsibility; stateless.\n */\nimport type { UIState, UIMode, TabKind } from '../domain/types';\nimport type { FSMEvent } from '../domain/types';\nimport type { CoreAuthPort, CoreAuthOptions } from '../ports/core-events.port';\nimport { applyTransition } from './transition.use-case';\nimport { runEnvEval, type RunEnvEvalParams } from './evaluate-env.use-case';\n\n/** Application facade contract: high-level methods per use case. */\nexport interface AuthUiApplicationService {\n /** Transition ENV_EVAL_START → EVALUATING_ENV (so WC shows evaluating state before await). */\n envEvalStart(currentState: UIState): UIState;\n\n /**\n * EvaluateEnvironment: evaluates env via port and returns final FSM state.\n * Always resolves with UIState. Caller (WC) must discard stale responses by comparing\n * a per-instance requestId after await (last-wins per component).\n */\n evaluateEnv(params: RunEnvEvalParams): Promise<UIState>;\n\n /** START_AUTH transition and core delegation (authenticate/register). */\n startAuth(\n currentState: UIState,\n mode: UIMode,\n coreAuthPort: CoreAuthPort,\n options?: CoreAuthOptions\n ): UIState;\n\n /** AUTH_SUCCESS transition. */\n handleAuthSuccess(currentState: UIState): UIState;\n\n /** AUTH_ERROR transition. */\n handleAuthError(currentState: UIState): UIState;\n\n /** Applies AUTH_SUCCESS only if state is AUTHENTICATING. Returns new state or null (avoids duplicating guard in WCs). */\n tryHandleAuthSuccess(currentState: UIState): UIState | null;\n\n /** Applies AUTH_ERROR only if state is AUTHENTICATING. Returns new state or null (avoids duplicating guard in WCs). */\n tryHandleAuthError(currentState: UIState): UIState | null;\n\n /** AUTH_FALLBACK[_EMAIL|_QR] transition by channel. */\n handleFallback(currentState: UIState, fallbackKind?: 'email' | 'qr'): UIState;\n\n /** TAB_CHANGE transition. */\n tabChange(currentState: UIState, tab: TabKind): UIState;\n\n /** RESET → IDLE transition. */\n reset(currentState: UIState): UIState;\n}\n\n/**\n * Pure helper: returns whether the FSM allows starting AUTH from the given state.\n * Uses applyTransition as single source of truth: if START_AUTH does not change state, it is not allowed.\n */\nexport function canStartAuth(currentState: UIState): boolean {\n const nextState = applyTransition(currentState, { type: 'START_AUTH' });\n return nextState !== currentState;\n}\n\nfunction applyStartAuthAndInvokeCore(\n currentState: UIState,\n mode: UIMode,\n coreAuthPort: CoreAuthPort,\n options?: CoreAuthOptions\n): UIState {\n const nextState = applyTransition(currentState, { type: 'START_AUTH' });\n if (mode === 'register') {\n coreAuthPort.register(options);\n } else {\n coreAuthPort.authenticate(options);\n }\n return nextState;\n}\n\n/** Fallback kind → FSM event. One lookup; generic is the default key. */\nconst FALLBACK_EVENT: Record<'email' | 'qr' | 'generic', FSMEvent> = {\n email: { type: 'AUTH_FALLBACK_EMAIL' },\n qr: { type: 'AUTH_FALLBACK_QR' },\n generic: { type: 'AUTH_FALLBACK' },\n};\n\nfunction applyFallbackTransition(currentState: UIState, fallbackKind?: 'email' | 'qr'): UIState {\n const key: 'email' | 'qr' | 'generic' =\n fallbackKind === 'email' ? 'email' : fallbackKind === 'qr' ? 'qr' : 'generic';\n return applyTransition(currentState, FALLBACK_EVENT[key]);\n}\n\n/** Stateless facade implementation; orchestrates use cases and ports. */\nexport const authUiApplicationService: AuthUiApplicationService = {\n envEvalStart(currentState) {\n return applyTransition(currentState, { type: 'ENV_EVAL_START' });\n },\n\n evaluateEnv(params) {\n return runEnvEval(params);\n },\n\n startAuth(currentState, mode, coreAuthPort, options) {\n return applyStartAuthAndInvokeCore(currentState, mode, coreAuthPort, options);\n },\n\n handleAuthSuccess(currentState) {\n return applyTransition(currentState, { type: 'AUTH_SUCCESS' });\n },\n\n handleAuthError(currentState) {\n return applyTransition(currentState, { type: 'AUTH_ERROR' });\n },\n\n tryHandleAuthSuccess(currentState) {\n if (currentState !== 'AUTHENTICATING') return null;\n return applyTransition(currentState, { type: 'AUTH_SUCCESS' });\n },\n\n tryHandleAuthError(currentState) {\n if (currentState !== 'AUTHENTICATING') return null;\n return applyTransition(currentState, { type: 'AUTH_ERROR' });\n },\n\n handleFallback(currentState, fallbackKind) {\n return applyFallbackTransition(currentState, fallbackKind);\n },\n\n tabChange(currentState, tab) {\n return applyTransition(currentState, { type: 'TAB_CHANGE', payload: { tab } });\n },\n\n reset(currentState) {\n return applyTransition(currentState, { type: 'RESET' });\n },\n};\n","/**\n * Pure helpers for DOM attribute parsing (string | null) → type. Shared by inline and modal adapters. No external deps; adapters layer.\n */\n\nexport function parseString(value: string | null): string {\n if (value == null || value.trim() === '') return '';\n return value.trim();\n}\n\nexport function parseOptionalString(value: string | null): string | null {\n const s = parseString(value);\n return s === '' ? null : s;\n}\n\n/**\n * Parses boolean attribute (HTML semantics: presence = true). Any present value including \"\" is true; only null is false.\n */\nexport function parseBoolean(value: string | null): boolean {\n if (value == null) return false;\n const v = value.trim().toLowerCase();\n return v === 'true' || v === '1' || v === '';\n}\n\nexport function parseOptionalBoolean(value: string | null): boolean | null {\n if (value == null || value.trim() === '') return null;\n const v = value.trim().toLowerCase();\n if (v === 'true' || v === '1') return true;\n if (v === 'false' || v === '0') return false;\n return null;\n}\n\n/**\n * Parses string to one of allowed values; null or empty → fallback. Normalizes trim + lowercase.\n */\nexport function parseEnum<T extends string>(\n value: string | null,\n allowed: readonly T[],\n fallback: T\n): T {\n if (value == null || value.trim() === '') return fallback;\n const normalized = value.trim().toLowerCase();\n if (allowed.includes(normalized as T)) return normalized as T;\n return fallback;\n}\n\n/**\n * Like parseEnum but returns undefined when attribute is missing or invalid. For optional fields without default.\n */\nexport function parseOptionalEnum<T extends string>(\n value: string | null,\n allowed: readonly T[]\n): T | undefined {\n if (value == null || value.trim() === '') return undefined;\n const normalized = value.trim().toLowerCase();\n if (allowed.includes(normalized as T)) return normalized as T;\n return undefined;\n}\n","/**\n * Parses and validates observedAttributes for inline WC. Uses parseEnum + domain enum arrays and defaults.\n */\nimport type { ParsedAttributes } from '../../domain/contracts/types';\nimport {\n UI_MODES,\n THEME_KINDS,\n BUTTON_ACTIONS,\n BUTTON_VARIANTS,\n DEFAULT_UI_MODE,\n DEFAULT_THEME,\n DEFAULT_BUTTON_ACTION,\n DEFAULT_BUTTON_VARIANT,\n} from '../../domain';\nimport { ensureParsedAttributes } from '../../domain/validators';\nimport { parseString, parseOptionalString, parseEnum, parseBoolean } from './parse.utils';\n\nexport type { ThemeKind, ParsedAttributes } from '../../domain/contracts/types';\n\nexport function parseAttributesFromElement(element: HTMLElement): ParsedAttributes {\n const raw = {\n appId: parseString(element.getAttribute('app-id')),\n publishableKey: parseString(element.getAttribute('publishable-key')),\n mode: parseEnum(element.getAttribute('mode'), UI_MODES, DEFAULT_UI_MODE),\n externalUserId: parseOptionalString(element.getAttribute('external-user-id')),\n theme: parseEnum(element.getAttribute('theme'), THEME_KINDS, DEFAULT_THEME),\n action: parseEnum(element.getAttribute('action'), BUTTON_ACTIONS, DEFAULT_BUTTON_ACTION),\n triggerOnly: parseBoolean(element.getAttribute('trigger-only')),\n buttonVariant: parseEnum(\n element.getAttribute('button-variant'),\n BUTTON_VARIANTS,\n DEFAULT_BUTTON_VARIANT\n ),\n };\n return ensureParsedAttributes(raw);\n}\n","/**\n * Centralized constants for the render layer (Shadow DOM, modal structure, selectors, labels).\n * Single source for IDs, class names, selectors, and copy used by shadow.adapter and modal-structure.adapter.\n */\n\n/** Main container ID in Shadow DOM; shared by inline and modal. */\nexport const MELLON_ROOT_ID = 'mellon-root';\n\n/** Primary auth (passkey) button selector. */\nexport const MELLON_BTN_SELECTOR = '.mellon-btn';\n\n/** Fallback button selector (data-mellon-action^=\"fallback\"). */\nexport const MELLON_FALLBACK_BTN_SELECTOR = '[data-mellon-action^=\"fallback\"]';\n\n/** data-mellon-action value for email fallback. */\nexport const MELLON_ACTION_FALLBACK_EMAIL = 'fallback-email';\n\n/** data-mellon-action value for QR fallback. */\nexport const MELLON_ACTION_FALLBACK_QR = 'fallback-qr';\n\n/** Primary button label when used as trigger (opens modal). */\nexport const PRIMARY_BUTTON_LABEL = 'TryMellon';\n\n/** Primary button label when inside modal (passkey on this device). Same structure as landing. */\nexport const MODAL_PASSKEY_BUTTON_LABEL = 'Try Passkey';\n\n/** aria-label for trigger/CTA (context without visual; not icon-only). */\nexport const TRIGGER_ARIA_LABEL = 'TryMellon, open authentication';\n\n/** aria-label for passkey button inside modal. */\nexport const MODAL_PASSKEY_ARIA_LABEL = 'Try Passkey, use this device';\n\n/** Internal: SVG namespace for fingerprint icon. */\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\n\n// --- Modal structure (modal-structure.adapter) ---\n\nexport const WRAPPER_CLASS = 'mellon-modal-wrapper';\nexport const OVERLAY_CLASS = 'mellon-modal-overlay';\nexport const PANEL_CLASS = 'mellon-modal-panel';\nexport const TABS_CLASS = 'mellon-modal-tabs';\nexport const CONTENT_WRAPPER_CLASS = 'mellon-modal-content';\n\n/** Slot name for host-injected QR / cross-device UI. Use <trymellon-auth-modal><div slot=\"cross-device\">...</div></trymellon-auth-modal>. */\nexport const SLOT_CROSS_DEVICE = 'cross-device';\n\nexport const SLOT_FALLBACK_CTA = 'fallback-cta';\n\n/** IDs for dialog aria-labelledby / aria-describedby. */\nexport const MELLON_DIALOG_TITLE_ID = 'mellon-dialog-title';\nexport const MELLON_DIALOG_DESC_ID = 'mellon-dialog-desc';\n\nexport const DIALOG_TITLE_TEXT = 'TryMellon — Sign in or register';\n/** Title when app name is set: \"{appName} — Sign in or register\". */\nexport const DIALOG_TITLE_WITH_APP = (appName: string): string =>\n `${appName} — Sign in or register`;\nexport const DIALOG_DESC_TEXT = 'Pick Register or Sign in to continue.';\n/** Separator between QR/cross-device and Try Passkey (with lines: —— or ——). */\nexport const MODAL_SEPARATOR_TEXT = 'Or sign in with';\nexport const CROSS_DEVICE_WRAP_CLASS = 'mellon-cross-device-wrap';\nexport const MODAL_SEPARATOR_CLASS = 'mellon-modal-separator';\n\n/** Modal close button (top-right, inside panel). */\nexport const MODAL_CLOSE_BUTTON_CLASS = 'mellon-modal-close-btn';\nexport const MODAL_CLOSE_BUTTON_ARIA_LABEL = 'Close dialog';\n\n/** Cross-device CTA (default slot content when host does not inject QR). Always visible above \"or\" and Try Passkey. */\nexport const CROSS_DEVICE_CTA_TEXT = 'Try from another device';\nexport const CROSS_DEVICE_CTA_CLASS = 'mellon-cross-device-cta';\n/** Aria-label for QR button (icon-only, no visible text). */\nexport const CROSS_DEVICE_QR_BUTTON_ARIA_LABEL = 'Try with QR';\n\n/** QR area: skeleton and timeout (owned by modal). */\nexport const MELLON_QR_SKELETON_CLASS = 'mellon-cross-device-skeleton';\nexport const MELLON_QR_ERROR_CLASS = 'mellon-cross-device-error';\nexport const MELLON_QR_SLOT_WRAP_CLASS = 'mellon-cross-device-slot-wrap';\nexport const QR_SKELETON_TEXT = 'Loading QRs';\nexport const QR_TIMEOUT_ERROR_TEXT = 'QR could not be loaded. Try again.';\n/** Default timeout (ms) when modal expects injected QR; host can override via qr-load-timeout-ms. */\nexport const QR_LOAD_TIMEOUT_MS_DEFAULT = 12_000;\n","/**\n * WC Shadow DOM render. Validates state at boundary (domain validators). No innerHTML/outerHTML; createElement/setAttribute only.\n * Constants: render/constants.ts. Re-exports public constants for consumers (e.g. interactions, presentation).\n */\nimport type { UIState } from '../../domain';\nimport type { ButtonVariant } from '../../domain/contracts/types';\nimport { ensureUIState } from '../../domain/validators';\nimport type { IRenderSurface, RenderOptions } from '../../ports/render.port';\nimport {\n MELLON_ROOT_ID,\n MELLON_BTN_SELECTOR,\n MELLON_FALLBACK_BTN_SELECTOR,\n MELLON_ACTION_FALLBACK_EMAIL,\n MELLON_ACTION_FALLBACK_QR,\n PRIMARY_BUTTON_LABEL,\n MODAL_PASSKEY_BUTTON_LABEL,\n TRIGGER_ARIA_LABEL,\n MODAL_PASSKEY_ARIA_LABEL,\n SVG_NS,\n} from './constants';\n\nexport { MELLON_ROOT_ID, MELLON_BTN_SELECTOR, MELLON_FALLBACK_BTN_SELECTOR };\nexport { MELLON_ACTION_FALLBACK_EMAIL, MELLON_ACTION_FALLBACK_QR };\nexport {\n PRIMARY_BUTTON_LABEL,\n MODAL_PASSKEY_BUTTON_LABEL,\n TRIGGER_ARIA_LABEL,\n MODAL_PASSKEY_ARIA_LABEL,\n};\n\n/** Fingerprint icon as inline SVG (no external resources). createElementNS only. */\nfunction createFingerprintIconSVG(): SVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('class', 'mellon-btn-icon');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const path1 = document.createElementNS(SVG_NS, 'path');\n path1.setAttribute('d', 'M12 22a10 10 0 0 0 10-10 10 10 0 0 0-20 0 10 10 0 0 0 10 10Z');\n const path2 = document.createElementNS(SVG_NS, 'path');\n path2.setAttribute('d', 'M12 14a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2 2 2 0 0 0 2 2Z');\n const path3 = document.createElementNS(SVG_NS, 'path');\n path3.setAttribute('d', 'M5 19.05A9 9 0 0 1 3 12a9 9 0 0 1 2-5.05');\n\n svg.appendChild(path1);\n svg.appendChild(path2);\n svg.appendChild(path3);\n return svg;\n}\n\n/** Primary button default: fingerprint icon + visible label + aria-label. */\nfunction createPrimaryButtonDefault(\n disabled: boolean,\n label: string = PRIMARY_BUTTON_LABEL,\n ariaLabel: string = TRIGGER_ARIA_LABEL\n): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn';\n btn.setAttribute('aria-label', ariaLabel);\n btn.disabled = disabled;\n btn.appendChild(createFingerprintIconSVG());\n btn.appendChild(document.createTextNode(label));\n return btn;\n}\n\n/** Primary button pill: landing-style (rounded-full, circle with icon + label), touch target ≥48px. */\nfunction createPrimaryButtonPill(\n disabled: boolean,\n label: string = PRIMARY_BUTTON_LABEL,\n ariaLabel: string = TRIGGER_ARIA_LABEL\n): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn mellon-btn-pill';\n btn.setAttribute('aria-label', ariaLabel);\n btn.disabled = disabled;\n const iconCircle = document.createElement('span');\n iconCircle.className = 'mellon-btn-pill-icon-circle';\n iconCircle.setAttribute('aria-hidden', 'true');\n iconCircle.appendChild(createFingerprintIconSVG());\n btn.appendChild(iconCircle);\n btn.appendChild(document.createTextNode(label));\n return btn;\n}\n\n/** HOF: returns the primary button builder for the given variant (stateless). */\nfunction getPrimaryButtonBuilder(\n variant: ButtonVariant,\n label: string = PRIMARY_BUTTON_LABEL,\n ariaLabel: string = TRIGGER_ARIA_LABEL\n): (disabled: boolean) => HTMLButtonElement {\n return (disabled: boolean) =>\n variant === 'pill'\n ? createPrimaryButtonPill(disabled, label, ariaLabel)\n : createPrimaryButtonDefault(disabled, label, ariaLabel);\n}\n\n/** Resolves primary button options from RenderOptions (single source for defaults). */\nfunction getPrimaryButtonOptions(options: RenderOptions): {\n variant: ButtonVariant;\n label: string;\n ariaLabel: string;\n} {\n return {\n variant: options.buttonVariant ?? 'default',\n label: options.primaryButtonLabel ?? PRIMARY_BUTTON_LABEL,\n ariaLabel: options.primaryButtonAriaLabel ?? TRIGGER_ARIA_LABEL,\n };\n}\n\n/** Builds the primary passkey button for READY_LOGIN / READY_REGISTER / READY (DRY). */\nfunction buildPrimaryButtonForReadyState(options: RenderOptions): HTMLButtonElement {\n const { variant, label, ariaLabel } = getPrimaryButtonOptions(options);\n return getPrimaryButtonBuilder(variant, label, ariaLabel)(false);\n}\n\nfunction ensureRoot(surface: IRenderSurface): HTMLElement {\n const { shadowRoot } = surface;\n let root = shadowRoot.getElementById(MELLON_ROOT_ID);\n if (!root) {\n root = document.createElement('div');\n root.id = MELLON_ROOT_ID;\n root.className = 'mellon-root';\n shadowRoot.appendChild(root);\n }\n return root;\n}\n\nfunction createParagraph(className: string, text: string): HTMLParagraphElement {\n const p = document.createElement('p');\n p.className = className;\n p.textContent = text;\n return p;\n}\n\n/** Fallback button with data-mellon-action for host click handling. createElement/setAttribute only. */\nfunction createFallbackButton(\n action: 'fallback' | typeof MELLON_ACTION_FALLBACK_EMAIL | typeof MELLON_ACTION_FALLBACK_QR,\n label: string\n): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn mellon-btn-fallback';\n btn.setAttribute('data-mellon-action', action);\n btn.textContent = label;\n return btn;\n}\n\ntype FallbackState = 'FALLBACK' | 'FALLBACK_EMAIL' | 'FALLBACK_QR';\ntype FallbackAction =\n | 'fallback'\n | typeof MELLON_ACTION_FALLBACK_EMAIL\n | typeof MELLON_ACTION_FALLBACK_QR;\n\nconst FALLBACK_BUTTON_CONFIG: Record<FallbackState, { action: FallbackAction; label: string }> = {\n FALLBACK: { action: 'fallback', label: 'Continuar' },\n FALLBACK_EMAIL: { action: MELLON_ACTION_FALLBACK_EMAIL, label: 'Continuar con email' },\n FALLBACK_QR: { action: MELLON_ACTION_FALLBACK_QR, label: 'Continuar con QR' },\n};\n\nfunction buildFallbackUI(state: FallbackState): HTMLElement {\n const wrap = document.createElement('div');\n wrap.className = 'mellon-fallback';\n const msg = document.createElement('p');\n msg.className = 'mellon-message';\n msg.textContent = 'Fallback disponible.';\n wrap.appendChild(msg);\n const { action, label } = FALLBACK_BUTTON_CONFIG[state];\n wrap.appendChild(createFallbackButton(action, label));\n return wrap;\n}\n\nfunction buildContentForState(state: UIState, options: RenderOptions): DocumentFragment {\n const fragment = document.createDocumentFragment();\n\n switch (state) {\n case 'IDLE':\n case 'EVALUATING_ENV':\n fragment.appendChild(createParagraph('mellon-loading', 'Loading…'));\n break;\n\n case 'READY_LOGIN':\n fragment.appendChild(buildPrimaryButtonForReadyState(options));\n break;\n\n case 'READY_REGISTER':\n if (options.registerSessionReady === false) {\n fragment.appendChild(createParagraph('mellon-loading', 'Preparando registro…'));\n } else {\n fragment.appendChild(buildPrimaryButtonForReadyState(options));\n }\n break;\n\n case 'READY':\n fragment.appendChild(buildPrimaryButtonForReadyState(options));\n break;\n\n case 'AUTHENTICATING':\n fragment.appendChild(createParagraph('mellon-loading', 'Authenticating…'));\n break;\n\n case 'SUCCESS':\n fragment.appendChild(createParagraph('mellon-message', 'Success.'));\n break;\n\n case 'ERROR':\n fragment.appendChild(createParagraph('mellon-message', 'Something went wrong.'));\n break;\n\n case 'FALLBACK':\n case 'FALLBACK_EMAIL':\n case 'FALLBACK_QR':\n fragment.appendChild(buildFallbackUI(state));\n break;\n\n default:\n fragment.appendChild(createParagraph('mellon-loading', 'Loading…'));\n }\n\n return fragment;\n}\n\n/** Updates render surface from FSM state. Validates state at boundary; invalid → IDLE (fail-safe). */\nexport function render(surface: IRenderSurface, state: unknown, options: RenderOptions = {}): void {\n const safeState = ensureUIState(state);\n const root = ensureRoot(surface);\n const content = buildContentForState(safeState, options);\n root.replaceChildren(...Array.from(content.childNodes));\n}\n","/**\n * Auth render helpers: viewmodel → RenderOptions → shadow-render.\n * Single place to translate AuthButtonViewModel / AuthModalViewModel to the existing render() contract.\n */\nimport type { IRenderSurface } from '../../ports/render.port';\nimport type { RenderOptions } from '../../ports/render.port';\nimport type { AuthButtonViewModel, AuthModalViewModel } from '../../domain/auth-viewmodels';\nimport { tabToUIMode } from '../../domain/types';\nimport { render } from './shadow.adapter';\n\nfunction viewModelToRenderOptions(vm: AuthButtonViewModel): RenderOptions {\n return {\n theme: vm.theme,\n mode: vm.mode,\n buttonVariant: vm.buttonVariant,\n registerSessionReady: vm.registerSessionReady,\n primaryButtonLabel: vm.primaryButtonLabel,\n primaryButtonAriaLabel: vm.primaryButtonAriaLabel,\n };\n}\n\nfunction modalViewModelToRenderOptions(vm: AuthModalViewModel): RenderOptions {\n return {\n theme: vm.theme,\n mode: tabToUIMode(vm.tab),\n buttonVariant: 'pill',\n registerSessionReady: vm.registerSessionReady,\n primaryButtonLabel: vm.primaryButtonLabel,\n primaryButtonAriaLabel: vm.primaryButtonAriaLabel,\n };\n}\n\n/**\n * Renders the auth button/trigger FSM content onto the surface using the viewmodel.\n * Uses the existing shadow-render adapter; does not know DOM beyond the surface.\n */\nexport function renderAuthButton(surface: IRenderSurface, vm: AuthButtonViewModel): void {\n render(surface, vm.state, viewModelToRenderOptions(vm));\n}\n\n/**\n * Renders the auth modal FSM content onto the surface using the viewmodel.\n * Does not create modal structure (wrapper/overlay/panel); the WC must call ensureModalStructure first if applicable.\n */\nexport function renderAuthModal(surface: IRenderSurface, vm: AuthModalViewModel): void {\n render(surface, vm.state, modalViewModelToRenderOptions(vm));\n}\n","/**\n * Centralized constants for the interactions layer (click delegation, focus trap).\n * Selectors and attribute names used by dom.adapter and focus-trap.adapter.\n */\n\n/** Modal tabs container selector (register/login tab buttons). */\nexport const MELLON_MODAL_TABS_SELECTOR = '.mellon-modal-tabs';\n\n/** Attribute name for tab value on buttons (register | login). */\nexport const TAB_ATTR = 'data-tab';\n\n/** Focusable elements for focus trap (a11y). Excludes disabled and [tabindex=\"-1\"]. */\nexport const FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/** Selector for any explicit \\\"close modal\\\" control inside the modal content. */\nexport const MELLON_MODAL_CLOSE_SELECTOR = '[data-mellon-modal-close=\"true\"]';\n","/**\n * DOM interaction delegation in Shadow Root: clicks on primary button, fallback, modal tabs and close controls.\n * Semantic callbacks. Constants: interactions/constants.ts + render/constants.ts.\n */\nimport {\n MELLON_BTN_SELECTOR,\n MELLON_FALLBACK_BTN_SELECTOR,\n MELLON_ACTION_FALLBACK_EMAIL,\n MELLON_ACTION_FALLBACK_QR,\n OVERLAY_CLASS,\n} from '../render/constants';\nimport type { ModalTabKind } from '../../domain/contracts/types';\nimport { MELLON_MODAL_TABS_SELECTOR, MELLON_MODAL_CLOSE_SELECTOR, TAB_ATTR } from './constants';\n\n/** Maps data-mellon-action to fallback type. Generic \"fallback\" → undefined (same callback path). */\nfunction fallbackActionToType(action: string | null): 'email' | 'qr' | undefined {\n if (action === MELLON_ACTION_FALLBACK_EMAIL) return 'email';\n if (action === MELLON_ACTION_FALLBACK_QR) return 'qr';\n return undefined;\n}\n\nexport type AuthButtonInteractionConfig = {\n onPrimaryClick(): void;\n /** type undefined = generic \"Continuar\" (data-mellon-action=\"fallback\"). */\n onFallbackClick(type?: 'email' | 'qr'): void;\n};\n\nexport type AuthModalInteractionConfig = {\n onTabChange(tab: ModalTabKind): void;\n onPrimaryClick(): void;\n /** type undefined = generic fallback. */\n onFallbackClick(type?: 'email' | 'qr'): void;\n /** Called when user clicks the grey backdrop outside the modal panel. */\n onOverlayClick?(): void;\n /** Called when user clicks any control marked with data-mellon-modal-close=\"true\" inside the modal. */\n onCloseClick?(): void;\n};\n\n/**\n * Registers click delegation for the auth button: primary vs fallback.\n * Checks fallback first (more specific), then primary.\n * @returns Function to remove listeners (teardown).\n */\nexport function registerAuthButtonInteractions(\n root: ShadowRoot,\n config: AuthButtonInteractionConfig\n): () => void {\n const handler = (e: Event): void => {\n const target = e.target instanceof Element ? e.target : null;\n if (!target) return;\n\n const fallbackBtn = target.closest(MELLON_FALLBACK_BTN_SELECTOR);\n if (fallbackBtn instanceof HTMLButtonElement) {\n config.onFallbackClick(fallbackActionToType(fallbackBtn.getAttribute('data-mellon-action')));\n return;\n }\n\n if (target.closest(MELLON_BTN_SELECTOR)) {\n config.onPrimaryClick();\n }\n };\n\n root.addEventListener('click', handler);\n return () => root.removeEventListener('click', handler);\n}\n\n/**\n * Registers click delegation for the modal: close controls, tabs (register/login), primary button and overlay.\n * Order: explicit close → fallback → tabs → primary → overlay.\n * @returns Function to remove listeners (teardown).\n */\nexport function registerAuthModalInteractions(\n root: ShadowRoot,\n config: AuthModalInteractionConfig\n): () => void {\n const handler = (e: Event): void => {\n const target = e.target instanceof Element ? e.target : null;\n if (!target) return;\n\n if (config.onCloseClick) {\n const closeBtn = target.closest(MELLON_MODAL_CLOSE_SELECTOR);\n if (closeBtn instanceof HTMLElement) {\n config.onCloseClick();\n return;\n }\n }\n\n const fallbackBtn = target.closest(MELLON_FALLBACK_BTN_SELECTOR);\n if (fallbackBtn instanceof HTMLButtonElement) {\n config.onFallbackClick(fallbackActionToType(fallbackBtn.getAttribute('data-mellon-action')));\n return;\n }\n\n const tabsContainer = root.querySelector(MELLON_MODAL_TABS_SELECTOR);\n if (tabsContainer?.contains(target)) {\n const tabEl = target.closest(`[${TAB_ATTR}]`);\n const tab = tabEl?.getAttribute(TAB_ATTR);\n if (tab === 'register' || tab === 'login') {\n config.onTabChange(tab as ModalTabKind);\n return;\n }\n }\n\n if (target.closest(MELLON_BTN_SELECTOR)) {\n config.onPrimaryClick();\n return;\n }\n\n if (config.onOverlayClick) {\n const overlay = root.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (overlay && target === overlay) {\n config.onOverlayClick();\n }\n }\n };\n\n root.addEventListener('click', handler);\n return () => root.removeEventListener('click', handler);\n}\n","/**\n * WC styles. Injected via adoptedStyleSheets or <style> + textContent. No innerHTML.\n * Constructable Stylesheet when supported; <style> fallback (e.g. Safari <16.4).\n */\n\n/**\n * Host overrides via CSS custom properties. Delegation: --mellon-* fallback to MDS-like tokens\n * (--surface-elevated, --text-strong, etc.) so the host can drive look without coupling.\n * Default: white-label minimal TryMellon — neutral with a cool tint (220°), WCAG AA.\n * Theming and accessibility are configurable via WC attributes and host CSS.\n */\nexport const BASE_STYLES = `\n:host {\n display: block;\n max-width: 100%;\n border: none;\n outline: none;\n /* Inherit --font-sans from host (e.g. landing: Noto Sans JP) or --mellon-font-sans; fallback system stack. */\n font-family: var(--font-sans, var(--mellon-font-sans, system-ui, -apple-system, sans-serif));\n --mellon-surface: var(--mellon-surface, hsl(var(--surface-elevated, 220 14% 98%)));\n --mellon-text: var(--mellon-text, hsl(var(--text-strong, 220 12% 14%)));\n --mellon-text-muted: var(--mellon-text-muted, hsl(var(--text-muted, 220 10% 48%)));\n --mellon-border: var(--mellon-border, hsl(var(--border-strong, 220 10% 90%)));\n --mellon-primary: var(--mellon-primary, hsl(var(--primary, 217 91% 58%)));\n --mellon-primary-contrast: var(--mellon-primary-contrast, #fff);\n --mellon-radius: var(--mellon-radius, var(--radius, 8px));\n --mellon-focus-ring: var(--mellon-focus-ring, hsl(217 91% 50%));\n --mellon-overlay: var(--mellon-overlay, rgba(0,0,0,0.5));\n /* Panel padding: keeps content away from edges; host can override. */\n --mellon-modal-panel-padding: var(--mellon-modal-panel-padding, 2rem);\n /* Cross-device CTA: text colour (grey between strong and muted). */\n --mellon-cta-text-color: var(--mellon-cta-text-color, var(--mellon-text-muted));\n /* Separator: line and \"or\" text (standard UI divider). */\n --mellon-separator-line: var(--mellon-border);\n --mellon-separator-text: var(--mellon-text-muted);\n /* QR icon button (cross-device). */\n --mellon-qr-btn-bg: var(--mellon-qr-btn-bg, transparent);\n --mellon-qr-btn-border: var(--mellon-qr-btn-border, var(--mellon-border));\n --mellon-qr-btn-color: var(--mellon-qr-btn-color, var(--mellon-text));\n}\n:host([theme=\"dark\"]) {\n --mellon-surface: var(--mellon-surface, hsl(var(--surface-elevated, 220 12% 11%)));\n --mellon-text: var(--mellon-text, hsl(var(--text-strong, 220 10% 96%)));\n --mellon-text-muted: var(--mellon-text-muted, hsl(var(--text-muted, 220 8% 62%)));\n --mellon-border: var(--mellon-border, hsl(var(--border-strong, 220 10% 22%)));\n --mellon-primary: var(--mellon-primary, hsl(var(--primary, 217 96% 72%)));\n --mellon-primary-contrast: var(--mellon-primary-contrast, #fff);\n --mellon-focus-ring: var(--mellon-focus-ring, hsl(217 96% 65%));\n}\n/* Pill variant: landing-style button (circle + label) uses same tokens. */\n:host([button-variant=\"pill\"]) .mellon-btn-pill {\n --mellon-btn-bg: var(--mellon-surface);\n --mellon-btn-border: var(--mellon-border);\n --mellon-btn-text: var(--mellon-text);\n}\n.mellon-root {\n padding: 1rem;\n min-width: 0;\n background: var(--mellon-surface);\n color: var(--mellon-text);\n border-radius: var(--mellon-radius);\n}\n.mellon-loading,\n.mellon-message {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mellon-text-muted);\n}\n.mellon-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n min-height: 48px;\n padding: 12px 24px;\n font-size: 1rem;\n font-weight: 500;\n background: var(--mellon-primary);\n color: var(--mellon-primary-contrast);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n}\n.mellon-btn:hover:not(:disabled) {\n opacity: 0.92;\n}\n.mellon-btn:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n.mellon-btn .mellon-btn-icon {\n width: 1.25em;\n height: 1.25em;\n flex-shrink: 0;\n}\n.mellon-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.mellon-btn-pill {\n min-height: 48px;\n min-width: 48px;\n padding: 0.5rem 1.25rem;\n border-radius: 9999px;\n border: none;\n background: var(--mellon-surface);\n color: var(--mellon-text);\n gap: 0.75rem;\n}\n.mellon-btn-pill .mellon-btn-pill-icon-circle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.275em;\n height: 1.275em;\n border-radius: 50%;\n border: 2px solid currentColor;\n flex-shrink: 0;\n}\n.mellon-btn-pill .mellon-btn-pill-icon-circle .mellon-btn-icon {\n width: 0.85em;\n height: 0.85em;\n}\n@media (prefers-reduced-motion: reduce) {\n .mellon-btn, .mellon-modal-wrapper { transition: none; }\n}\n`.trim();\n\n/** Evaluated at load. Browser-only SDK; would be false in SSR. */\nconst SUPPORTS_ADOPTED_STYLESHEETS =\n typeof ShadowRoot !== 'undefined' &&\n 'adoptedStyleSheets' in ShadowRoot.prototype &&\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype;\n\n/** Returns CSSStyleSheet for adoptedStyleSheets when supported; null otherwise (use <style> + textContent). */\nexport function createConstructableStylesheet(): CSSStyleSheet | null {\n if (!SUPPORTS_ADOPTED_STYLESHEETS) return null;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(BASE_STYLES);\n return sheet;\n } catch {\n return null;\n }\n}\n\n/** Returns CSS string for <style> textContent (fallback). */\nexport function getStylesFallback(): string {\n return BASE_STYLES;\n}\n\n/** Extra styles for trymellon-auth-modal: overlay, panel, tabs. */\nexport const MODAL_EXTRA_STYLES = `\n/* Host: full viewport when open, no border (only the inner panel has border). */\n:host {\n border: none;\n outline: none;\n}\n:host([open=\"true\"]) {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n pointer-events: none;\n}\n:host([open=\"true\"]) .mellon-modal-wrapper {\n pointer-events: auto;\n}\n/* Wrapper: fills host, no border. Overlay + panel are the only visible layers. */\n.mellon-modal-wrapper {\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border: none;\n outline: none;\n}\n/* Overlay: full viewport, transparent grey only (no border). */\n.mellon-modal-overlay {\n position: fixed;\n inset: 0;\n background: var(--mellon-overlay, rgba(0,0,0,0.5));\n z-index: 1;\n border: none;\n}\n/* Panel: vertical gap 2rem (top/bottom) so it doesn't sit flush with viewport edge; sides 1.5rem. Match landing font via --font-sans. */\n.mellon-modal-panel {\n position: fixed;\n inset: max(2rem, env(safe-area-inset-top)) max(1.5rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(1.5rem, env(safe-area-inset-left));\n margin: auto;\n z-index: 2;\n width: calc(100% - 3rem);\n max-width: 30rem;\n max-height: min(90vh, 34rem);\n overflow-y: auto;\n overflow-x: hidden;\n box-sizing: border-box;\n background: var(--mellon-surface);\n color: var(--mellon-text);\n font-family: var(--font-sans, var(--mellon-font-sans, inherit));\n border-radius: 12px;\n border: 1px solid var(--mellon-border);\n padding: var(--mellon-modal-panel-padding);\n box-shadow: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04);\n -webkit-overflow-scrolling: touch;\n}\n/* Close button: circular \"X\" in the top-right corner, aligned with panel padding. */\n.mellon-modal-close-btn {\n position: absolute;\n top: 0.75rem;\n right: 0.75rem;\n left: auto;\n bottom: auto;\n width: 2.25rem; /* 36px */\n height: 2.25rem; /* 36px */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 9999px;\n border: none;\n background: color-mix(in srgb, var(--mellon-surface) 80%, #000 20%);\n color: var(--mellon-text-muted);\n cursor: pointer;\n padding: 0;\n font-size: 1.1rem;\n line-height: 1;\n}\n.mellon-modal-close-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mellon-surface) 70%, #000 30%);\n color: var(--mellon-text);\n}\n.mellon-modal-close-btn:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n:host([theme=\"dark\"]) .mellon-modal-panel {\n box-shadow: 0 8px 24px -4px rgba(0,0,0,0.35), 0 4px 8px -4px rgba(0,0,0,0.2);\n}\n/* Dialog title and description: centered, with vertical breathing room. */\n.mellon-dialog-title,\n.mellon-dialog-desc {\n margin: 0 0 0.75rem;\n padding: 0;\n font-size: 1rem;\n line-height: 1.5;\n color: var(--mellon-text);\n text-align: center;\n}\n.mellon-dialog-title {\n font-weight: 600;\n font-size: 1.125rem;\n margin-top: 1.25rem;\n}\n.mellon-dialog-desc {\n color: var(--mellon-text-muted);\n font-size: 0.875rem;\n margin-bottom: 1rem;\n}\n/* Modal spacing scale: base 0.5rem (8px); sections 0.75–1rem; tight 0.25rem. */\n.mellon-modal-tabs {\n display: flex;\n gap: 0;\n padding: 0 0 0.75rem;\n border-bottom: none;\n}\n.mellon-modal-tabs button {\n flex: 1;\n min-height: 2.75rem;\n padding: 0.625rem 1rem;\n font-size: 0.875rem;\n font-weight: 400;\n background: transparent;\n color: var(--mellon-text-muted);\n border: none;\n border-bottom: 1px solid var(--mellon-border);\n cursor: pointer;\n}\n.mellon-modal-tabs button[aria-selected=\"true\"] {\n border-bottom-color: var(--mellon-primary);\n font-weight: 600;\n color: var(--mellon-text);\n}\n.mellon-modal-tabs button:hover {\n color: var(--mellon-text);\n}\n.mellon-modal-tabs button:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n/* Content wrapper: QR wrap → separator \"or\" → passkey; all centered with consistent vertical gap. */\n.mellon-modal-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5rem; /* 8px */\n}\n/* QR / cross-device area: centered; no min-height when empty to avoid extra space. */\n.mellon-cross-device-wrap {\n min-height: 11.25rem; /* 180px */\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n margin-top: 0.85rem; /* ~10% más margen con el top (tabs) */\n margin-bottom: 0.5rem; /* 8px */\n}\n/* Skeleton and error (modal-owned): visibility by data-qr-area-state. */\n.mellon-cross-device-skeleton,\n.mellon-cross-device-error {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mellon-cta-text-color);\n text-align: center;\n width: 11.25rem; /* 180px */\n height: 11.25rem; /* 180px */\n padding: 0 0.75rem; /* 0 12px */\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 0.75rem;\n border: 1px dashed var(--mellon-separator-line);\n box-sizing: border-box;\n background: var(--mellon-surface-elevated, rgba(128, 128, 128, 0.12));\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"default\"] .mellon-cross-device-error,\n.mellon-cross-device-wrap[data-qr-area-state=\"loaded\"] .mellon-cross-device-skeleton,\n.mellon-cross-device-wrap[data-qr-area-state=\"loaded\"] .mellon-cross-device-error {\n display: none;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"waiting\"] .mellon-cross-device-slot-wrap,\n.mellon-cross-device-wrap[data-qr-area-state=\"waiting\"] .mellon-cross-device-error {\n display: none;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"waiting\"] .mellon-cross-device-skeleton {\n display: flex;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"timeout\"] .mellon-cross-device-slot-wrap,\n.mellon-cross-device-wrap[data-qr-area-state=\"timeout\"] .mellon-cross-device-skeleton {\n display: none;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"timeout\"] .mellon-cross-device-error {\n display: flex;\n}\n.mellon-cross-device-slot-wrap {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 11.25rem; /* 180px */\n height: 11.25rem; /* 180px */\n}\n/* Default slot content: \"Try from another device\" (variable colour) + QR icon button; centered in column. */\n.mellon-cross-device-cta {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.75rem;\n width: fit-content;\n max-width: 100%;\n margin-top: 0.5rem;\n margin-left: auto;\n margin-right: auto;\n}\n.mellon-cross-device-cta-text {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mellon-cta-text-color);\n}\n.mellon-cross-device-cta .mellon-btn-qr-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 48px;\n min-height: 48px;\n padding: 0.5rem;\n background: var(--mellon-qr-btn-bg);\n color: var(--mellon-qr-btn-color);\n border: 1px solid var(--mellon-qr-btn-border);\n border-radius: var(--mellon-radius);\n cursor: pointer;\n}\n.mellon-cross-device-cta .mellon-btn-qr-icon:hover:not(:disabled) {\n background: var(--mellon-separator-line);\n}\n.mellon-cross-device-cta .mellon-btn-qr-icon:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n.mellon-qr-icon {\n width: 1.75rem;\n height: 1.75rem;\n}\n/* Separator: standard UI divider — line | \"or\" | line (all colours via variables). ~15% más margen con el bloque de arriba. */\n.mellon-modal-separator {\n display: flex;\n align-items: center;\n gap: 1rem;\n width: 100%;\n margin-top: 0.875rem; /* 0.75rem + ~15% */\n margin-bottom: 0;\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mellon-separator-text);\n}\n.mellon-modal-separator::before,\n.mellon-modal-separator::after {\n content: '';\n flex: 1;\n min-width: 0;\n height: 0;\n border-bottom: 1px solid var(--mellon-separator-line);\n}\n.mellon-modal-separator .mellon-separator-text {\n text-transform: uppercase;\n letter-spacing: 0.08em;\n font-size: 0.75rem;\n flex-shrink: 0;\n position: relative;\n padding: 0.375rem 1.25rem;\n background: transparent;\n z-index: 0;\n}\n.mellon-modal-separator .mellon-separator-text::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n width: 140%;\n height: 220%;\n transform: translate(-50%, -50%) rotate(45deg);\n border-radius: 0.35rem;\n border: 2px solid var(--mellon-separator-line);\n background: color-mix(in srgb, var(--mellon-surface) 80%, var(--mellon-text) 20%);\n z-index: -1;\n}\n/* Passkey slot/root centered in content wrapper. Less space between separator and this block. */\n.mellon-modal-separator + .mellon-root {\n margin-top: -0.25rem;\n}\n.mellon-modal-content .mellon-root {\n display: flex;\n justify-content: center;\n width: 100%;\n}\n/* QR skeleton loading dots: \"Loading QRs\" + animated trailing dots while waiting. */\n.mellon-qr-dots {\n display: inline-block;\n width: 1.5em;\n text-align: left;\n overflow: hidden;\n}\n.mellon-qr-dots::after {\n content: '...';\n display: inline-block;\n animation: mellon-qr-dots 1s steps(4, end) infinite;\n}\n@keyframes mellon-qr-dots {\n 0% {\n clip-path: inset(0 100% 0 0);\n }\n 33% {\n clip-path: inset(0 66% 0 0);\n }\n 66% {\n clip-path: inset(0 33% 0 0);\n }\n 100% {\n clip-path: inset(0 0 0 0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .mellon-qr-dots::after {\n animation: none;\n }\n}\n/* Minimal variant: transparent black, white border, same as landing (auth.styles modalContent) */\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-panel {\n border-radius: 1rem;\n border-width: 2px;\n border-style: solid;\n}\n:host([theme=\"dark\"]) [data-mellon-modal-variant=\"minimal\"] {\n --mellon-border: rgba(255, 255, 255, 0.9);\n}\n:host([theme=\"light\"]) [data-mellon-modal-variant=\"minimal\"] {\n --mellon-border: rgba(0, 0, 0, 0.15);\n}\n:host([theme=\"dark\"]) [data-mellon-modal-variant=\"minimal\"] .mellon-modal-panel {\n background: rgba(0, 0, 0, 0.88);\n}\n:host([theme=\"light\"]) [data-mellon-modal-variant=\"minimal\"] .mellon-modal-panel {\n background: rgba(255, 255, 255, 0.95);\n}\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-tabs {\n padding: 0.5rem 1rem 0;\n border-bottom-width: 2px;\n}\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-tabs button {\n padding: 0.4rem 0.6rem;\n font-size: 0.8125rem;\n}\n/* Responsive: narrow viewports — minimum padding so 5% does not get too small. */\n@media (max-width: 22.5rem) {\n .mellon-modal-panel {\n --mellon-modal-panel-padding: max(1rem, 5%);\n }\n .mellon-modal-tabs {\n padding: 0.75rem 0;\n }\n .mellon-modal-tabs button {\n padding: 0.625rem 0.75rem;\n }\n .mellon-modal-content {\n gap: 0.75rem;\n }\n}\n/* Responsive: very short viewport (e.g. landscape) — ensure panel scrolls. */\n@media (max-height: 400px) {\n .mellon-modal-panel {\n max-height: calc(100dvh - 4rem);\n }\n}\n`.trim();\n\n/** Returns BASE_STYLES + MODAL_EXTRA_STYLES for modal WC. */\nexport function getModalStylesFallback(): string {\n return BASE_STYLES + '\\n' + MODAL_EXTRA_STYLES;\n}\n\n/** Constructable stylesheet for modal (base + overlay/panel/tabs). */\nexport function createModalConstructableStylesheet(): CSSStyleSheet | null {\n if (!SUPPORTS_ADOPTED_STYLESHEETS) return null;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(BASE_STYLES + '\\n' + MODAL_EXTRA_STYLES);\n return sheet;\n } catch {\n return null;\n }\n}\n","export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport function map<T, E, U>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E> {\n if (result.ok) {\n return ok(mapper(result.value));\n }\n return result;\n}\n\nexport function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F> {\n if (!result.ok) {\n return err(mapper(result.error));\n }\n return result;\n}\n\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (result.ok) {\n return result.value;\n }\n throw result.error;\n}\n","export type TryMellonErrorCode =\n | 'NOT_SUPPORTED'\n | 'USER_CANCELLED'\n | 'PASSKEY_NOT_FOUND'\n | 'SESSION_EXPIRED'\n | 'NETWORK_FAILURE'\n | 'INVALID_ARGUMENT'\n | 'TIMEOUT'\n | 'ABORTED'\n | 'ABORT_ERROR'\n | 'CHALLENGE_MISMATCH'\n | 'UNKNOWN_ERROR';\n\nexport class TryMellonError extends Error {\n readonly code: TryMellonErrorCode;\n readonly details?: unknown;\n readonly isTryMellonError = true;\n\n constructor(code: TryMellonErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TryMellonError';\n this.code = code;\n this.details = details;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TryMellonError);\n }\n }\n}\n\nconst DEFAULT_MESSAGES: Record<TryMellonErrorCode, string> = {\n NOT_SUPPORTED: 'WebAuthn is not supported in this environment',\n USER_CANCELLED: 'User cancelled the operation',\n PASSKEY_NOT_FOUND: 'Passkey not found',\n SESSION_EXPIRED: 'Session has expired',\n NETWORK_FAILURE: 'Network request failed',\n INVALID_ARGUMENT: 'Invalid argument provided',\n TIMEOUT: 'Operation timed out',\n ABORTED: 'Operation was aborted',\n ABORT_ERROR: 'Operation aborted by user or timeout',\n CHALLENGE_MISMATCH: 'This link was already used or expired. Please try again from your computer.',\n UNKNOWN_ERROR: 'An unknown error occurred',\n};\n\nexport function createError(\n code: TryMellonErrorCode,\n message?: string,\n details?: unknown\n): TryMellonError {\n return new TryMellonError(code, message ?? DEFAULT_MESSAGES[code], details);\n}\n\nexport function isTryMellonError(error: unknown): error is TryMellonError {\n return (\n error instanceof TryMellonError ||\n (typeof error === 'object' &&\n error !== null &&\n 'isTryMellonError' in error &&\n (error as TryMellonError).isTryMellonError === true)\n );\n}\n\nexport function createNotSupportedError(): TryMellonError {\n return createError('NOT_SUPPORTED');\n}\n\nexport function createUserCancelledError(): TryMellonError {\n return createError('USER_CANCELLED');\n}\n\nexport function createNetworkError(cause?: Error): TryMellonError {\n return createError('NETWORK_FAILURE', undefined, {\n cause: cause?.message,\n originalError: cause,\n });\n}\n\nexport function createTimeoutError(): TryMellonError {\n return createError('TIMEOUT');\n}\n\nexport function createInvalidArgumentError(field: string, reason: string): TryMellonError {\n return createError('INVALID_ARGUMENT', `Invalid argument: ${field} - ${reason}`, {\n field,\n reason,\n });\n}\n\nexport function createCredentialError(operation: 'create' | 'get'): TryMellonError {\n return createError('UNKNOWN_ERROR', `Failed to ${operation} credential`, { operation });\n}\n\nexport function createEncodingError(type: 'encode' | 'decode'): TryMellonError {\n return createError(\n 'NOT_SUPPORTED',\n `No base64 ${type === 'encode' ? 'encoding' : 'decoding'} available`,\n { type }\n );\n}\n\nexport function validateNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (!value || typeof value !== 'string' || value.trim() === '') {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n}\n\nexport function validateUrl(url: string, fieldName: string): void {\n try {\n const urlObj = new URL(url);\n if (urlObj.protocol !== 'https:' && urlObj.protocol !== 'http:') {\n throw createInvalidArgumentError(fieldName, 'must use http or https protocol');\n }\n } catch (error) {\n if (isTryMellonError(error)) {\n throw error;\n }\n throw createInvalidArgumentError(fieldName, 'must be a valid URL');\n }\n}\n\nexport function validateRange(value: number, fieldName: string, min: number, max: number): void {\n if (!Number.isFinite(value)) {\n throw createInvalidArgumentError(fieldName, 'must be a finite number');\n }\n if (value < min || value > max) {\n throw createInvalidArgumentError(fieldName, `must be between ${min} and ${max}`);\n }\n}\n\nexport function validateBase64Url(s: string, fieldName: string): void {\n if (typeof s !== 'string' || s.length === 0) {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n if (!/^[A-Za-z0-9_-]+$/.test(s)) {\n throw createInvalidArgumentError(fieldName, 'must be a valid base64url string');\n }\n}\n\nconst DOM_EXCEPTION_ERROR_MAP: Record<string, TryMellonErrorCode> = {\n NotAllowedError: 'USER_CANCELLED',\n AbortError: 'ABORTED',\n NotSupportedError: 'NOT_SUPPORTED',\n SecurityError: 'NOT_SUPPORTED',\n InvalidStateError: 'UNKNOWN_ERROR',\n UnknownError: 'UNKNOWN_ERROR',\n};\n\n/**\n * Maps backend API error codes (fintech envelope) to TryMellonErrorCode.\n * Pure, testable. Unknown codes map to UNKNOWN_ERROR.\n * Defensive: non-string input returns UNKNOWN_ERROR (no throw).\n */\nexport function mapBackendErrorCodeToTryMellon(backendCode: string): TryMellonErrorCode {\n if (typeof backendCode !== 'string') return 'UNKNOWN_ERROR';\n const normalized = backendCode.toLowerCase().trim();\n const map: Record<string, TryMellonErrorCode> = {\n challenge_mismatch: 'CHALLENGE_MISMATCH',\n session_expired: 'SESSION_EXPIRED',\n unauthorized: 'SESSION_EXPIRED',\n validation_error: 'INVALID_ARGUMENT',\n invalid_argument: 'INVALID_ARGUMENT',\n user_not_found: 'SESSION_EXPIRED',\n passkey_not_found: 'PASSKEY_NOT_FOUND',\n };\n return map[normalized] ?? 'UNKNOWN_ERROR';\n}\n\nexport function mapWebAuthnError(error: unknown): TryMellonError {\n if (error instanceof DOMException) {\n const name = error.name;\n const message = error.message || 'WebAuthn operation failed';\n const errorCode = DOM_EXCEPTION_ERROR_MAP[name] ?? 'UNKNOWN_ERROR';\n return createError(errorCode, message, { originalError: error });\n }\n\n if (error instanceof Error) {\n return createError('UNKNOWN_ERROR', error.message, { originalError: error });\n }\n\n return createError('UNKNOWN_ERROR', 'An unknown error occurred', {\n originalError: error,\n });\n}\n","import { err, ok, type Result } from '../../utils/result';\nimport { createError, type TryMellonError } from '../../errors';\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nexport function validationError(\n message: string,\n details?: { field?: string; expected?: string; originalData?: unknown }\n): Result<never, TryMellonError> {\n return err(\n createError('UNKNOWN_ERROR', message, {\n ...details,\n originalData: details?.originalData,\n })\n );\n}\n\nexport function required(obj: Record<string, unknown>, key: string): unknown {\n return obj[key];\n}\n\nexport function optionalString(obj: Record<string, unknown>, key: string): string | undefined {\n const v = obj[key];\n return v === undefined ? undefined : typeof v === 'string' ? v : undefined;\n}\n\n// DRY Helpers for common TryMellon objects\n\nexport function validateChallengeRP(rp: unknown, data: unknown): Result<true, TryMellonError> {\n if (!isObject(rp) || !isString(rp.name) || !isString(rp.id)) {\n return validationError('Invalid API response: challenge.rp must have name and id strings', {\n originalData: data,\n });\n }\n return ok(true);\n}\n\nexport function validateChallengeUser(user: unknown, data: unknown): Result<true, TryMellonError> {\n if (\n !isObject(user) ||\n !isString(user.id) ||\n !isString(user.name) ||\n !isString(user.displayName)\n ) {\n return validationError(\n 'Invalid API response: challenge.user must have id, name, displayName strings',\n { originalData: data }\n );\n }\n return ok(true);\n}\n\nexport function validatePubKeyCredParams(\n params: unknown,\n data: unknown\n): Result<true, TryMellonError> {\n if (!isArray(params)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of params) {\n if (!isObject(item) || item.type !== 'public-key' || !isNumber(item.alg)) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n { originalData: data }\n );\n }\n }\n return ok(true);\n}\n\nexport function validateUserEntity(\n user: unknown,\n data: unknown\n): Result<\n { user_id: string; external_user_id: string; email?: string; metadata?: Record<string, unknown> },\n TryMellonError\n> {\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const userId = required(user, 'user_id');\n const externalUserId = required(user, 'external_user_id');\n if (!isString(userId) || !isString(externalUserId)) {\n return validationError(\n 'Invalid API response: user must have user_id and external_user_id strings',\n { originalData: data }\n );\n }\n\n const email = user.email;\n const metadata = user.metadata;\n if (email !== undefined && !isString(email)) {\n return validationError('Invalid API response: user.email must be string', {\n originalData: data,\n });\n }\n if (metadata !== undefined && (typeof metadata !== 'object' || metadata === null)) {\n return validationError('Invalid API response: user.metadata must be object', {\n originalData: data,\n });\n }\n\n return ok({\n user_id: userId,\n external_user_id: externalUserId,\n ...(email !== undefined && { email }),\n ...(metadata !== undefined && { metadata: metadata as Record<string, unknown> }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n RegisterStartResponse,\n AuthStartResponse,\n RegisterFinishResponse,\n AuthFinishResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport {\n isObject,\n isString,\n isNumber,\n isBoolean,\n isArray,\n validationError,\n required,\n validateChallengeRP,\n validateChallengeUser,\n validatePubKeyCredParams,\n validateUserEntity,\n} from './helpers';\n\nexport function validateRegisterStartResponse(\n data: unknown\n): Result<RegisterStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const rpResult = validateChallengeRP(required(challenge, 'rp'), data);\n if (!rpResult.ok) return rpResult;\n\n const userResult = validateChallengeUser(required(challenge, 'user'), data);\n if (!userResult.ok) return userResult;\n\n const challengeStr = required(challenge, 'challenge');\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n\n const pubKeyCredParamsResult = validatePubKeyCredParams(\n required(challenge, 'pubKeyCredParams'),\n data\n );\n if (!pubKeyCredParamsResult.ok) return pubKeyCredParamsResult;\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const excludeCredentials = challenge.excludeCredentials;\n if (excludeCredentials !== undefined) {\n if (!isArray(excludeCredentials)) {\n return validationError('Invalid API response: excludeCredentials must be array', {\n originalData: data,\n });\n }\n for (const c of excludeCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: excludeCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const authenticatorSelection = challenge.authenticatorSelection;\n if (authenticatorSelection !== undefined && !isObject(authenticatorSelection)) {\n return validationError('Invalid API response: authenticatorSelection must be object', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n challenge: {\n rp: challenge.rp as RegisterStartResponse['challenge']['rp'],\n user: challenge.user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams:\n challenge.pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n ...(timeout !== undefined && { timeout }),\n ...(excludeCredentials !== undefined && {\n excludeCredentials:\n excludeCredentials as RegisterStartResponse['challenge']['excludeCredentials'],\n }),\n ...(authenticatorSelection !== undefined && {\n authenticatorSelection:\n authenticatorSelection as RegisterStartResponse['challenge']['authenticatorSelection'],\n }),\n },\n });\n}\n\nexport function validateAuthStartResponse(\n data: unknown\n): Result<AuthStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const ch = required(challenge, 'challenge');\n const rpId = required(challenge, 'rpId');\n const allowCredentials = challenge.allowCredentials;\n if (!isString(ch)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isString(rpId)) {\n return validationError('Invalid API response: challenge.rpId must be string', {\n originalData: data,\n });\n }\n if (allowCredentials !== undefined && !isArray(allowCredentials)) {\n return validationError('Invalid API response: allowCredentials must be array', {\n originalData: data,\n });\n }\n if (allowCredentials) {\n for (const c of allowCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: allowCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const userVerification = challenge.userVerification;\n if (\n userVerification !== undefined &&\n !['required', 'preferred', 'discouraged'].includes(String(userVerification))\n ) {\n return validationError(\n 'Invalid API response: userVerification must be required|preferred|discouraged',\n {\n originalData: data,\n }\n );\n }\n\n return ok({\n session_id,\n challenge: {\n challenge: ch,\n rpId,\n allowCredentials:\n (allowCredentials as AuthStartResponse['challenge']['allowCredentials']) ?? [],\n ...(timeout !== undefined && { timeout }),\n ...(userVerification !== undefined && {\n userVerification: userVerification as AuthStartResponse['challenge']['userVerification'],\n }),\n },\n });\n}\n\nexport function validateRegisterFinishResponse(\n data: unknown\n): Result<RegisterFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const credential_id = required(data, 'credential_id');\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n const redirect_url = data.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n credential_id,\n status,\n session_token,\n user: userResult.value,\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n\nexport function validateAuthFinishResponse(\n data: unknown\n): Result<AuthFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const authenticated = required(data, 'authenticated');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const signals = required(data, 'signals');\n\n if (!isBoolean(authenticated)) {\n return validationError('Invalid API response: authenticated must be boolean', {\n field: 'authenticated',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n if (signals !== undefined && !isObject(signals)) {\n return validationError('Invalid API response: signals must be object', {\n originalData: data,\n });\n }\n\n const redirect_url = data.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n authenticated,\n session_token,\n user: userResult.value,\n signals: signals as AuthFinishResponse['signals'],\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { SessionValidateResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isBoolean, required, validationError } from './helpers';\n\nexport function validateSessionValidateResponse(\n data: unknown\n): Result<SessionValidateResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const valid = required(data, 'valid');\n const user_id = required(data, 'user_id');\n const external_user_id = required(data, 'external_user_id');\n const tenant_id = required(data, 'tenant_id');\n const app_id = required(data, 'app_id');\n\n if (!isBoolean(valid)) {\n return validationError('Invalid API response: valid must be boolean', {\n field: 'valid',\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n field: 'user_id',\n originalData: data,\n });\n }\n if (!isString(external_user_id)) {\n return validationError('Invalid API response: external_user_id must be string', {\n field: 'external_user_id',\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n field: 'tenant_id',\n originalData: data,\n });\n }\n if (!isString(app_id)) {\n return validationError('Invalid API response: app_id must be string', {\n field: 'app_id',\n originalData: data,\n });\n }\n\n return ok({\n valid,\n user_id,\n external_user_id,\n tenant_id,\n app_id,\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\n\nexport function validateEmailVerifyResponse(\n data: unknown\n): Result<{ sessionToken: string; redirectUrl?: string }, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const raw =\n (data as Record<string, unknown>).session_token ??\n (data as Record<string, unknown>).sessionToken;\n if (!isString(raw)) {\n return validationError('Invalid API response: session_token/sessionToken must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n const redirect_url = (data as Record<string, unknown>).redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n sessionToken: raw,\n ...(redirect_url !== undefined && { redirectUrl: redirect_url }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterResponse,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteResponse,\n RegisterStartResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isNumber, isArray, required, validationError } from './helpers';\n\nconst ONBOARDING_STATUSES = ['pending_passkey', 'pending_data', 'completed'] as const;\nconst REGISTER_PASSKEY_STATUSES = ['pending_data', 'completed'] as const;\n\nexport function validateOnboardingStartResponse(\n data: unknown\n): Result<OnboardingStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n field: 'onboarding_url',\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n field: 'expires_in',\n originalData: data,\n });\n }\n\n return ok({ session_id, onboarding_url, expires_in });\n}\n\nexport function validateOnboardingStatusResponse(\n data: unknown\n): Result<OnboardingStatusResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (\n !isString(status) ||\n !ONBOARDING_STATUSES.includes(status as (typeof ONBOARDING_STATUSES)[number])\n ) {\n return validationError(\n 'Invalid API response: status must be pending_passkey|pending_data|completed',\n {\n field: 'status',\n originalData: data,\n }\n );\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as OnboardingStatusResponse['status'],\n onboarding_url,\n expires_in,\n });\n}\n\n/** Response may include optional challenge for same-device passkey registration */\nexport type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {\n challenge?: RegisterStartResponse['challenge'];\n};\n\nexport function validateOnboardingRegisterResponse(\n data: unknown\n): Result<OnboardingRegisterResponseWithChallenge, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (status !== 'pending_passkey') {\n return validationError('Invalid API response: status must be pending_passkey', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n\n const challenge = data.challenge;\n let parsedChallenge: RegisterStartResponse['challenge'] | undefined;\n if (challenge !== undefined) {\n const chResult = validateOnboardingChallenge(challenge);\n if (!chResult.ok) return chResult;\n parsedChallenge = chResult.value;\n }\n\n return ok({\n session_id,\n status: 'pending_passkey',\n onboarding_url,\n ...(parsedChallenge !== undefined && { challenge: parsedChallenge }),\n });\n}\n\nfunction validateOnboardingChallenge(\n data: unknown\n): Result<RegisterStartResponse['challenge'], TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: challenge must be object', {\n originalData: data,\n });\n }\n\n const rp = required(data, 'rp');\n const user = required(data, 'user');\n const challengeStr = required(data, 'challenge');\n const pubKeyCredParams = required(data, 'pubKeyCredParams');\n\n if (\n !isObject(rp) ||\n !isString((rp as Record<string, unknown>).name) ||\n !isString((rp as Record<string, unknown>).id)\n ) {\n return validationError('Invalid API response: challenge.rp must have name and id', {\n originalData: data,\n });\n }\n if (\n !isObject(user) ||\n !isString((user as Record<string, unknown>).id) ||\n !isString((user as Record<string, unknown>).name) ||\n !isString((user as Record<string, unknown>).displayName)\n ) {\n return validationError('Invalid API response: challenge.user must have id, name, displayName', {\n originalData: data,\n });\n }\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isArray(pubKeyCredParams)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of pubKeyCredParams) {\n if (\n !isObject(item) ||\n (item as Record<string, unknown>).type !== 'public-key' ||\n !isNumber((item as Record<string, unknown>).alg)\n ) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n {\n originalData: data,\n }\n );\n }\n }\n\n return ok({\n rp: rp as RegisterStartResponse['challenge']['rp'],\n user: user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams: pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n });\n}\n\nexport function validateOnboardingRegisterPasskeyResponse(\n data: unknown\n): Result<OnboardingRegisterPasskeyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (\n !isString(status) ||\n !REGISTER_PASSKEY_STATUSES.includes(status as (typeof REGISTER_PASSKEY_STATUSES)[number])\n ) {\n return validationError('Invalid API response: status must be pending_data|completed', {\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n status: status as OnboardingRegisterPasskeyResponse['status'],\n user_id,\n tenant_id,\n });\n}\n\nexport function validateOnboardingCompleteResponse(\n data: unknown\n): Result<OnboardingCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n const session_token = required(data, 'session_token');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (status !== 'completed') {\n return validationError('Invalid API response: status must be completed', {\n originalData: data,\n });\n }\n if (!isString(user_id) || !isString(tenant_id) || !isString(session_token)) {\n return validationError(\n 'Invalid API response: user_id, tenant_id, session_token must be strings',\n { originalData: data }\n );\n }\n\n return ok({\n session_id,\n status: 'completed',\n user_id,\n tenant_id,\n session_token,\n });\n}\n","import { ok } from '../../utils/result';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n} from '../../types';\n\n/**\n * Validates the response for cross-device verify and verify-registration endpoints.\n * Backend returns 204 No Content; body may be undefined, null, or empty object.\n * Accepts only those; rejects any other shape to detect unexpected API responses.\n */\nexport function validateCrossDeviceVerifyResponse(data: unknown): Result<void, TryMellonError> {\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n if (isObject(data) && Object.keys(data).length === 0) {\n return ok(undefined);\n }\n return validationError('Invalid API response: expected empty body (204)', {\n originalData: data,\n });\n}\n\nfunction isCreationOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return (\n typeof o.challenge === 'string' &&\n o.rp != null &&\n typeof o.rp === 'object' &&\n o.user != null &&\n typeof o.user === 'object' &&\n Array.isArray((o as { pubKeyCredParams?: unknown }).pubKeyCredParams)\n );\n}\n\nfunction isRequestOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return typeof o.challenge === 'string' && typeof o.rpId === 'string';\n}\n\n/**\n * Accepts either the unwrapped payload { session_id, qr_url, expires_at } or the fintech\n * envelope { ok: true, resultado: { session_id, qr_url, expires_at } } so the flow works\n * regardless of whether the fetch-client unwraps before calling this validator.\n */\nexport function validateCrossDeviceInitResponse(\n data: unknown\n): Result<CrossDeviceInitResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const payload =\n 'resultado' in data && isObject((data as { resultado: unknown }).resultado)\n ? (data as { resultado: Record<string, unknown> }).resultado\n : data;\n\n const session_id = payload.session_id;\n const qr_url = payload.qr_url;\n const expires_at = payload.expires_at;\n const polling_token = payload.polling_token;\n\n if (\n !isString(session_id) ||\n !isString(qr_url) ||\n !isString(expires_at) ||\n !isString(polling_token)\n ) {\n return validationError('Invalid API response: missing required fields', { originalData: data });\n }\n\n const result: CrossDeviceInitResult = {\n session_id,\n qr_url,\n expires_at,\n polling_token,\n };\n if (payload.external_user_id !== undefined && isString(payload.external_user_id)) {\n result.external_user_id = payload.external_user_id;\n }\n return ok(result);\n}\n\n/**\n * Accepts either the unwrapped payload { status, user_id?, session_token?, redirect_url? } or the\n * fintech envelope { ok: true, resultado: { ... } } so the flow works regardless of unwrapping.\n */\nexport function validateCrossDeviceStatusResponse(\n data: unknown\n): Result<CrossDeviceStatusResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const payload =\n 'resultado' in data && isObject((data as { resultado: unknown }).resultado)\n ? (data as { resultado: Record<string, unknown> }).resultado\n : data;\n\n const status = payload.status;\n if (!isString(status) || !['pending', 'authenticated', 'completed'].includes(status)) {\n return validationError('Invalid API response: invalid status', { originalData: data });\n }\n\n const user_id = payload.user_id;\n const session_token = payload.session_token;\n const redirect_url = payload.redirect_url;\n\n if (user_id !== undefined && !isString(user_id)) {\n return validationError('Invalid API response: user_id must be a string when present', {\n originalData: data,\n });\n }\n if (session_token !== undefined && !isString(session_token)) {\n return validationError('Invalid API response: session_token must be a string when present', {\n originalData: data,\n });\n }\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be a string when present', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as CrossDeviceStatusResult['status'],\n user_id: user_id as string | undefined,\n session_token: session_token as string | undefined,\n redirect_url: redirect_url as string | undefined,\n });\n}\n\nexport function validateCrossDeviceContextResponse(\n data: unknown\n): Result<CrossDeviceContextResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const rawType = data.type;\n const type =\n rawType === 'registration' ? 'registration' : rawType === 'auth' ? 'auth' : ('auth' as const);\n\n const options = data.options;\n if (!isObject(options)) {\n return validationError('Invalid API response: options are required', { originalData: data });\n }\n\n const MAX_CONTEXT_LENGTH = 200;\n const approval_context = optionalContextString(data.approval_context, MAX_CONTEXT_LENGTH);\n const application_name = optionalContextString(data.application_name, MAX_CONTEXT_LENGTH);\n if (approval_context === false || application_name === false) {\n return validationError(\n 'Invalid API response: approval_context/application_name must be string max 200 chars',\n {\n originalData: data,\n }\n );\n }\n\n const extra: { approval_context?: string; application_name?: string } = {};\n if (typeof approval_context === 'string') extra.approval_context = approval_context;\n if (typeof application_name === 'string') extra.application_name = application_name;\n\n if (type === 'registration') {\n if (!isCreationOptionsShape(options)) {\n return validationError(\n 'Invalid API response: registration options must have challenge, rp, user, pubKeyCredParams',\n { originalData: data }\n );\n }\n return ok({\n type: 'registration',\n options,\n ...extra,\n } as CrossDeviceContextResult);\n }\n\n if (!isRequestOptionsShape(options)) {\n return validationError('Invalid API response: auth options must have challenge and rpId', {\n originalData: data,\n });\n }\n return ok({ type: 'auth', options, ...extra } as CrossDeviceContextResult);\n}\n\n/** Returns string if valid (optional, max len), undefined if missing, false if invalid. */\nfunction optionalContextString(value: unknown, maxLength: number): string | undefined | false {\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') return false;\n if (value.length > maxLength) return false;\n return value;\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { RecoveryVerifyResponse, RecoveryCompleteResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateRecoveryVerifyResponse(\n data: unknown\n): Result<RecoveryVerifyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const challenge = required(data, 'challenge');\n const recovery_session_id = required(data, 'recovery_session_id');\n\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n if (!isString(recovery_session_id)) {\n return validationError('Invalid API response: recovery_session_id must be string', {\n field: 'recovery_session_id',\n originalData: data,\n });\n }\n\n return ok({\n challenge: challenge as Record<string, unknown>,\n recovery_session_id,\n });\n}\n\nexport function validateRecoveryCompleteResponse(\n data: unknown\n): Result<RecoveryCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const credential_id = required(data, 'credential_id');\n\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const user_id = required(user, 'user_id');\n if (!isString(user_id)) {\n return validationError('Invalid API response: user.user_id must be string', {\n field: 'user.user_id',\n originalData: data,\n });\n }\n\n const dataObj = data as Record<string, unknown>;\n const redirect_url = dataObj.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n field: 'redirect_url',\n originalData: data,\n });\n }\n\n const userObj = user as Record<string, unknown>;\n return ok({\n status,\n session_token,\n credential_id,\n user: {\n user_id,\n external_user_id: isString(userObj.external_user_id) ? userObj.external_user_id : undefined,\n email: isString(userObj.email) ? userObj.email : undefined,\n metadata: isObject(userObj.metadata)\n ? (userObj.metadata as Record<string, unknown>)\n : undefined,\n },\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n","import type { HttpClient } from './http-client';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport {\n validateRegisterStartResponse,\n validateAuthStartResponse,\n validateRegisterFinishResponse,\n validateAuthFinishResponse,\n validateSessionValidateResponse,\n validateEmailVerifyResponse,\n validateOnboardingStartResponse,\n validateOnboardingStatusResponse,\n validateOnboardingRegisterResponse,\n validateOnboardingRegisterPasskeyResponse,\n validateOnboardingCompleteResponse,\n validateCrossDeviceInitResponse,\n validateCrossDeviceStatusResponse,\n validateCrossDeviceContextResponse,\n validateCrossDeviceVerifyResponse,\n validateRecoveryVerifyResponse,\n validateRecoveryCompleteResponse,\n} from './validators';\nimport type {\n RegisterStartRequest,\n RegisterStartResponse,\n AuthStartRequest,\n AuthStartResponse,\n RegisterFinishRequest,\n RegisterFinishResponse,\n AuthFinishRequest,\n AuthFinishResponse,\n SessionValidateResponse,\n OnboardingStartRequest,\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterPasskeyRequest,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteRequest,\n OnboardingCompleteResponse,\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n CrossDeviceVerifyRequest,\n CrossDeviceVerifyRegistrationRequest,\n RecoveryVerifyResponse,\n RecoveryCompleteResponse,\n} from '../types';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nexport class ApiClient {\n constructor(\n private readonly httpClient: HttpClient,\n private readonly baseUrl: string,\n private readonly defaultHeaders: Record<string, string> = {}\n ) {}\n\n private mergeHeaders(extra?: Record<string, string>): Record<string, string> {\n return { ...this.defaultHeaders, ...extra };\n }\n\n private async post<Req, Res>(\n path: string,\n body: Req,\n validate: (data: unknown) => Result<Res, TryMellonError>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.post<unknown>(url, body, this.mergeHeaders());\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n private async get<Res>(\n path: string,\n validate: (data: unknown) => Result<Res, TryMellonError>,\n headers?: Record<string, string>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.get<unknown>(url, this.mergeHeaders(headers));\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n async startRegister(\n request: RegisterStartRequest\n ): Promise<Result<RegisterStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/start', request, validateRegisterStartResponse);\n }\n\n async startAuth(request: AuthStartRequest): Promise<Result<AuthStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/start', request, validateAuthStartResponse);\n }\n\n async finishRegister(\n request: RegisterFinishRequest\n ): Promise<Result<RegisterFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/finish', request, validateRegisterFinishResponse);\n }\n\n async finishAuthentication(\n request: AuthFinishRequest\n ): Promise<Result<AuthFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/finish', request, validateAuthFinishResponse);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n return this.get('/v1/sessions/validate', validateSessionValidateResponse, {\n Authorization: `Bearer ${sessionToken}`,\n });\n }\n\n async startEmailFallback(options: {\n userId: string;\n email: string;\n }): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/fallback/email/start`;\n const result = await this.httpClient.post<unknown>(\n url,\n { userId: options.userId, email: options.email },\n this.mergeHeaders()\n );\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyEmailCode(options: {\n userId: string;\n code: string;\n successUrl?: string;\n }): Promise<Result<{ sessionToken: string; redirectUrl?: string }, TryMellonError>> {\n const body: Record<string, unknown> = { userId: options.userId, code: options.code };\n if (options.successUrl) body.success_url = options.successUrl;\n return this.post('/v1/fallback/email/verify', body, validateEmailVerifyResponse);\n }\n\n async startOnboarding(\n request: OnboardingStartRequest\n ): Promise<Result<OnboardingStartResponse, TryMellonError>> {\n return this.post('/v1/onboarding/start', request, validateOnboardingStartResponse);\n }\n\n async getOnboardingStatus(\n sessionId: string\n ): Promise<Result<OnboardingStatusResponse, TryMellonError>> {\n return this.get(`/v1/onboarding/${sessionId}/status`, validateOnboardingStatusResponse);\n }\n\n async getOnboardingRegister(\n sessionId: string\n ): Promise<Result<OnboardingRegisterResponseWithChallenge, TryMellonError>> {\n return this.get(`/v1/onboarding/${sessionId}/register`, validateOnboardingRegisterResponse);\n }\n\n async registerOnboardingPasskey(\n sessionId: string,\n request: OnboardingRegisterPasskeyRequest\n ): Promise<Result<OnboardingRegisterPasskeyResponse, TryMellonError>> {\n return this.post(\n `/v1/onboarding/${sessionId}/register-passkey`,\n request,\n validateOnboardingRegisterPasskeyResponse\n );\n }\n\n async completeOnboarding(\n sessionId: string,\n request: OnboardingCompleteRequest\n ): Promise<Result<OnboardingCompleteResponse, TryMellonError>> {\n return this.post(\n `/v1/onboarding/${sessionId}/complete`,\n request,\n validateOnboardingCompleteResponse\n );\n }\n\n async initCrossDeviceAuth(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post('/v1/auth/cross-device/init', {}, validateCrossDeviceInitResponse);\n }\n\n async initCrossDeviceRegistration(options?: {\n externalUserId?: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n const trimmed =\n typeof options?.externalUserId === 'string' ? options.externalUserId.trim() : '';\n const body = trimmed.length > 0 ? { external_user_id: trimmed } : {};\n return this.post(\n '/v1/auth/cross-device/init-registration',\n body,\n validateCrossDeviceInitResponse\n );\n }\n\n async getCrossDeviceStatus(\n sessionId: string,\n pollingToken?: string | null\n ): Promise<Result<CrossDeviceStatusResult, TryMellonError>> {\n const headers: Record<string, string> = {};\n if (typeof pollingToken === 'string' && pollingToken.length > 0) {\n headers['X-Polling-Token'] = pollingToken;\n }\n return this.get(\n `/v1/auth/cross-device/status/${sessionId}`,\n validateCrossDeviceStatusResponse,\n Object.keys(headers).length > 0 ? headers : undefined\n );\n }\n\n /**\n * Fetches WebAuthn options for the cross-device session.\n * Contract: response is CrossDeviceContextResult (auth | registration).\n * Use result.value.type to branch: 'auth' → credentials.get + verify;\n * 'registration' → credentials.create + verify-registration.\n */\n async getCrossDeviceContext(\n sessionId: string\n ): Promise<Result<CrossDeviceContextResult, TryMellonError>> {\n return this.get(\n `/v1/auth/cross-device/context/${sessionId}`,\n validateCrossDeviceContextResponse\n );\n }\n\n async verifyCrossDeviceAuth(\n request: CrossDeviceVerifyRequest\n ): Promise<Result<void, TryMellonError>> {\n return this.post('/v1/auth/cross-device/verify', request, validateCrossDeviceVerifyResponse);\n }\n\n async verifyCrossDeviceRegistration(\n request: CrossDeviceVerifyRegistrationRequest\n ): Promise<Result<void, TryMellonError>> {\n return this.post(\n '/v1/auth/cross-device/verify-registration',\n request,\n validateCrossDeviceVerifyResponse\n );\n }\n\n async verifyAccountRecoveryOtp(\n externalUserId: string,\n otp: string\n ): Promise<Result<RecoveryVerifyResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/verify',\n { external_id: externalUserId, otp },\n validateRecoveryVerifyResponse\n );\n }\n\n async completeAccountRecovery(\n recoverySessionId: string,\n credential: Record<string, unknown>\n ): Promise<Result<RecoveryCompleteResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/complete',\n { recovery_session_id: recoverySessionId, credential },\n validateRecoveryCompleteResponse\n );\n }\n}\n","import type { HttpClient } from './http-client';\nimport type { Logger } from './ports/logger';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport {\n createError,\n mapBackendErrorCodeToTryMellon,\n type TryMellonError,\n type TryMellonErrorCode,\n} from '../errors';\n\n/** Fintech success envelope: { ok: true, resultado: T } */\nfunction isEnvelopeSuccess(data: unknown): data is { ok: true; resultado: unknown } {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as Record<string, unknown>).ok === true &&\n 'resultado' in (data as Record<string, unknown>)\n );\n}\n\n/** Fintech error envelope: { ok: false, error: { code, message } } */\nfunction isEnvelopeError(\n data: unknown\n): data is { ok: false; error: { code: string; message: string; details?: unknown } } {\n if (typeof data !== 'object' || data === null) return false;\n const o = data as Record<string, unknown>;\n if (o.ok !== false || !o.error || typeof o.error !== 'object') return false;\n const err = o.error as Record<string, unknown>;\n return typeof err.code === 'string' && typeof err.message === 'string';\n}\n\n/**\n * Pure function: parses HTTP error body (fintech envelope or fallbacks) into message and code.\n * Concentrates all error-body parsing in one place for testability and single responsibility.\n */\nexport function parseHttpErrorBody(\n errorData: unknown,\n statusText: string\n): { message: string; code: TryMellonErrorCode } {\n if (isEnvelopeError(errorData)) {\n return {\n message: errorData.error.message,\n code: mapBackendErrorCodeToTryMellon(errorData.error.code),\n };\n }\n const body = errorData as\n | { message?: string; error?: string | { code?: string; message?: string } }\n | undefined;\n const errObj = body?.error;\n if (\n typeof errObj === 'object' &&\n errObj !== null &&\n 'code' in errObj &&\n typeof (errObj as { code: string }).code === 'string'\n ) {\n return {\n message: (errObj as { message?: string }).message ?? body?.message ?? statusText,\n code: mapBackendErrorCodeToTryMellon((errObj as { code: string }).code),\n };\n }\n const message = body?.message ?? statusText;\n const rawCode = body?.error;\n const code =\n typeof rawCode === 'string'\n ? mapBackendErrorCodeToTryMellon(rawCode)\n : rawCode === undefined\n ? 'NETWORK_FAILURE'\n : mapBackendErrorCodeToTryMellon(String(rawCode));\n return { message, code };\n}\n\nconst RETRY_DELAY_CAP_MS = 30_000;\n\n/**\n * Generates a unique request ID. Uses globalThis.crypto.randomUUID only (Elite: no Node crypto).\n * @throws Error when Web Crypto API is not available (Edge/browser must provide it).\n */\nfunction generateRequestId(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID();\n }\n throw new Error('Web Crypto API is required but not available.');\n}\n\n/**\n * Exponential backoff delay for a given attempt (0-based).\n * Cap at RETRY_DELAY_CAP_MS.\n */\nexport function getRetryDelayMs(attempt: number, baseMs: number): number {\n const delay = baseMs * Math.pow(2, attempt);\n return Math.min(delay, RETRY_DELAY_CAP_MS);\n}\n\nfunction shouldRetryOnStatus(method: string, status: number): boolean {\n if (method !== 'GET') return false;\n return status >= 500 || status === 429;\n}\n\nexport class FetchHttpClient implements HttpClient {\n constructor(\n private readonly timeoutMs: number,\n private readonly maxRetries: number = 0,\n private readonly retryDelayMs: number = 1000,\n private readonly logger?: Logger\n ) {}\n\n async get<T>(url: string, headers?: Record<string, string>): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, { method: 'GET', headers });\n }\n\n async post<T>(\n url: string,\n body: unknown,\n headers?: Record<string, string>\n ): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: { 'Content-Type': 'application/json', ...headers },\n });\n }\n\n private async request<T>(url: string, config: RequestInit): Promise<Result<T, TryMellonError>> {\n const method = (config.method ?? 'GET').toUpperCase();\n const requestId = generateRequestId();\n const headers = new Headers(config.headers as HeadersInit);\n headers.set('X-Request-Id', requestId);\n\n if (this.logger) {\n this.logger.debug('request', { requestId, url, method });\n }\n\n let lastError: TryMellonError | Error | unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...config,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorData: unknown;\n try {\n errorData = await response.json();\n } catch {\n // Ignore JSON parse error\n }\n\n const { message, code } = parseHttpErrorBody(errorData, response.statusText);\n const errResult = createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: errorData,\n });\n\n if (shouldRetryOnStatus(method, response.status) && attempt < this.maxRetries) {\n lastError = errResult;\n clearTimeout(timeoutId);\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n continue;\n }\n\n return err(errResult);\n }\n\n if (response.status === 204) {\n return ok(undefined as T);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n return ok(undefined as T);\n }\n const raw = (await response.json()) as unknown;\n if (isEnvelopeSuccess(raw)) {\n return ok((raw as { ok: true; resultado: T }).resultado);\n }\n const o = raw as Record<string, unknown>;\n if (typeof raw === 'object' && raw !== null && o.ok === true && !('resultado' in o)) {\n return ok(undefined as T);\n }\n if (isEnvelopeError(raw)) {\n const { message, code } = parseHttpErrorBody(raw, response.statusText);\n return err(\n createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: raw,\n })\n );\n }\n return ok(raw as T);\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n lastError = error;\n const isGet = method === 'GET';\n if (isGet && attempt < this.maxRetries) {\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n } else {\n break;\n }\n }\n }\n\n if (lastError instanceof Error && lastError.name === 'AbortError') {\n return err(createError('TIMEOUT', 'Request timed out', { requestId }));\n }\n\n return err(\n createError(\n 'NETWORK_FAILURE',\n lastError instanceof Error ? lastError.message : 'Request failed',\n { requestId, cause: lastError }\n )\n );\n }\n}\n","import { createEncodingError } from '../errors';\n\n/**\n * Encodes an ArrayBuffer to base64url using globalThis.btoa (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when btoa is unavailable\n */\nexport function base64UrlEncode(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join('');\n\n if (typeof globalThis.btoa === 'undefined') {\n throw createEncodingError('encode');\n }\n const base64 = globalThis.btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Decodes a base64url string to Uint8Array using globalThis.atob (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when atob is unavailable\n */\nexport function base64UrlDecode(s: string): Uint8Array {\n if (typeof globalThis.atob === 'undefined') {\n throw createEncodingError('decode');\n }\n\n const base64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const padding = base64.length % 4;\n const padded = padding === 0 ? base64 : base64 + '='.repeat(4 - padding);\n const binary = globalThis.atob(padded);\n\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n\n/** Decodes base64url to ArrayBuffer (delegates to base64UrlDecode). */\nexport function base64UrlDecodeToArrayBuffer(s: string): ArrayBuffer {\n const bytes = base64UrlDecode(s);\n const buffer = new ArrayBuffer(bytes.length);\n new Uint8Array(buffer).set(bytes);\n return buffer;\n}\n","import { createError } from '../errors';\nimport { base64UrlEncode } from '../utils/base64url';\nimport type { RegisterFinishRequest, AuthFinishRequest } from '../types';\n\ntype SerializedCredentialForRegister = RegisterFinishRequest['credential'];\ntype SerializedCredentialForAuth = AuthFinishRequest['credential'];\n\n/**\n * Type guard to verify whether a credential response is valid.\n */\nfunction isValidCredentialResponse(\n response: unknown\n): response is AuthenticatorAssertionResponse | AuthenticatorAttestationResponse {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'clientDataJSON' in response &&\n response.clientDataJSON instanceof ArrayBuffer\n );\n}\n\n/**\n * Serializes a credential for registration (finish).\n * Includes attestationObject required for registration verification.\n *\n * @param credential - WebAuthn credential from navigator.credentials.create()\n * @returns Serialized credential in Base64URL format\n * @throws {TryMellonError} If the credential does not have the expected structure for registration\n */\nexport function serializeCredentialForRegister(\n credential: PublicKeyCredential\n): SerializedCredentialForRegister {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('attestationObject' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for register: attestationObject is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const attestationObject = (response as AuthenticatorAttestationResponse).attestationObject;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n clientDataJSON: base64UrlEncode(clientDataJSON),\n attestationObject: base64UrlEncode(attestationObject),\n },\n type: 'public-key',\n };\n}\n\n/**\n * Serializes a credential for authentication (finish).\n * Includes authenticatorData, signature, and optionally userHandle.\n *\n * @param credential - WebAuthn credential from navigator.credentials.get()\n * @returns Serialized credential in Base64URL format\n * @throws {TryMellonError} If the credential does not have the expected structure for authentication\n */\nexport function serializeCredentialForAuth(\n credential: PublicKeyCredential\n): SerializedCredentialForAuth {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('authenticatorData' in response) || !('signature' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for auth: authenticatorData or signature is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const authenticatorData = (response as AuthenticatorAssertionResponse).authenticatorData;\n const signature = (response as AuthenticatorAssertionResponse).signature;\n const userHandle = (response as AuthenticatorAssertionResponse).userHandle;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n authenticatorData: base64UrlEncode(authenticatorData),\n clientDataJSON: base64UrlEncode(clientDataJSON),\n signature: base64UrlEncode(signature),\n ...(userHandle && { userHandle: base64UrlEncode(userHandle) }),\n },\n type: 'public-key',\n };\n}\n","import type { ClientStatus } from '../types';\n\nexport function isWebAuthnSupported(): boolean {\n try {\n if (typeof navigator === 'undefined' || !navigator.credentials) {\n return false;\n }\n\n if (typeof PublicKeyCredential === 'undefined') {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n try {\n if (!isWebAuthnSupported()) {\n return false;\n }\n\n if (typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable !== 'function') {\n return false;\n }\n\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\nexport async function getClientStatus(): Promise<ClientStatus> {\n const isPasskeySupported = isWebAuthnSupported();\n const platformAuthenticatorAvailable = await isPlatformAuthenticatorAvailable();\n\n return {\n isPasskeySupported,\n platformAuthenticatorAvailable,\n recommendedFlow: isPasskeySupported ? 'passkey' : 'fallback',\n };\n}\n","import { createCredentialError } from '../errors';\n\nexport function validateCredentialStructure(\n credential: unknown,\n operation: 'create' | 'get' = 'create'\n): asserts credential is PublicKeyCredential {\n if (\n !credential ||\n typeof credential !== 'object' ||\n !('id' in credential) ||\n !('rawId' in credential) ||\n !('response' in credential)\n ) {\n throw createCredentialError(operation);\n }\n}\n","import type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { isWebAuthnSupported } from '../utils/support';\nimport type { EventEmitter } from './events';\nimport type { TryMellonError } from '../errors';\nimport { mapWebAuthnError, createNotSupportedError, createInvalidArgumentError } from '../errors';\nimport { validateCredentialStructure } from '../utils/validation';\n\nexport type CeremonyOperation = 'register' | 'authenticate';\n\nexport interface InvokeCeremonyContext<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n> {\n operation: CeremonyOperation;\n eventEmitter: EventEmitter;\n start: () => Promise<Result<TStartResult, TryMellonError>>;\n createOptions: (startResult: TStartResult) => Result<TCeremonyOptions, TryMellonError>;\n invoke: (options: TCeremonyOptions) => Promise<Credential | null>;\n finish: (\n startResult: TStartResult,\n credential: PublicKeyCredential\n ) => Promise<Result<TFinishResult, TryMellonError>>;\n}\n\n/**\n * Orchestrates a generic WebAuthn flow (Ceremony) to remove duplicated code in the SDK.\n * Encapsulates start call, options creation, browser credentials API invocation,\n * base structure validation, and finish call.\n */\nexport async function invokeCeremony<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n>(\n context: InvokeCeremonyContext<TStartResult, TFinishResult, TCeremonyOptions>\n): Promise<Result<TFinishResult, TryMellonError>> {\n const { operation, eventEmitter, start, createOptions, invoke, finish } = context;\n\n try {\n eventEmitter.emit('start', { type: 'start', operation });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 1. Obtener challenge del servidor\n const startResult = await start();\n if (!startResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: startResult.error });\n return err(startResult.error);\n }\n\n // 2. Create options\n const optionsResult = createOptions(startResult.value);\n if (!optionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: optionsResult.error });\n return err(optionsResult.error);\n }\n\n // 3. Invoke browser\n const credential = (await invoke(optionsResult.value)) as PublicKeyCredential;\n if (!credential) {\n const error = createInvalidArgumentError(\n 'credential',\n `${operation === 'register' ? 'creation' : 'retrieval'} failed`\n );\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Completar en servidor (success lo emite el caller con token/user; 03-eventos-seguridad)\n const finishResult = await finish(startResult.value, credential);\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n return ok(finishResult.value);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n","import { createInvalidArgumentError, validateBase64Url, mapWebAuthnError } from '../errors';\nimport { base64UrlDecodeToArrayBuffer } from '../utils/base64url';\nimport type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n RegisterStartResponse,\n AuthStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Creates credential creation options for WebAuthn.\n * Converts server response to WebAuthn API format.\n * WebAuthn protocol: challenge and rp.id are taken from the server only; do not override.\n * Exported for use by OnboardingManager (same-device) and CrossDeviceManager (QR registration).\n *\n * @param serverChallengePayload - Value of the `.challenge` property from RegisterStartResponse\n * (the nested object with challenge, user, rp, pubKeyCredParams, etc.). Not the full API response.\n */\nexport function createRegistrationOptions(\n serverChallengePayload: RegisterStartResponse['challenge'],\n authenticatorType?: 'platform' | 'cross-platform'\n): Result<CredentialCreationOptions, TryMellonError> {\n try {\n validateBase64Url(serverChallengePayload.challenge, 'challenge');\n validateBase64Url(serverChallengePayload.user.id, 'user.id');\n\n const challengeBuffer = base64UrlDecodeToArrayBuffer(serverChallengePayload.challenge);\n const userIdBuffer = base64UrlDecodeToArrayBuffer(serverChallengePayload.user.id);\n\n // Construir authenticatorSelection: priorizar servidor, permitir override de authenticatorType\n let authenticatorSelection: AuthenticatorSelectionCriteria = {\n userVerification: 'preferred',\n };\n\n if (serverChallengePayload.authenticatorSelection) {\n // Usar valores del servidor como base\n authenticatorSelection = {\n ...serverChallengePayload.authenticatorSelection,\n };\n }\n\n // Si el usuario especifica authenticatorType, sobrescribir authenticatorAttachment\n if (authenticatorType) {\n authenticatorSelection = {\n ...authenticatorSelection,\n authenticatorAttachment: authenticatorType,\n };\n }\n\n const publicKey: PublicKeyCredentialCreationOptions = {\n rp: {\n id: serverChallengePayload.rp.id,\n name: serverChallengePayload.rp.name,\n },\n user: {\n id: userIdBuffer,\n name: serverChallengePayload.user.name,\n displayName: serverChallengePayload.user.displayName,\n },\n challenge: challengeBuffer,\n pubKeyCredParams: serverChallengePayload.pubKeyCredParams,\n ...(serverChallengePayload.timeout !== undefined && {\n timeout: serverChallengePayload.timeout,\n }),\n attestation: 'none',\n authenticatorSelection,\n ...(serverChallengePayload.excludeCredentials && {\n excludeCredentials: serverChallengePayload.excludeCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n };\n\n return ok({ publicKey });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Creates authentication options for WebAuthn.\n * Converts server response to WebAuthn API format.\n * WebAuthn protocol: challenge and rpId are taken from the server only; do not override.\n */\nexport function createAuthenticationOptions(\n challenge: AuthStartResponse['challenge'],\n mediation?: AuthenticateOptions['mediation']\n): Result<CredentialRequestOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n\n return ok({\n publicKey: {\n challenge: challengeBuffer,\n rpId: challenge.rpId,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n userVerification: challenge.userVerification ?? 'preferred',\n ...(challenge.allowCredentials && {\n allowCredentials: challenge.allowCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n },\n ...(mediation !== undefined && { mediation }),\n });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Registers a new passkey for a user.\n * Handles the full WebAuthn registration flow.\n */\nexport async function registerPasskey(\n options: RegisterOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RegisterResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const result = await invokeCeremony<\n RegisterStartResponse,\n RegisterResult,\n CredentialCreationOptions\n >({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.startRegister({ external_user_id: extId }),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge, options.authenticatorType),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.create(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishRegister({\n session_id: startResult.session_id,\n credential: serializeCredentialForRegister(credential),\n ...(options.successUrl && { success_url: options.successUrl }),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n success: true,\n credentialId: finishResult.value.credential_id,\n credential_id: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n ...(finishResult.value.redirect_url && { redirectUrl: finishResult.value.redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n\n/**\n * Authenticates a user with their passkey.\n * Handles the full WebAuthn authentication flow.\n */\nexport async function authenticatePasskey(\n options: AuthenticateOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<AuthenticateResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n const hasUserId = extId !== undefined && typeof extId === 'string' && extId.trim() !== '';\n\n const result = await invokeCeremony<\n AuthStartResponse,\n AuthenticateResult,\n CredentialRequestOptions\n >({\n operation: 'authenticate',\n eventEmitter,\n start: () =>\n apiClient.startAuth(hasUserId ? { external_user_id: (extId as string).trim() } : {}),\n createOptions: (startResult) =>\n createAuthenticationOptions(startResult.challenge, options.mediation),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.get(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishAuthentication({\n session_id: startResult.session_id,\n credential: serializeCredentialForAuth(credential),\n ...(options.successUrl && { success_url: options.successUrl }),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n authenticated: finishResult.value.authenticated,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n signals: finishResult.value.signals,\n ...(finishResult.value.redirect_url && { redirectUrl: finishResult.value.redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'authenticate',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n","export async function waitWithAbort(\n intervalMs: number,\n signal?: AbortSignal\n): Promise<'aborted' | 'completed'> {\n // Fast path when no signal is provided: simple sleep.\n if (!signal) {\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n return 'completed';\n }\n\n if (signal.aborted) {\n return 'aborted';\n }\n\n return new Promise<'aborted' | 'completed'>((resolve) => {\n const onAbort = () => {\n cleanup();\n resolve('aborted');\n };\n\n const cleanup = () => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n };\n\n const timeout = setTimeout(() => {\n cleanup();\n resolve('completed');\n }, intervalMs);\n\n signal.addEventListener('abort', onAbort);\n });\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type { OnboardingStartOptions, OnboardingCompleteResult } from '../types';\nimport { createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\nimport { waitWithAbort } from './polling-utils';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class OnboardingManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Executes the full onboarding flow in a single call.\n * 1. Starts onboarding\n * 2. Polls for 'pending_passkey' or 'completed' status\n * 3. If pending_passkey: when API returns challenge, registers passkey (WebAuthn) then completes onboarding\n * 4. If pending_passkey but API does not return challenge: returns NOT_SUPPORTED with onboarding_url for user to complete elsewhere\n */\n async startFlow(\n options: OnboardingStartOptions & { company_name?: string },\n signal?: AbortSignal\n ): Promise<Result<OnboardingCompleteResult, TryMellonError>> {\n const startResult = await this.apiClient.startOnboarding({ user_role: options.user_role });\n if (!startResult.ok) return err(startResult.error);\n\n const { session_id } = startResult.value;\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const waitResult = await waitWithAbort(POLL_INTERVAL_MS, signal);\n if (waitResult === 'aborted') {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const statusResult = await this.apiClient.getOnboardingStatus(session_id);\n if (!statusResult.ok) return err(statusResult.error);\n\n const status = statusResult.value.status;\n const onboarding_url = statusResult.value.onboarding_url;\n\n if (status === 'pending_passkey') {\n const registerInfoResult = await this.apiClient.getOnboardingRegister(session_id);\n if (!registerInfoResult.ok) return err(registerInfoResult.error);\n\n const registerInfo = registerInfoResult.value as OnboardingRegisterResponseWithChallenge;\n\n if (!registerInfo.challenge) {\n return err(\n createError(\n 'NOT_SUPPORTED',\n 'Onboarding requires user action - complete passkey registration at the provided onboarding_url',\n { onboarding_url }\n )\n );\n }\n\n const creationOptionsResult = createRegistrationOptions(registerInfo.challenge);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n const registerPasskeyResult = await this.apiClient.registerOnboardingPasskey(session_id, {\n credential: serializedCredential,\n challenge: registerInfo.challenge.challenge,\n });\n if (!registerPasskeyResult.ok) return err(registerPasskeyResult.error);\n\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n\n if (status === 'completed') {\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n }\n\n return err(createError('TIMEOUT', 'Onboarding timed out'));\n }\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceContextAuth,\n CrossDeviceContextRegistration,\n} from '../types';\nimport { createAuthenticationOptions, createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport { waitWithAbort } from './polling-utils';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class CrossDeviceManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Initializes a cross-device authentication session.\n * Typically called by the desktop side to get a QR code URL.\n */\n async init(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceAuth();\n }\n\n /**\n * Initializes a cross-device registration session (create account via QR).\n * Typically called by the desktop side to get a QR code URL for new users.\n * Pass externalUserId for known users; omit for anonymous registration.\n */\n async initRegistration(options?: {\n externalUserId?: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceRegistration(options);\n }\n\n /**\n * High-level helper to poll for session status until it is completed.\n * Typically called by the desktop side after showing the QR code.\n * Pass pollingToken from init() result so the backend can verify the poller is the initiator.\n */\n async waitForSession(\n sessionId: string,\n signal?: AbortSignal,\n pollingToken?: string | null\n ): Promise<\n Result<{ session_token: string; user_id: string; redirectUrl?: string }, TryMellonError>\n > {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n const statusResult = await this.apiClient.getCrossDeviceStatus(sessionId, pollingToken);\n if (!statusResult.ok) return err(statusResult.error);\n\n if (statusResult.value.status === 'completed') {\n if (!statusResult.value.session_token || !statusResult.value.user_id) {\n return err(createError('UNKNOWN_ERROR', 'Missing data in completed session'));\n }\n const redirectUrl =\n statusResult.value.redirect_url != null && statusResult.value.redirect_url !== ''\n ? statusResult.value.redirect_url\n : undefined;\n return ok({\n session_token: statusResult.value.session_token,\n user_id: statusResult.value.user_id,\n ...(redirectUrl !== undefined && { redirectUrl }),\n });\n }\n\n const waitResult = await waitWithAbort(POLL_INTERVAL_MS, signal);\n if (waitResult === 'aborted') {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n }\n\n return err(createError('TIMEOUT', 'Cross-device authentication timed out'));\n }\n\n /**\n * Approves a cross-device session.\n * Typically called by the mobile side after scanning a QR code.\n * Branches by context type: registration → credentials.create + verify-registration;\n * auth → credentials.get + verify.\n */\n async approve(sessionId: string): Promise<Result<void, TryMellonError>> {\n const contextResult = await this.apiClient.getCrossDeviceContext(sessionId);\n if (!contextResult.ok) return err(contextResult.error);\n\n const context = contextResult.value;\n\n if (context.type === 'registration') {\n return this.executeRegistrationApproval(sessionId, context);\n }\n return this.executeAuthApproval(sessionId, context);\n }\n\n /**\n * Executes the registration branch: create credential and verify-registration.\n */\n private async executeRegistrationApproval(\n sessionId: string,\n context: CrossDeviceContextRegistration\n ): Promise<Result<void, TryMellonError>> {\n const creationOptionsResult = createRegistrationOptions(context.options);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceRegistration({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n\n /**\n * Executes the auth branch: get credential and verify.\n */\n private async executeAuthApproval(\n sessionId: string,\n context: CrossDeviceContextAuth\n ): Promise<Result<void, TryMellonError>> {\n const requestOptionsResult = createAuthenticationOptions(context.options);\n if (!requestOptionsResult.ok) return err(requestOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.get(requestOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'get');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForAuth(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceAuth({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n}\n","import type { EventHandler, EventPayload, TryMellonEvent } from '../types';\n\nexport class EventEmitter {\n private handlers: Map<TryMellonEvent, Set<EventHandler>>;\n\n constructor() {\n this.handlers = new Map();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n let handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n handlersSet = new Set();\n this.handlers.set(event, handlersSet);\n }\n\n handlersSet.add(handler);\n\n return () => {\n this.off(event, handler);\n };\n }\n\n off(event: TryMellonEvent, handler: EventHandler): void {\n const handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n return;\n }\n handlersSet.delete(handler);\n if (handlersSet.size === 0) {\n this.handlers.delete(event);\n }\n }\n\n emit(event: TryMellonEvent, payload: EventPayload): void {\n const handlersSet = this.handlers.get(event);\n if (handlersSet) {\n for (const handler of handlersSet) {\n try {\n handler(payload);\n } catch {\n // Silently ignore handler errors to prevent one handler from breaking others\n // Handler errors are the responsibility of the handler implementation\n }\n }\n }\n }\n\n removeAllListeners(): void {\n this.handlers.clear();\n }\n}\n","export const COSE_ALGORITHM_ES256 = -7;\nexport const COSE_ALGORITHM_RS256 = -257;\n\nexport const DEFAULT_API_BASE_URL = 'https://api.trymellonauth.com';\nexport const DEFAULT_TELEMETRY_ENDPOINT = 'https://api.trymellonauth.com/v1/telemetry';\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\nexport const MIN_TIMEOUT_MS = 1000;\nexport const MAX_TIMEOUT_MS = 300000;\nexport const MIN_MAX_RETRIES = 0;\nexport const MAX_MAX_RETRIES = 10;\nexport const MIN_RETRY_DELAY_MS = 100;\nexport const MAX_RETRY_DELAY_MS = 10000;\n\n/**\n * Fixed session token returned by register() and authenticate() when sandbox mode is enabled.\n * Backends MUST NOT accept this token in production; only in development for testing the integration flow.\n */\nexport const SANDBOX_SESSION_TOKEN = 'trymellon_sandbox_session_token_v1';\n","import type { TelemetrySender, TelemetryPayload } from '../ports/telemetry';\n\n/**\n * Default telemetry sender: sends payload via sendBeacon (or fetch) to the given endpoint.\n * No retries; fire-and-forget.\n */\nexport function createDefaultTelemetrySender(endpoint: string): TelemetrySender {\n return {\n async send(payload: TelemetryPayload): Promise<void> {\n const body = JSON.stringify(payload);\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n navigator.sendBeacon(endpoint, body);\n return;\n }\n if (typeof fetch !== 'undefined') {\n await fetch(endpoint, {\n method: 'POST',\n body,\n headers: { 'Content-Type': 'application/json' },\n keepalive: true,\n });\n }\n },\n };\n}\n","export type TelemetryEvent = 'register' | 'authenticate';\n\nexport type TelemetryPayload = {\n event: TelemetryEvent;\n latencyMs: number;\n ok: true;\n};\n\nexport interface TelemetrySender {\n send(payload: TelemetryPayload): Promise<void>;\n}\n\n/**\n * Builds the minimal telemetry payload (no PII).\n */\nexport function buildTelemetryPayload(event: TelemetryEvent, latencyMs: number): TelemetryPayload {\n return { event, latencyMs, ok: true };\n}\n","import type { ApiClient } from '../api';\nimport type { EventEmitter } from '../events';\nimport type {\n AuthenticateOptions,\n AuthenticateResult,\n RegisterOptions,\n RegisterResult,\n} from '../../types';\nimport type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { buildTelemetryPayload, type TelemetrySender } from '../ports/telemetry';\nimport { registerPasskey, authenticatePasskey } from '../webauthn';\n\ntype AuthOperation = 'register' | 'authenticate';\n\ntype AuthOptions = RegisterOptions | AuthenticateOptions;\n\nexport class AuthService {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly eventEmitter: EventEmitter,\n private readonly sandbox: boolean,\n private readonly sandboxToken: string,\n private readonly telemetrySender?: TelemetrySender\n ) {}\n\n private async sandboxAuthResult(\n operation: AuthOperation,\n options: AuthOptions\n ): Promise<Result<RegisterResult | AuthenticateResult, TryMellonError>> {\n const externalUserId =\n 'externalUserId' in options\n ? (options.externalUserId ?? options.external_user_id ?? 'sandbox')\n : (options.external_user_id ?? options.externalUserId ?? 'sandbox');\n const externalId = typeof externalUserId === 'string' ? externalUserId : 'sandbox';\n\n if (operation === 'register') {\n return Promise.resolve(\n ok({\n success: true,\n credentialId: '',\n status: 'sandbox',\n sessionToken: this.sandboxToken,\n user: { userId: 'sandbox-user', externalUserId: externalId },\n })\n );\n }\n\n return Promise.resolve(\n ok({\n authenticated: true,\n sessionToken: this.sandboxToken,\n user: { userId: 'sandbox-user', externalUserId: externalId },\n })\n );\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n if (this.sandbox) {\n const result = await this.sandboxAuthResult('register', options);\n if (result.ok) {\n this.eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result as Result<RegisterResult, TryMellonError>;\n }\n\n const start = Date.now();\n const result = await registerPasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('register', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n if (this.sandbox) {\n const result = await this.sandboxAuthResult('authenticate', options);\n if (result.ok) {\n this.eventEmitter.emit('success', {\n type: 'success',\n operation: 'authenticate',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result as Result<AuthenticateResult, TryMellonError>;\n }\n\n const start = Date.now();\n const result = await authenticatePasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('authenticate', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n}\n","import type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RecoverAccountOptions,\n RecoverAccountResult,\n RecoveryVerifyResponse,\n RegisterStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { createInvalidArgumentError } from '../errors';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { createRegistrationOptions } from './webauthn';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Recovers an account using an email OTP and creates a new passkey credential.\n * Manages the complete orchestrated WebAuthn registration flow for recovery.\n */\nexport async function recoverAccount(\n options: RecoverAccountOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RecoverAccountResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n if (!options.otp || typeof options.otp !== 'string' || options.otp.trim().length !== 6) {\n const error = createInvalidArgumentError('otp', 'must be a 6-digit string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const result = await invokeCeremony<\n RecoveryVerifyResponse,\n RecoverAccountResult,\n CredentialCreationOptions\n >({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.verifyAccountRecoveryOtp(extId, options.otp),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge as RegisterStartResponse['challenge']),\n invoke: async (ceremonyOptions) => navigator.credentials.create(ceremonyOptions),\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.completeAccountRecovery(\n startResult.recovery_session_id,\n serializeCredentialForRegister(credential)\n );\n\n if (!finishResult.ok) return err(finishResult.error);\n\n const {\n credential_id,\n status,\n session_token,\n user: userPayload,\n redirect_url,\n } = finishResult.value;\n return ok({\n success: true,\n credentialId: credential_id,\n status,\n sessionToken: session_token,\n user: {\n userId: userPayload.user_id,\n externalUserId: userPayload.external_user_id,\n email: userPayload.email,\n metadata: userPayload.metadata,\n },\n ...(redirect_url !== undefined && { redirectUrl: redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n","import type { ApiClient } from '../api';\nimport type { EventEmitter } from '../events';\nimport type { RecoverAccountOptions, RecoverAccountResult } from '../../types';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { recoverAccount } from '../recover';\n\nexport class RecoveryService {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly eventEmitter: EventEmitter\n ) {}\n\n recover(options: RecoverAccountOptions): Promise<Result<RecoverAccountResult, TryMellonError>> {\n return recoverAccount(options, this.apiClient, this.eventEmitter);\n }\n}\n","import { ApiClient } from './api';\nimport { FetchHttpClient } from './fetch-client';\nimport { OnboardingManager } from './onboarding-manager';\nimport { CrossDeviceManager } from './cross-device-manager';\nimport { EventEmitter } from './events';\nimport { isWebAuthnSupported, getClientStatus } from '../utils/support';\nimport { validateUrl, validateRange, createInvalidArgumentError } from '../errors';\nimport {\n DEFAULT_API_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_RETRY_DELAY_MS,\n DEFAULT_TELEMETRY_ENDPOINT,\n MIN_TIMEOUT_MS,\n MAX_TIMEOUT_MS,\n MIN_MAX_RETRIES,\n MAX_MAX_RETRIES,\n MIN_RETRY_DELAY_MS,\n MAX_RETRY_DELAY_MS,\n SANDBOX_SESSION_TOKEN,\n} from './constants';\nimport { createDefaultTelemetrySender } from './adapters/telemetry-sender';\nimport type { TelemetrySender } from './ports/telemetry';\nimport type {\n TryMellonConfig,\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n ClientStatus,\n TryMellonEvent,\n EventHandler,\n EmailFallbackStartOptions,\n EmailFallbackVerifyOptions,\n EmailFallbackVerifyResult,\n SessionValidateResponse,\n RecoverAccountOptions,\n} from '../types';\nimport { ok, err, type Result } from '../utils/result';\nimport { type TryMellonError, isTryMellonError } from '../errors';\nimport { AuthService } from './services/auth-service';\nimport { RecoveryService } from './services/recovery-service';\n\ndeclare const __VERSION__: string;\n\nexport class TryMellon {\n private readonly sandbox: boolean;\n private readonly sandboxToken: string;\n private apiClient: ApiClient;\n private eventEmitter: EventEmitter;\n private telemetrySender: TelemetrySender | undefined;\n private crossDeviceManager: CrossDeviceManager;\n private authService: AuthService;\n private recoveryService: RecoveryService;\n public onboarding: OnboardingManager;\n\n /**\n * Creates a new TryMellon instance.\n * Validates config and returns a Result.\n * @param config SDK configuration\n */\n static create(config: TryMellonConfig): Result<TryMellon, TryMellonError> {\n try {\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n return err(createInvalidArgumentError('appId', 'must be a non-empty string'));\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n return err(createInvalidArgumentError('publishableKey', 'must be a non-empty string'));\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n // Safe to instantiate now\n return ok(new TryMellon(config));\n } catch (e) {\n if (isTryMellonError(e)) {\n return err(e);\n }\n return err(createInvalidArgumentError('config', (e as Error).message));\n }\n }\n\n /**\n * @deprecated Use `TryMellon.create(config)` instead to handle validation errors safely.\n * This constructor will throw errors if configuration is invalid.\n */\n constructor(config: TryMellonConfig) {\n this.sandbox = config.sandbox === true;\n this.sandboxToken =\n this.sandbox && config.sandboxToken != null && config.sandboxToken !== ''\n ? config.sandboxToken\n : SANDBOX_SESSION_TOKEN;\n\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n // Legacy validation for direct constructor usage (still throws to maintain behavior for legacy code,\n // but create() handles this safely before calling constructor)\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n throw createInvalidArgumentError('appId', 'must be a non-empty string');\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n throw createInvalidArgumentError('publishableKey', 'must be a non-empty string');\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n // validateUrl throws, which is expected for the constructor. create() catches it.\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const httpClient = new FetchHttpClient(timeoutMs, maxRetries, retryDelayMs, config.logger);\n\n const originHeader =\n config.origin ??\n (typeof window !== 'undefined' && window?.location?.origin\n ? window.location.origin\n : undefined);\n\n const defaultHeaders: Record<string, string> = {\n 'X-App-Id': appId.trim(),\n Authorization: `Bearer ${publishableKey.trim()}`,\n ...(originHeader && { Origin: originHeader }),\n };\n\n this.apiClient = new ApiClient(httpClient, apiBaseUrl, defaultHeaders);\n this.eventEmitter = new EventEmitter();\n\n if (config.enableTelemetry) {\n this.telemetrySender =\n config.telemetrySender ??\n createDefaultTelemetrySender(config.telemetryEndpoint ?? DEFAULT_TELEMETRY_ENDPOINT);\n }\n\n this.authService = new AuthService(\n this.apiClient,\n this.eventEmitter,\n this.sandbox,\n this.sandboxToken,\n this.telemetrySender\n );\n this.recoveryService = new RecoveryService(this.apiClient, this.eventEmitter);\n this.onboarding = new OnboardingManager(this.apiClient);\n this.crossDeviceManager = new CrossDeviceManager(this.apiClient);\n }\n\n static isSupported(): boolean {\n return isWebAuthnSupported();\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n return this.authService.register(options);\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n return this.authService.authenticate(options);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n if (this.sandbox && sessionToken === this.sandboxToken) {\n return Promise.resolve(\n ok({\n valid: true,\n user_id: 'sandbox-user',\n external_user_id: 'sandbox',\n tenant_id: 'sandbox-tenant',\n app_id: 'sandbox-app',\n })\n );\n }\n return this.apiClient.validateSession(sessionToken);\n }\n\n async getStatus(): Promise<ClientStatus> {\n return getClientStatus();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n return this.eventEmitter.on(event, handler);\n }\n\n version(): string {\n return typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0';\n }\n\n fallback = {\n email: {\n start: async (options: EmailFallbackStartOptions): Promise<Result<void, TryMellonError>> => {\n return this.apiClient.startEmailFallback(options);\n },\n verify: async (\n options: EmailFallbackVerifyOptions\n ): Promise<Result<EmailFallbackVerifyResult, TryMellonError>> => {\n const result = await this.apiClient.verifyEmailCode({\n userId: options.userId,\n code: options.code,\n ...(options.successUrl && { successUrl: options.successUrl }),\n });\n if (!result.ok) return result;\n return ok({\n sessionToken: result.value.sessionToken,\n ...(result.value.redirectUrl && { redirectUrl: result.value.redirectUrl }),\n });\n },\n },\n };\n\n auth = {\n crossDevice: {\n init: () => this.crossDeviceManager.init(),\n initRegistration: (options?: { externalUserId?: string }) =>\n this.crossDeviceManager.initRegistration(options ?? {}),\n waitForSession: (sessionId: string, signal?: AbortSignal, pollingToken?: string | null) =>\n this.crossDeviceManager.waitForSession(sessionId, signal, pollingToken),\n getContext: (sessionId: string) => this.apiClient.getCrossDeviceContext(sessionId),\n approve: (sessionId: string) => this.crossDeviceManager.approve(sessionId),\n },\n recoverAccount: (options: RecoverAccountOptions) => this.recoveryService.recover(options),\n };\n}\n","/**\n * Adapter/factory to create and validate core instances for UI. Infrastructure: may import real TryMellon.\n */\nimport { TryMellon } from '../../../core/trymellon';\nimport type { CoreAuthPort, CoreAuthOptions } from '../../ports';\n\nexport interface CoreConfig {\n appId: string;\n publishableKey: string;\n}\n\n/** Creates core instance for UI using minimal CoreAuthPort. Returns null on failure; Presentation decides. */\nexport function createCoreForUI(config: CoreConfig): CoreAuthPort | null {\n const result = TryMellon.create({\n appId: config.appId,\n publishableKey: config.publishableKey,\n });\n\n if (!result.ok || result.value == null) {\n return null;\n }\n\n return result.value as CoreAuthPort;\n}\n\n/** Runtime guard: injected instance satisfies CoreAuthPort. Keeps WCs decoupled from concrete TryMellon. */\nexport function isCoreAuthPort(candidate: unknown): candidate is CoreAuthPort {\n if (candidate == null || typeof candidate !== 'object') return false;\n\n const maybe = candidate as Record<string, unknown>;\n\n const hasAuthenticate = typeof maybe.authenticate === 'function';\n const hasRegister = typeof maybe.register === 'function';\n const hasOn = typeof maybe.on === 'function';\n\n return hasAuthenticate && hasRegister && hasOn;\n}\n\n/** Normalizes Presentation options to CoreAuthOptions. Forwards externalUserId when present. */\nexport function toCoreAuthOptions(externalUserId: string | null): CoreAuthOptions {\n return externalUserId ? { externalUserId } : {};\n}\n","/**\n * Centralized constants for the infra layer (event bridge).\n * CustomEvent names for core → host communication.\n */\n\n/** Event name when modal opens (WC lifecycle). */\nexport const MELLON_OPEN = 'mellon:open';\n\n/** Event name when button/host requests modal open. bubbles: true, composed: true; detail empty or minimal. */\nexport const MELLON_OPEN_REQUEST = 'mellon:open-request';\n\n/** Event name when modal closes (WC lifecycle). */\nexport const MELLON_CLOSE = 'mellon:close';\n\n/** Event name when auth completes (core → host). bubbles: false, composed: true; listener on WC element. */\nexport const MELLON_SUCCESS = 'mellon:success';\n\n/** Event name when auth fails (core → host). bubbles: true, composed: true. */\nexport const MELLON_ERROR = 'mellon:error';\n\n/** Event name when ceremony starts (core → host). */\nexport const MELLON_START = 'mellon:start';\n\n/** Event name when ceremony is cancelled (host close or reset from AUTHENTICATING). bubbles: true, composed: true. */\nexport const MELLON_CANCELLED = 'mellon:cancelled';\n\n/** Fired on fallback UI click inside WC (no external navigation). */\nexport const MELLON_FALLBACK = 'mellon:fallback';\n\n/** Event name when tab changes (register ↔ login) in the modal. */\nexport const MELLON_TAB_CHANGE = 'mellon:tab-change';\n","/**\n * Event bridge: Core EventEmitter → DOM CustomEvents on the WC host element.\n * Token only in mellon:success; bubbles:false, composed:true. At most once success per ceremony; no error after success.\n * Payload as unknown; narrow with type guards to port types. P1-B: nonce in detail when present; no public API to dispatch success with arbitrary detail.\n * Constants: infra/constants.ts.\n */\nimport type {\n AuthOperation,\n CoreCancelledPayload,\n CoreErrorPayload,\n CoreEventsPort,\n CoreStartPayload,\n CoreSuccessPayload,\n CoreWithEvents,\n MellonErrorDetail,\n MellonOperationDetail,\n MellonSuccessDetail,\n MellonSuccessUserInfo,\n} from '../../ports/core-events.port';\nimport {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n} from './constants';\n\nexport {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n};\n\nexport type {\n AuthOperation,\n CoreWithEvents,\n MellonErrorDetail,\n MellonOperationDetail,\n MellonSuccessDetail,\n} from '../../ports/core-events.port';\n\nfunction dispatchCustomEvent<T>(\n host: HTMLElement,\n name: string,\n detail: T,\n options: { bubbles: boolean; composed: boolean }\n): void {\n host.dispatchEvent(\n new CustomEvent(name, {\n detail,\n bubbles: options.bubbles,\n composed: options.composed,\n })\n );\n}\n\n/** Map core operation to public contract ('login' | 'register'). */\nfunction toPublicOperation(op: 'register' | 'authenticate'): AuthOperation {\n return op === 'authenticate' ? 'login' : 'register';\n}\n\n/**\n * Maps raw core success payload user to MellonSuccessUserInfo. Returns undefined if payload\n * does not expose user or does not have at least a non-empty userId (no inventar forma).\n */\nfunction mapSuccessUser(raw: unknown): MellonSuccessUserInfo | undefined {\n if (raw == null || typeof raw !== 'object') return undefined;\n const o = raw as Record<string, unknown>;\n const userId = o.userId;\n if (typeof userId !== 'string' || userId.length === 0) return undefined;\n const result: MellonSuccessUserInfo = { userId };\n if (typeof o.externalUserId === 'string') result.externalUserId = o.externalUserId;\n if (typeof o.email === 'string') result.email = o.email;\n if (o.metadata != null && typeof o.metadata === 'object' && !Array.isArray(o.metadata)) {\n result.metadata = o.metadata as Record<string, unknown>;\n }\n return result;\n}\n\nfunction isCoreStartPayload(raw: unknown): raw is CoreStartPayload {\n return (\n raw != null &&\n typeof raw === 'object' &&\n (raw as CoreStartPayload).type === 'start' &&\n ((raw as CoreStartPayload).operation === 'register' ||\n (raw as CoreStartPayload).operation === 'authenticate')\n );\n}\n\nfunction isCoreSuccessPayload(raw: unknown): raw is CoreSuccessPayload {\n const o = raw as Record<string, unknown>;\n return (\n raw != null &&\n typeof raw === 'object' &&\n o.type === 'success' &&\n typeof o.token === 'string' &&\n (o.operation === 'register' || o.operation === 'authenticate')\n );\n}\n\nfunction isCoreErrorPayload(raw: unknown): raw is CoreErrorPayload {\n return raw != null && typeof raw === 'object' && (raw as CoreErrorPayload).type === 'error';\n}\n\nfunction isCoreCancelledPayload(raw: unknown): raw is CoreCancelledPayload {\n return (\n raw != null &&\n typeof raw === 'object' &&\n (raw as CoreCancelledPayload).type === 'cancelled' &&\n ((raw as CoreCancelledPayload).operation === 'register' ||\n (raw as CoreCancelledPayload).operation === 'authenticate')\n );\n}\n\n/** Event-bridge adapter: CoreEventsPort (core → CustomEvents on host). */\nconst eventBridgeAdapter: CoreEventsPort = {\n subscribe(core: CoreWithEvents, host: HTMLElement): () => void {\n if (core == null || host == null) {\n throw new TypeError('eventBridgeAdapter.subscribe: core and host are required');\n }\n const unsubscribes: Array<() => void> = [];\n let lastOperation: 'register' | 'authenticate' = 'authenticate';\n let successEmittedThisCeremony = false;\n\n const offStart = core.on('start', (payload: unknown) => {\n if (!isCoreStartPayload(payload)) return;\n lastOperation = payload.operation;\n successEmittedThisCeremony = false;\n const detail: MellonOperationDetail = {\n operation: toPublicOperation(payload.operation),\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n };\n dispatchCustomEvent<MellonOperationDetail>(host, MELLON_START, detail, {\n bubbles: true,\n composed: true,\n });\n });\n unsubscribes.push(offStart);\n\n const offSuccess = core.on('success', (payload: unknown) => {\n if (!isCoreSuccessPayload(payload)) return;\n if (successEmittedThisCeremony) return;\n if (payload.token.length === 0) return;\n successEmittedThisCeremony = true;\n const mappedUser = mapSuccessUser(payload.user);\n const detail: MellonSuccessDetail = {\n operation: toPublicOperation(payload.operation),\n token: payload.token,\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n ...(mappedUser !== undefined && { user: mappedUser }),\n ...(typeof payload.redirectUrl === 'string' && { redirectUrl: payload.redirectUrl }),\n };\n // Token not exposed to document/window (bubbles: false).\n dispatchCustomEvent<MellonSuccessDetail>(host, MELLON_SUCCESS, detail, {\n bubbles: false,\n composed: true,\n });\n });\n unsubscribes.push(offSuccess);\n\n const offError = core.on('error', (payload: unknown) => {\n if (!isCoreErrorPayload(payload)) return;\n if (successEmittedThisCeremony) return;\n const code = payload.error?.code ?? 'UNKNOWN_ERROR';\n const detail: MellonErrorDetail = {\n operation: toPublicOperation(payload.operation ?? lastOperation),\n code,\n message:\n typeof payload.error?.message === 'string' ? payload.error.message : 'Unknown error',\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n };\n dispatchCustomEvent<MellonErrorDetail>(host, MELLON_ERROR, detail, {\n bubbles: true,\n composed: true,\n });\n });\n unsubscribes.push(offError);\n\n const offCancelled = core.on('cancelled', (payload: unknown) => {\n if (!isCoreCancelledPayload(payload)) return;\n const detail: MellonOperationDetail = {\n operation: toPublicOperation(payload.operation),\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n };\n dispatchCustomEvent<MellonOperationDetail>(host, MELLON_CANCELLED, detail, {\n bubbles: true,\n composed: true,\n });\n });\n unsubscribes.push(offCancelled);\n\n return function unsubscribe(): void {\n for (const off of unsubscribes) {\n off();\n }\n };\n },\n};\n\nexport { eventBridgeAdapter };\n","/**\n * Adapter: EnvStatusPort implementado delegando en getClientStatus.\n * Maps ClientStatus (core) → UIClientStatus (domain); coupling to core only here.\n */\nimport type { ClientStatus } from '../../../types';\nimport type { UIClientStatus } from '../../domain/types';\nimport type { EnvStatusPort } from '../../ports/env-evaluator.port';\nimport { getClientStatus } from '../../../utils/support';\n\nfunction mapClientStatusToUI(status: ClientStatus): UIClientStatus {\n return {\n isPasskeySupported: status.isPasskeySupported,\n platformAuthenticatorAvailable: status.platformAuthenticatorAvailable,\n recommendedFlow: status.recommendedFlow,\n };\n}\n\n/**\n * Creates adapter implementing EnvStatusPort using getClientStatus from utils/support. Used in tests or paths without core.\n */\nexport function createEnvStatusAdapter(): EnvStatusPort {\n return {\n getClientStatus: async (): Promise<UIClientStatus> => {\n const status = await getClientStatus();\n return mapClientStatusToUI(status);\n },\n };\n}\n\n/**\n * Creates adapter implementing EnvStatusPort using core TryMellon getStatus. Caller MUST validate getClientStatus result with isClientStatus.\n */\nexport function createEnvStatusPortFromCore(core: unknown): EnvStatusPort {\n const candidate = core as { getStatus?: () => Promise<ClientStatus> };\n if (typeof candidate.getStatus !== 'function') {\n return createEnvStatusAdapter();\n }\n\n const getStatus = candidate.getStatus;\n\n return {\n getClientStatus: async (): Promise<UIClientStatus> => {\n const status = await getStatus();\n return mapClientStatusToUI(status);\n },\n };\n}\n","import {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n} from '../adapters/infra/event-bridge.adapter';\nimport type {\n MellonErrorDetail,\n MellonFallbackDetail,\n MellonOperationDetail,\n MellonSuccessDetail,\n} from '../ports/core-events.port';\nimport type { MellonCloseDetail, MellonOpenDetail } from '../ports';\n\nexport {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n};\n\nexport function createMellonOpenEvent(detail: MellonOpenDetail): CustomEvent<MellonOpenDetail> {\n return new CustomEvent<MellonOpenDetail>(MELLON_OPEN, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonCloseEvent(detail: MellonCloseDetail): CustomEvent<MellonCloseDetail> {\n return new CustomEvent<MellonCloseDetail>(MELLON_CLOSE, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonCancelledEvent(\n detail: MellonOperationDetail\n): CustomEvent<MellonOperationDetail> {\n return new CustomEvent<MellonOperationDetail>(MELLON_CANCELLED, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonFallbackEvent(\n detail: MellonFallbackDetail\n): CustomEvent<MellonFallbackDetail> {\n return new CustomEvent<MellonFallbackDetail>(MELLON_FALLBACK, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonTabChangeEvent(detail: { tab: string }): CustomEvent<{ tab: string }> {\n return new CustomEvent<{ tab: string }>(MELLON_TAB_CHANGE, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonStartEvent(\n detail: MellonOperationDetail\n): CustomEvent<MellonOperationDetail> {\n return new CustomEvent<MellonOperationDetail>(MELLON_START, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonSuccessEvent(\n detail: MellonSuccessDetail\n): CustomEvent<MellonSuccessDetail> {\n return new CustomEvent<MellonSuccessDetail>(MELLON_SUCCESS, {\n detail,\n bubbles: false,\n composed: true,\n });\n}\n\nexport function createMellonErrorEvent(detail: MellonErrorDetail): CustomEvent<MellonErrorDetail> {\n return new CustomEvent<MellonErrorDetail>(MELLON_ERROR, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n","import type { UIState, TabKind } from '../domain/types';\nimport { INITIAL_UI_STATE, tabToUIMode } from '../domain/types';\nimport { authUiApplicationService, canStartAuth } from '../application/auth-ui.application-service';\nimport type {\n CoreAuthPort,\n CoreAuthOptions,\n MellonOperationDetail,\n} from '../ports/core-events.port';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\n\nexport type PendingAuthOperation = 'register' | 'authenticate';\n\nexport class AuthController {\n private _currentState: UIState = INITIAL_UI_STATE;\n private _lastRenderedState: UIState | null = null;\n private _renderDirty = true;\n private _pendingOperation: PendingAuthOperation = 'authenticate';\n private _currentNonce: string | undefined = undefined;\n private _envEvalRequestId = 0;\n\n get currentState(): UIState {\n return this._currentState;\n }\n\n setState(next: UIState): void {\n this._currentState = next;\n this._renderDirty = true;\n }\n\n invalidateRender(): void {\n this._renderDirty = true;\n }\n\n /**\n * Decides if a render is needed based on state/dirty flag.\n * Returns true when the caller should render and marks state as clean.\n */\n consumeRenderDecision(): boolean {\n if (!this._renderDirty && this._currentState === this._lastRenderedState) {\n return false;\n }\n this._lastRenderedState = this._currentState;\n this._renderDirty = false;\n return true;\n }\n\n setPendingOperationFromTab(tab: TabKind): void {\n this._pendingOperation = tab === 'login' ? 'authenticate' : 'register';\n }\n\n get pendingOperation(): PendingAuthOperation {\n return this._pendingOperation;\n }\n\n setNonce(nonce: string | undefined): void {\n this._currentNonce = nonce;\n }\n\n consumeCancelledDetailIfAuthenticating(): MellonOperationDetail | null {\n if (this._currentState !== 'AUTHENTICATING') return null;\n const detail: MellonOperationDetail = {\n operation: this._pendingOperation === 'authenticate' ? 'login' : this._pendingOperation,\n ...(this._currentNonce !== undefined && { nonce: this._currentNonce }),\n };\n this._currentNonce = undefined;\n return detail;\n }\n\n handleAuthSuccess(): void {\n const next = authUiApplicationService.tryHandleAuthSuccess(this._currentState);\n if (next === null) return;\n this.setState(next);\n }\n\n handleAuthError(): void {\n const next = authUiApplicationService.tryHandleAuthError(this._currentState);\n if (next === null) return;\n this.setState(next);\n }\n\n onStartEvent(detail: MellonOperationDetail | undefined): void {\n if (detail?.nonce !== undefined) {\n this._currentNonce = detail.nonce;\n }\n }\n\n startAuthFromClick(core: CoreAuthPort | null, tab: TabKind, options?: CoreAuthOptions): void {\n if (!core) return;\n if (!canStartAuth(this._currentState)) return;\n this.setPendingOperationFromTab(tab);\n const next = authUiApplicationService.startAuth(\n this._currentState,\n tabToUIMode(tab),\n core,\n options\n );\n this.setState(next);\n }\n\n async runEnvEval(params: Omit<RunEnvEvalParams, 'currentState'>): Promise<UIState | null> {\n const requestId = ++this._envEvalRequestId;\n this.setState(authUiApplicationService.envEvalStart(this._currentState));\n const nextState = await authUiApplicationService.evaluateEnv({\n ...params,\n currentState: this._currentState,\n });\n if (requestId !== this._envEvalRequestId) {\n return null;\n }\n return nextState;\n }\n\n reset(): void {\n this._currentState = authUiApplicationService.reset(this._currentState);\n this._lastRenderedState = null;\n this._renderDirty = true;\n this._currentNonce = undefined;\n }\n\n setStateForRender(state: UIState): void {\n this._currentState = state;\n this._renderDirty = true;\n }\n}\n","/**\n * Abstract base for <trymellon-auth> and <trymellon-auth-modal>. Shared lifecycle: teardown, host/fallback listeners, Mellon handlers, env eval.\n * AuthController encapsulates FSM/env-eval; this base wires it to HTMLElement and DOM events.\n */\nimport type { UIState, TabKind } from '../domain/types';\nimport { createEnvStatusPortFromCore } from '../adapters/infra/env-status.adapter';\nimport { eventBridgeAdapter } from '../adapters/infra/event-bridge.adapter';\nimport type {\n CoreAuthPort,\n MellonFallbackDetail,\n MellonOperationDetail,\n} from '../ports/core-events.port';\nimport { createCoreForUI, isCoreAuthPort } from '../adapters/infra/core-factory.adapter';\nimport type { CoreConfig } from '../adapters/infra/core-factory.adapter';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\nimport { createMellonCancelledEvent, createMellonFallbackEvent } from './ui-events';\nimport { AuthController } from './auth-controller';\n\n/**\n * Abstract base: FSM, core, event bridge, env eval, fallback/shadow click.\n * Subclasses define observedAttributes, parsing, _render() and (modal only) open/tab.\n * Render flow: setState / invalidateRender → scheduleRenderIfNeeded → _render (single path).\n */\nexport abstract class AuthElementBase extends HTMLElement {\n protected _controller = new AuthController();\n protected _unsubscribeBridge: (() => void) | null = null;\n protected _core: CoreAuthPort | null = null;\n protected _lastCoreConfig: CoreConfig | null = null;\n\n /** Encapsulates state assignment and schedules render. Single canonical way to change _currentState and trigger _render. */\n protected setState(next: UIState): void {\n this._controller.setState(next);\n this.scheduleRenderIfNeeded();\n }\n\n /** Marks that a re-render is needed even if FSM state did not change (e.g. theme or props). */\n protected invalidateRender(): void {\n this._controller.invalidateRender();\n this.scheduleRenderIfNeeded();\n }\n\n /** Compares current state with last render; if changed or dirty, calls _render and updates cache. */\n protected scheduleRenderIfNeeded(): void {\n if (!this.shadowRoot) return;\n if (!this._controller.consumeRenderDecision()) return;\n this._render();\n }\n\n /** If state was AUTHENTICATING: build detail, dispatch mellon:cancelled, clear nonce; return true. Else false. */\n protected _emitCancelledIfAuthenticating(): boolean {\n const detail = this._controller.consumeCancelledDetailIfAuthenticating();\n if (!detail) return false;\n this.dispatchEvent(createMellonCancelledEvent(detail));\n return true;\n }\n\n /**\n * Injects auth core and starts env eval. Pass null to detach and transition to IDLE.\n * Multi-write safe: teardown existing core before attaching new one. Host must call reset() before re-open if WC stays in DOM.\n * @param core - CoreAuthPort-compatible instance, or null to detach.\n */\n attachCore(core: unknown): void {\n if (this._core !== null) {\n this._teardownCore();\n }\n if (core == null) {\n this._core = null;\n this._controller.reset();\n this.scheduleRenderIfNeeded();\n return;\n }\n if (!isCoreAuthPort(core)) {\n throw new Error('[trymellon-auth] attachCore requires a CoreAuthPort-compatible instance.');\n }\n this._core = core;\n this._unsubscribeBridge = eventBridgeAdapter.subscribe(this._core, this);\n this._attachHostListeners();\n this._runEnvEval();\n }\n\n protected _teardownCore(): void {\n this._unsubscribeBridge?.();\n this._unsubscribeBridge = null;\n this.removeEventListener('mellon:start', this._onMellonStart);\n this.removeEventListener('mellon:success', this._onMellonSuccess);\n this.removeEventListener('mellon:error', this._onMellonError);\n this._core = null;\n }\n\n protected _attachHostListeners(): void {\n this.removeEventListener('mellon:start', this._onMellonStart);\n this.removeEventListener('mellon:success', this._onMellonSuccess);\n this.removeEventListener('mellon:error', this._onMellonError);\n this.addEventListener('mellon:start', this._onMellonStart);\n this.addEventListener('mellon:success', this._onMellonSuccess);\n this.addEventListener('mellon:error', this._onMellonError);\n }\n\n protected _onMellonSuccess = (): void => {\n this._controller.handleAuthSuccess();\n this.scheduleRenderIfNeeded();\n };\n\n protected _onMellonError = (): void => {\n this._controller.handleAuthError();\n this.scheduleRenderIfNeeded();\n };\n\n protected _onMellonStart = (e: Event): void => {\n const detail = (e as CustomEvent<MellonOperationDetail>).detail;\n this._controller.onStartEvent(detail);\n };\n\n /**\n * Semantic logic for \"click on primary auth button\". Subclasses register DOM delegation\n * (e.g. adapters/interactions/dom.adapter) and call this method from the callback.\n */\n protected startAuthFromClick(): void {\n if (!this._core) return;\n if (!this.canStartAuth()) return;\n this._controller.startAuthFromClick(this._core, this.getTabKind(), this.getCoreAuthOptions());\n this.scheduleRenderIfNeeded();\n }\n\n /**\n * Emits mellon:fallback. With type = email|qr sets detail.fallbackType; without type (generic \"Continue\") does not set fallbackType.\n */\n protected dispatchFallback(type?: 'email' | 'qr'): void {\n const detail: MellonFallbackDetail =\n type !== undefined\n ? { ...this.getFallbackDetail(), fallbackType: type }\n : this.getFallbackDetail();\n this.dispatchEvent(createMellonFallbackEvent(detail));\n }\n\n protected async _runEnvEval(): Promise<void> {\n if (!this._core) return;\n const params: RunEnvEvalParams = {\n ...this.getEnvEvalParams(),\n envStatusPort: createEnvStatusPortFromCore(this._core),\n // currentState is injected by AuthController\n } as RunEnvEvalParams;\n const nextState = await this._controller.runEnvEval(params);\n if (nextState === null) return;\n if (!this._core || !this.isConnected) return;\n this.setState(nextState);\n }\n\n protected _maybeAutoCreateCoreAndRunEnvEval(): void {\n if (this._core !== null) return;\n const config = this.getCoreConfig();\n if (!config) return;\n const core = createCoreForUI(config);\n if (!core) {\n this.attachCore(null);\n return;\n }\n this.attachCore(core);\n }\n\n /** Single path: compare config with last, attach or detach core. No per-call special cases. */\n protected _reconcileCoreFromConfig(): void {\n const nextConfig = this.getCoreConfig();\n const sameConfig =\n (this._lastCoreConfig === null && nextConfig === null) ||\n (this._lastCoreConfig !== null &&\n nextConfig !== null &&\n this._lastCoreConfig.appId === nextConfig.appId &&\n this._lastCoreConfig.publishableKey === nextConfig.publishableKey);\n\n if (sameConfig) return;\n\n this._lastCoreConfig = nextConfig;\n\n if (nextConfig === null) {\n this.attachCore(null);\n return;\n }\n\n const core = createCoreForUI(nextConfig);\n this.attachCore(core ?? null);\n }\n\n disconnectedCallback(): void {\n this._teardownCore();\n }\n\n /** Current FSM state (read-only). */\n get currentState(): UIState {\n return this._controller.currentState;\n }\n\n /**\n * Transitions FSM to IDLE, clears in-flight ceremony, re-renders. If state was AUTHENTICATING, emits mellon:cancelled first.\n * Host must call reset() before re-open if WC remains in DOM after close.\n */\n reset(): void {\n this._emitCancelledIfAuthenticating();\n this._controller.reset();\n this.scheduleRenderIfNeeded();\n }\n\n /** Tests only: set state and re-render without FSM transition. */\n setStateForRender(state: UIState): void {\n this._controller.setStateForRender(state);\n this.scheduleRenderIfNeeded();\n }\n\n protected abstract getTabKind(): TabKind;\n protected abstract getCoreAuthOptions(): { externalUserId?: string | null };\n protected abstract canStartAuth(): boolean;\n protected abstract getEnvEvalParams(): Omit<RunEnvEvalParams, 'envStatusPort' | 'currentState'>;\n protected abstract getCoreConfig(): { appId: string; publishableKey: string } | null;\n protected abstract getFallbackDetail(): MellonFallbackDetail;\n protected abstract _render(): void;\n}\n","/**\n * Parses trymellon-auth-modal WC attributes.\n * Uses parseEnum + enum arrays and domain-centralized defaults.\n */\nimport type { ParsedModalAttributes, TabLabels } from '../../domain/contracts/types';\nimport {\n DEFAULT_MODAL_DISPLAY_MODE,\n DEFAULT_MODAL_VARIANT,\n DEFAULT_TAB,\n DEFAULT_TAB_LABELS,\n DEFAULT_THEME,\n} from '../../domain/contracts/constants';\nimport {\n MODAL_DISPLAY_MODES,\n MODAL_VARIANTS,\n TAB_KINDS,\n THEME_KINDS,\n FALLBACK_TYPES,\n} from '../../domain/validators/validators-state';\nimport { ensureParsedModalAttributes } from '../../domain/validators';\nimport {\n parseString,\n parseOptionalString,\n parseBoolean,\n parseOptionalBoolean,\n parseEnum,\n parseOptionalEnum,\n} from './parse.utils';\n\nexport type {\n FallbackTypeKind,\n ModalDisplayMode,\n ModalTabKind,\n ParsedModalAttributes,\n ThemeKind,\n} from '../../domain/contracts/types';\n\n/**\n * Parses tab-labels. Format: \"registerLabel,loginLabel\" (CSV). Missing or empty → domain defaults.\n */\nfunction parseTabLabels(value: string | null): TabLabels {\n if (value == null || value.trim() === '') return DEFAULT_TAB_LABELS;\n const parts = value.split(',').map((p) => p.trim());\n const register = parts[0] ?? DEFAULT_TAB_LABELS.register;\n const login = parts[1] ?? DEFAULT_TAB_LABELS.login;\n return { register, login };\n}\n\n/**\n * Parses all modal attributes from element. Validates at boundary before return (adapter validates domain type).\n */\nexport function parseModalAttributesFromElement(element: HTMLElement): ParsedModalAttributes {\n const raw = {\n open: parseBoolean(element.getAttribute('open')),\n mode: parseEnum(element.getAttribute('mode'), MODAL_DISPLAY_MODES, DEFAULT_MODAL_DISPLAY_MODE),\n tab: parseEnum(element.getAttribute('tab'), TAB_KINDS, DEFAULT_TAB),\n tabLabels: parseTabLabels(element.getAttribute('tab-labels')),\n theme: parseEnum(element.getAttribute('theme'), THEME_KINDS, DEFAULT_THEME),\n sessionId: parseOptionalString(element.getAttribute('session-id')),\n onboardingUrl: parseOptionalString(element.getAttribute('onboarding-url')),\n isMobileOverride: parseOptionalBoolean(element.getAttribute('is-mobile-override')),\n fallbackType: parseOptionalEnum(element.getAttribute('fallback-type'), FALLBACK_TYPES),\n appId: parseString(element.getAttribute('app-id')),\n publishableKey: parseString(element.getAttribute('publishable-key')),\n appName: parseOptionalString(element.getAttribute('app-name')),\n dialogTitle: parseOptionalString(element.getAttribute('dialog-title')),\n dialogDescription: parseOptionalString(element.getAttribute('dialog-description')),\n externalUserId: parseOptionalString(element.getAttribute('external-user-id')),\n modalVariant: parseEnum(\n element.getAttribute('modal-variant'),\n MODAL_VARIANTS,\n DEFAULT_MODAL_VARIANT\n ),\n };\n return ensureParsedModalAttributes(raw);\n}\n","/**\n * Modal DOM structure: overlay (when mode=modal), panel, tabs, content wrapper (slot cross-device + default slot with #mellon-root), fallback-cta slot.\n * createElement/setAttribute/appendChild only. FSM content from shadow.adapter render(). ARIA: dialog on panel, tablist on tabs.\n * Constants: render/constants.ts.\n */\nimport type { ParsedModalAttributes } from '../../domain/contracts/types';\nimport {\n MELLON_ROOT_ID,\n WRAPPER_CLASS,\n OVERLAY_CLASS,\n PANEL_CLASS,\n TABS_CLASS,\n CONTENT_WRAPPER_CLASS,\n SLOT_CROSS_DEVICE,\n SLOT_FALLBACK_CTA,\n MELLON_DIALOG_TITLE_ID,\n MELLON_DIALOG_DESC_ID,\n DIALOG_TITLE_TEXT,\n DIALOG_TITLE_WITH_APP,\n DIALOG_DESC_TEXT,\n MODAL_SEPARATOR_TEXT,\n CROSS_DEVICE_WRAP_CLASS,\n MODAL_SEPARATOR_CLASS,\n CROSS_DEVICE_CTA_TEXT,\n CROSS_DEVICE_CTA_CLASS,\n CROSS_DEVICE_QR_BUTTON_ARIA_LABEL,\n MELLON_ACTION_FALLBACK_QR,\n MELLON_QR_SKELETON_CLASS,\n MELLON_QR_ERROR_CLASS,\n MELLON_QR_SLOT_WRAP_CLASS,\n QR_SKELETON_TEXT,\n QR_TIMEOUT_ERROR_TEXT,\n SVG_NS,\n MODAL_CLOSE_BUTTON_CLASS,\n MODAL_CLOSE_BUTTON_ARIA_LABEL,\n} from './constants';\n\nexport { SLOT_CROSS_DEVICE, MELLON_DIALOG_TITLE_ID, MELLON_DIALOG_DESC_ID };\n\nfunction ensureWrapper(shadowRoot: ShadowRoot): HTMLElement {\n let wrapper = shadowRoot.querySelector<HTMLElement>(`.${WRAPPER_CLASS}`);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.className = WRAPPER_CLASS;\n shadowRoot.appendChild(wrapper);\n }\n return wrapper;\n}\n\nfunction ensureOverlay(wrapper: HTMLElement): HTMLElement {\n let overlay = wrapper.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (!overlay) {\n overlay = document.createElement('div');\n overlay.className = OVERLAY_CLASS;\n overlay.setAttribute('aria-hidden', 'true');\n wrapper.appendChild(overlay);\n }\n return overlay;\n}\n\nfunction ensurePanel(wrapper: HTMLElement): HTMLElement {\n let panel = wrapper.querySelector<HTMLElement>(`.${PANEL_CLASS}`);\n if (!panel) {\n panel = document.createElement('div');\n panel.className = PANEL_CLASS;\n wrapper.appendChild(panel);\n }\n return panel;\n}\n\n/** Panel as dialog: role, aria-modal, labelledby/describedby. */\nfunction setPanelDialogAria(panel: HTMLElement, mode: 'modal' | 'inline'): void {\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', mode === 'modal' ? 'true' : 'false');\n panel.setAttribute('aria-labelledby', MELLON_DIALOG_TITLE_ID);\n panel.setAttribute('aria-describedby', MELLON_DIALOG_DESC_ID);\n}\n\n/** Creates or reuses dialog title and description; inserts at panel start. Uses dialog-title/dialog-description when set, else app-name + defaults. */\nfunction ensureDialogTitleAndDescription(panel: HTMLElement, parsed: ParsedModalAttributes): void {\n let titleEl = panel.querySelector<HTMLElement>(`#${MELLON_DIALOG_TITLE_ID}`);\n if (!titleEl) {\n titleEl = document.createElement('h2');\n titleEl.id = MELLON_DIALOG_TITLE_ID;\n titleEl.className = 'mellon-dialog-title';\n panel.insertBefore(titleEl, panel.firstChild);\n }\n const titleText =\n parsed.dialogTitle?.trim() ??\n (parsed.appName?.trim() ? DIALOG_TITLE_WITH_APP(parsed.appName.trim()) : DIALOG_TITLE_TEXT);\n titleEl.textContent = titleText;\n\n let descEl = panel.querySelector<HTMLElement>(`#${MELLON_DIALOG_DESC_ID}`);\n if (!descEl) {\n descEl = document.createElement('p');\n descEl.id = MELLON_DIALOG_DESC_ID;\n descEl.className = 'mellon-dialog-desc';\n panel.insertBefore(descEl, titleEl.nextSibling);\n }\n descEl.textContent = parsed.dialogDescription?.trim() ?? DIALOG_DESC_TEXT;\n}\n\n/** Close button (visual 'X') in top-right corner of the modal panel. */\nfunction ensureCloseButton(panel: HTMLElement): void {\n let btn = panel.querySelector<HTMLButtonElement>(`.${MODAL_CLOSE_BUTTON_CLASS}`);\n if (btn) return;\n btn = document.createElement('button');\n btn.type = 'button';\n btn.className = MODAL_CLOSE_BUTTON_CLASS;\n btn.setAttribute('aria-label', MODAL_CLOSE_BUTTON_ARIA_LABEL);\n btn.setAttribute('data-mellon-modal-close', 'true');\n btn.textContent = '×';\n panel.appendChild(btn);\n}\n\nfunction ensureTabs(\n panel: HTMLElement,\n tabLabels: { register: string; login: string }\n): HTMLElement {\n let tabs = panel.querySelector<HTMLElement>(`.${TABS_CLASS}`);\n if (!tabs) {\n tabs = document.createElement('div');\n tabs.className = TABS_CLASS;\n tabs.setAttribute('role', 'tablist');\n const btnRegister = document.createElement('button');\n btnRegister.type = 'button';\n btnRegister.setAttribute('data-tab', 'register');\n btnRegister.setAttribute('role', 'tab');\n const btnLogin = document.createElement('button');\n btnLogin.type = 'button';\n btnLogin.setAttribute('data-tab', 'login');\n btnLogin.setAttribute('role', 'tab');\n tabs.appendChild(btnRegister);\n tabs.appendChild(btnLogin);\n const afterDesc = panel.querySelector<HTMLElement>(`#${MELLON_DIALOG_DESC_ID}`);\n panel.insertBefore(tabs, afterDesc ? afterDesc.nextSibling : panel.firstChild);\n }\n const [btnRegister, btnLogin] = tabs.querySelectorAll('button');\n if (btnRegister) btnRegister.textContent = tabLabels.register;\n if (btnLogin) btnLogin.textContent = tabLabels.login;\n return tabs;\n}\n\n/** Content wrapper: cross-device slot (QR) + default slot (mellon-root). Same structure as landing: QR above, Try Passkey below. */\nfunction ensureModalContentWrapper(panel: HTMLElement): HTMLElement {\n let wrapper = panel.querySelector<HTMLElement>(`.${CONTENT_WRAPPER_CLASS}`);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.className = CONTENT_WRAPPER_CLASS;\n const afterTabs = panel.querySelector(`.${TABS_CLASS}`);\n panel.insertBefore(wrapper, afterTabs ? afterTabs.nextSibling : panel.firstChild);\n }\n return wrapper;\n}\n\n/** QR code icon as inline SVG (icon-only button). */\nfunction createQrIconSVG(): SVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('class', 'mellon-qr-icon');\n svg.setAttribute('fill', 'currentColor');\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute(\n 'd',\n 'M3 3h6v6H3V3zm2 2v2h2V5H5zm8-2h6v6h-6V3zm2 2v2h2V5h-2zM3 15h6v6H3v-6zm2 2v2h2v-2H5zm8-2h6v6h-6v-6zm2 2v2h2v-2h-2zm4-12h2v2h-2V5zm0 8h2v2h-2v-2zm-4 4h2v2h-2v-2zm0-8h2v2h-2V9zm0 4h2v2h-2v-2z'\n );\n svg.appendChild(path);\n return svg;\n}\n\n/** Default content for cross-device slot: CTA text + icon-only QR button. Shown when host does not inject QR; click dispatches fallback qr. */\nfunction createCrossDeviceDefaultContent(): DocumentFragment {\n const frag = document.createDocumentFragment();\n const wrap = document.createElement('div');\n wrap.className = CROSS_DEVICE_CTA_CLASS;\n const p = document.createElement('p');\n p.className = 'mellon-cross-device-cta-text';\n p.textContent = CROSS_DEVICE_CTA_TEXT;\n wrap.appendChild(p);\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn mellon-btn-qr-icon';\n btn.setAttribute('data-mellon-action', MELLON_ACTION_FALLBACK_QR);\n btn.setAttribute('aria-label', CROSS_DEVICE_QR_BUTTON_ARIA_LABEL);\n btn.appendChild(createQrIconSVG());\n wrap.appendChild(btn);\n frag.appendChild(wrap);\n return frag;\n}\n\n/** Skeleton node (modal-owned): shown when waiting for host-injected QR. */\nfunction createQrSkeletonNode(): HTMLElement {\n const el = document.createElement('div');\n el.className = MELLON_QR_SKELETON_CLASS;\n el.setAttribute('aria-live', 'polite');\n const label = document.createElement('span');\n label.textContent = QR_SKELETON_TEXT;\n const dots = document.createElement('span');\n dots.className = 'mellon-qr-dots';\n dots.setAttribute('aria-hidden', 'true');\n el.appendChild(label);\n el.appendChild(dots);\n return el;\n}\n\n/** Error node (modal-owned): shown when QR load times out. */\nfunction createQrErrorNode(): HTMLElement {\n const el = document.createElement('div');\n el.className = MELLON_QR_ERROR_CLASS;\n el.setAttribute('aria-live', 'polite');\n el.textContent = QR_TIMEOUT_ERROR_TEXT;\n return el;\n}\n\n/** Wrapper + slot for cross-device UI. Includes skeleton (waiting) and error (timeout); slot shows default CTA or host-injected QR. */\nfunction ensureCrossDeviceSlot(panel: HTMLElement): HTMLSlotElement {\n const wrapper = ensureModalContentWrapper(panel);\n let wrap = wrapper.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (!wrap) {\n wrap = document.createElement('div');\n wrap.className = CROSS_DEVICE_WRAP_CLASS;\n wrap.setAttribute('data-qr-area-state', 'default');\n\n wrap.appendChild(createQrSkeletonNode());\n wrap.appendChild(createQrErrorNode());\n\n const slotWrap = document.createElement('div');\n slotWrap.className = MELLON_QR_SLOT_WRAP_CLASS;\n const slot = document.createElement('slot');\n slot.name = SLOT_CROSS_DEVICE;\n slot.appendChild(createCrossDeviceDefaultContent());\n slotWrap.appendChild(slot);\n wrap.appendChild(slotWrap);\n\n wrapper.appendChild(wrap);\n }\n const slot = wrap.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_CROSS_DEVICE}\"]`);\n if (!slot) {\n const created = document.createElement('slot');\n created.name = SLOT_CROSS_DEVICE;\n created.appendChild(createCrossDeviceDefaultContent());\n wrap.appendChild(created);\n return created;\n }\n return slot;\n}\n\n/** Separator: continuous lines with \"or\" centered between them. */\nfunction ensureSeparator(panel: HTMLElement): void {\n const wrapper = ensureModalContentWrapper(panel);\n if (wrapper.querySelector(`.${MODAL_SEPARATOR_CLASS}`)) return;\n const sep = document.createElement('div');\n sep.className = MODAL_SEPARATOR_CLASS;\n sep.setAttribute('aria-hidden', 'true');\n const span = document.createElement('span');\n span.className = 'mellon-separator-text';\n span.textContent = MODAL_SEPARATOR_TEXT;\n sep.appendChild(span);\n const wrap = wrapper.querySelector(`.${CROSS_DEVICE_WRAP_CLASS}`);\n wrapper.insertBefore(sep, wrap ? wrap.nextSibling : wrapper.firstChild);\n}\n\n/** Default slot: main content; fallback #mellon-root when host does not inject. Lives inside content wrapper. */\nfunction ensureDefaultSlotWithRoot(panel: HTMLElement): HTMLElement {\n const wrapper = ensureModalContentWrapper(panel);\n let slot = wrapper.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) {\n slot = document.createElement('slot');\n const root = document.createElement('div');\n root.id = MELLON_ROOT_ID;\n root.className = 'mellon-root';\n slot.appendChild(root);\n wrapper.appendChild(slot);\n }\n let root = panel.querySelector<HTMLElement>(`#${MELLON_ROOT_ID}`);\n if (!root) {\n root = document.createElement('div');\n root.id = MELLON_ROOT_ID;\n root.className = 'mellon-root';\n slot.appendChild(root);\n }\n return root;\n}\n\nfunction ensureFallbackSlot(panel: HTMLElement): HTMLSlotElement {\n let slot = panel.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_FALLBACK_CTA}\"]`);\n if (!slot) {\n slot = document.createElement('slot');\n slot.name = SLOT_FALLBACK_CTA;\n panel.appendChild(slot);\n }\n return slot;\n}\n\n/** Syncs active tab on buttons (aria-selected). Does not control wrapper/overlay visibility (WC responsibility via open/mode). */\nfunction syncTabAriaSelected(panel: HTMLElement, activeTab: 'register' | 'login'): void {\n const tabs = panel.querySelector<HTMLElement>(`.${TABS_CLASS}`);\n if (!tabs) return;\n const reg = tabs.querySelector<HTMLButtonElement>('[data-tab=\"register\"]');\n const log = tabs.querySelector<HTMLButtonElement>('[data-tab=\"login\"]');\n if (reg) reg.setAttribute('aria-selected', String(activeTab === 'register'));\n if (log) log.setAttribute('aria-selected', String(activeTab === 'login'));\n}\n\n/** Ensures modal structure: wrapper, overlay when mode=modal, panel, tabs, #mellon-root, fallback-cta slot, tab aria-selected. Visibility (open/mode) is WC responsibility. */\nfunction ensureModalStructure(shadowRoot: ShadowRoot, parsed: ParsedModalAttributes): void {\n if (shadowRoot == null || parsed == null) return;\n const wrapper = ensureWrapper(shadowRoot);\n wrapper.setAttribute('data-mellon-modal-variant', parsed.modalVariant);\n if (parsed.mode === 'modal') {\n ensureOverlay(wrapper);\n }\n const panel = ensurePanel(wrapper);\n setPanelDialogAria(panel, parsed.mode);\n ensureDialogTitleAndDescription(panel, parsed);\n ensureCloseButton(panel);\n ensureTabs(panel, parsed.tabLabels);\n ensureCrossDeviceSlot(panel);\n ensureSeparator(panel);\n ensureDefaultSlotWithRoot(panel);\n ensureFallbackSlot(panel);\n syncTabAriaSelected(panel, parsed.tab);\n}\n\nexport { ensureModalStructure };\n","/**\n * Focus trap: keeps focus inside a container. Tab/Shift+Tab cycle within; deactivate restores focus to previous element or body.\n * Used by adapters; WC in presentation only calls activate/deactivate.\n * Constants: interactions/constants.ts.\n */\nimport { FOCUSABLE_SELECTOR } from './constants';\n\n/** Excludes hidden elements; avoids offsetParent (often null in jsdom shadow). */\nfunction isFocusableCandidate(el: HTMLElement): boolean {\n if ((el as unknown as { hidden?: boolean }).hidden === true) return false;\n if (el.getAttribute('aria-hidden') === 'true') return false;\n return true;\n}\n\n/** Returns focusable elements inside container in document order (visible only). */\nexport function getFocusables(container: HTMLElement): HTMLElement[] {\n const candidates = Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n return candidates.filter((el) => isFocusableCandidate(el));\n}\n\nexport interface FocusTrapHandle {\n activate(): void;\n deactivate(): void;\n}\n\n/**\n * Creates a focus trap on container. activate(): store activeElement, focus first focusable, add Tab keydown.\n * deactivate(): remove listener, restore focus to stored element if still in document, else body.\n */\nexport function createFocusTrap(container: HTMLElement): FocusTrapHandle {\n let previousActiveElement: Element | null = null;\n let keydownBound: ((e: KeyboardEvent) => void) | null = null;\n let isActive = false;\n\n function handleKeydown(e: KeyboardEvent): void {\n if (e.key !== 'Tab') return;\n const focusables = getFocusables(container);\n if (focusables.length === 0) return;\n const current = e.target instanceof Node ? (e.target as HTMLElement) : null;\n const currentIndex = current ? focusables.indexOf(current) : -1;\n const lastIndex = focusables.length - 1;\n let nextIndex: number;\n if (e.shiftKey) {\n nextIndex = currentIndex <= 0 ? lastIndex : currentIndex - 1;\n } else {\n nextIndex = currentIndex >= lastIndex ? 0 : currentIndex + 1;\n }\n const next = focusables[nextIndex];\n if (next) {\n e.preventDefault();\n next.focus();\n }\n }\n\n function activate(): void {\n if (isActive) return;\n previousActiveElement = document.activeElement;\n const focusables = getFocusables(container);\n const first = focusables[0];\n if (first) {\n first.focus();\n }\n keydownBound = handleKeydown;\n container.addEventListener('keydown', keydownBound, true);\n isActive = true;\n }\n\n function deactivate(): void {\n if (!isActive) return;\n if (keydownBound) {\n container.removeEventListener('keydown', keydownBound, true);\n keydownBound = null;\n }\n isActive = false;\n const doc = (container.getRootNode() as Document | ShadowRoot)?.ownerDocument ?? document;\n const toRestore =\n previousActiveElement instanceof HTMLElement && doc.body.contains(previousActiveElement)\n ? previousActiveElement\n : null;\n if (toRestore) {\n toRestore.focus();\n } else {\n const body = doc.body as HTMLElement;\n const prevTabindex = body.getAttribute('tabindex');\n body.setAttribute('tabindex', '-1');\n body.focus();\n if (prevTabindex === null) body.removeAttribute('tabindex');\n else body.setAttribute('tabindex', prevTabindex);\n }\n previousActiveElement = null;\n }\n\n return { activate, deactivate };\n}\n","/**\n * Centralized constants for the presentation layer (WC elements).\n * Attribute names, modal DOM selectors, close reasons. Single source — no magic strings.\n * Selector class names must match render layer (styles.adapter, modal-structure.adapter).\n */\n\n// --- Modal DOM selectors (class names aligned with render/constants WRAPPER_CLASS, etc.) ---\nconst MODAL_WRAPPER_CLASS = 'mellon-modal-wrapper';\nconst MODAL_OVERLAY_CLASS = 'mellon-modal-overlay';\nconst MODAL_PANEL_CLASS = 'mellon-modal-panel';\n\n// --- Observed attribute names (public API) ---\n\nexport const OBSERVED_ATTRIBUTES_AUTH = [\n 'app-id',\n 'publishable-key',\n 'mode',\n 'external-user-id',\n 'theme',\n 'action',\n 'trigger-only',\n 'button-variant',\n] as const;\n\nexport const OBSERVED_ATTRIBUTES_MODAL = [\n 'open',\n 'mode',\n 'tab',\n 'tab-labels',\n 'theme',\n 'session-id',\n 'onboarding-url',\n 'is-mobile-override',\n 'fallback-type',\n 'app-id',\n 'publishable-key',\n 'app-name',\n 'dialog-title',\n 'dialog-description',\n 'external-user-id',\n 'modal-variant',\n 'qr-load-timeout-ms',\n] as const;\n\n// --- Modal DOM selectors ---\n\nexport const MODAL_SELECTORS = {\n wrapper: `.${MODAL_WRAPPER_CLASS}`,\n overlay: `.${MODAL_OVERLAY_CLASS}`,\n panel: `.${MODAL_PANEL_CLASS}`,\n} as const;\n\n// --- Close / event reasons ---\n\nexport const MELLON_CLOSE_REASON_DEFAULT = 'user' as const;\n","/**\n * Web Component <trymellon-auth-modal>. Public API per 01-limites-api-publica.md.\n * Extends AuthElementBase; attributes, parsing, modal structure, open/tab and _render only.\n */\nimport type { UIState, TabKind } from '../domain/types';\nimport { tabToUIMode } from '../domain/types';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\nimport { authUiApplicationService } from '../application/auth-ui.application-service';\nimport type { ParsedModalAttributes } from '../adapters/attributes/modal.adapter';\nimport { parseModalAttributesFromElement } from '../adapters/attributes/modal.adapter';\nimport { ensureModalStructure } from '../adapters/render/modal-structure.adapter';\nimport { createFocusTrap, type FocusTrapHandle } from '../adapters/interactions/focus-trap.adapter';\nimport { buildAuthModalViewModel } from '../domain/auth-viewmodels';\nimport { renderAuthModal } from '../adapters/render/auth.adapter';\nimport { registerAuthModalInteractions } from '../adapters/interactions/dom.adapter';\nimport { MODAL_PASSKEY_ARIA_LABEL, MODAL_PASSKEY_BUTTON_LABEL } from '../adapters/render/constants';\nimport {\n createModalConstructableStylesheet,\n getModalStylesFallback,\n} from '../adapters/render/styles.adapter';\nimport type { IRenderSurface } from '../ports/render.port';\nimport type { MellonCloseDetail, MellonFallbackDetail, MellonOpenDetail } from '../ports';\nimport {\n createMellonCloseEvent,\n createMellonOpenEvent,\n createMellonTabChangeEvent,\n} from './ui-events';\nimport { AuthElementBase } from './auth-element-base';\nimport {\n OBSERVED_ATTRIBUTES_MODAL,\n MODAL_SELECTORS,\n MELLON_CLOSE_REASON_DEFAULT,\n} from './constants';\nimport {\n CROSS_DEVICE_WRAP_CLASS,\n SLOT_CROSS_DEVICE,\n QR_LOAD_TIMEOUT_MS_DEFAULT,\n} from '../adapters/render/constants';\n\n/** State → close reason. Lookup only; default handles all unmapped states (good taste: no special-case ifs). */\nconst CLOSE_REASON_BY_STATE: Partial<Record<UIState, MellonCloseDetail>> = {\n SUCCESS: { reason: 'success' },\n AUTHENTICATING: { reason: 'cancel' },\n ERROR: { reason: 'error' },\n};\n\nfunction closeDetailFromState(state: UIState): MellonCloseDetail {\n const mapped = CLOSE_REASON_BY_STATE[state];\n return mapped ?? { reason: MELLON_CLOSE_REASON_DEFAULT };\n}\n\nexport class TryMellonAuthModalElement extends AuthElementBase {\n static get observedAttributes(): string[] {\n return [...OBSERVED_ATTRIBUTES_MODAL];\n }\n\n protected _parsed: ParsedModalAttributes = parseModalAttributesFromElement(this as HTMLElement);\n private _focusTrap: FocusTrapHandle | null = null;\n private _unregisterInteractions: (() => void) | null = null;\n /** When external-user-id is not set, register uses this UUID so backend can notify client without external UI. */\n private _generatedExternalUserId: string | null = null;\n private _qrLoadTimeoutId: number | null = null;\n private _qrSlotChangeBound: (() => void) | null = null;\n\n /** Escape closes modal via same path as open=false → _transitionToIdle. */\n private _boundEscapeKeydown = (e: KeyboardEvent): void => {\n if (e.key !== 'Escape') return;\n if (!this._parsed.open) return;\n e.preventDefault();\n this.open = false;\n };\n\n connectedCallback(): void {\n this.addEventListener('keydown', this._boundEscapeKeydown, true);\n if (this.shadowRoot) {\n this._registerInteractions();\n if (this._core !== null && this._unsubscribeBridge === null) {\n this.attachCore(this._core);\n }\n return;\n }\n\n const shadow = this.attachShadow({ mode: 'open' });\n\n const sheet = createModalConstructableStylesheet();\n if (sheet) {\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const styleEl = document.createElement('style');\n styleEl.textContent = getModalStylesFallback();\n shadow.appendChild(styleEl);\n }\n\n this._parsed = parseModalAttributesFromElement(this);\n ensureModalStructure(shadow, this._parsed);\n this._registerInteractions();\n this._render();\n this._applyModalVisibility();\n this._maybeAutoCreateCoreAndRunEnvEval();\n }\n\n private _registerInteractions(): void {\n if (!this.shadowRoot) return;\n this._unregisterInteractions?.();\n this._unregisterInteractions = registerAuthModalInteractions(this.shadowRoot, {\n onTabChange: (tab) => {\n this.dispatchEvent(createMellonTabChangeEvent({ tab }));\n this.setAttribute('tab', tab);\n },\n onPrimaryClick: () => this.startAuthFromClick(),\n onFallbackClick: (type) => this.dispatchFallback(type),\n onOverlayClick: () => {\n this.open = false;\n },\n onCloseClick: () => {\n this.open = false;\n },\n });\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, _newValue: string | null): void {\n if (!this.shadowRoot) return;\n this._parsed = parseModalAttributesFromElement(this);\n if (name === 'open') {\n if (this._parsed.open && oldValue !== 'true') {\n const detail: MellonOpenDetail = { timestamp: Date.now() };\n this.dispatchEvent(createMellonOpenEvent(detail));\n this._startQrLoadWait();\n }\n if (!this._parsed.open) {\n this._clearQrLoadWait();\n this._transitionToIdle();\n return;\n }\n }\n if (name === 'tab') {\n this._emitCancelledIfAuthenticating();\n this.setState(authUiApplicationService.tabChange(this.currentState, this._parsed.tab));\n }\n if (name === 'app-id' || name === 'publishable-key') {\n this._reconcileCoreFromConfig();\n }\n ensureModalStructure(this.shadowRoot, this._parsed);\n this._render();\n this._applyModalVisibility();\n }\n\n private _startQrLoadWait(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const wrap = root.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n const slot = root.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_CROSS_DEVICE}\"]`);\n if (!wrap || !slot) return;\n wrap.setAttribute('data-qr-area-state', 'waiting');\n const ms = Math.max(\n 1000,\n parseInt(this.getAttribute('qr-load-timeout-ms') ?? String(QR_LOAD_TIMEOUT_MS_DEFAULT), 10) ||\n QR_LOAD_TIMEOUT_MS_DEFAULT\n );\n this._qrLoadTimeoutId = window.setTimeout(() => {\n this._qrLoadTimeoutId = null;\n if (!this.shadowRoot) return;\n const wrapElement = this.shadowRoot.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (wrapElement?.getAttribute('data-qr-area-state') === 'waiting') {\n wrapElement.setAttribute('data-qr-area-state', 'timeout');\n }\n }, ms);\n const onSlotChange = (): void => {\n if (slot.assignedNodes().length > 0) {\n this._clearQrLoadWait();\n const w = this.shadowRoot?.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (w) w.setAttribute('data-qr-area-state', 'loaded');\n }\n };\n this._qrSlotChangeBound = onSlotChange;\n slot.addEventListener('slotchange', onSlotChange);\n if (slot.assignedNodes().length > 0) onSlotChange();\n }\n\n private _clearQrLoadWait(): void {\n if (this._qrLoadTimeoutId != null) {\n clearTimeout(this._qrLoadTimeoutId);\n this._qrLoadTimeoutId = null;\n }\n const root = this.shadowRoot;\n if (!root) return;\n const slot = root.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_CROSS_DEVICE}\"]`);\n if (slot && this._qrSlotChangeBound) {\n slot.removeEventListener('slotchange', this._qrSlotChangeBound);\n this._qrSlotChangeBound = null;\n }\n const wrap = root.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (wrap) wrap.setAttribute('data-qr-area-state', 'default');\n }\n\n /** Single path to IDLE: close event, cancelled if needed, reset FSM, structure, render, visibility. Called from open→false and reset(). */\n private _transitionToIdle(): void {\n this._generatedExternalUserId = null;\n const closeDetail = closeDetailFromState(this.currentState);\n const detail: MellonCloseDetail = { reason: closeDetail.reason, timestamp: Date.now() };\n this.dispatchEvent(createMellonCloseEvent(detail));\n this._emitCancelledIfAuthenticating();\n this.setState(authUiApplicationService.reset(this.currentState));\n if (!this.shadowRoot) return;\n ensureModalStructure(this.shadowRoot, this._parsed);\n this.scheduleRenderIfNeeded();\n this._applyModalVisibility();\n }\n\n get open(): boolean {\n return this._parsed.open;\n }\n set open(value: boolean) {\n this.setAttribute('open', value ? 'true' : 'false');\n }\n\n get mode(): 'modal' | 'inline' {\n return this._parsed.mode;\n }\n set mode(value: 'modal' | 'inline') {\n this.setAttribute('mode', value);\n }\n\n get tab(): 'register' | 'login' {\n return this._parsed.tab;\n }\n set tab(value: 'register' | 'login') {\n this.setAttribute('tab', value);\n }\n\n get tabLabels(): string {\n return `${this._parsed.tabLabels.register},${this._parsed.tabLabels.login}`;\n }\n set tabLabels(value: string | undefined) {\n if (value == null || value === '') this.removeAttribute('tab-labels');\n else this.setAttribute('tab-labels', value);\n }\n\n get theme(): 'light' | 'dark' {\n return this._parsed.theme;\n }\n set theme(value: 'light' | 'dark') {\n this.setAttribute('theme', value);\n }\n\n get sessionId(): string | null {\n return this._parsed.sessionId;\n }\n set sessionId(value: string | null) {\n if (value == null) this.removeAttribute('session-id');\n else this.setAttribute('session-id', value);\n }\n\n get onboardingUrl(): string | null {\n return this._parsed.onboardingUrl;\n }\n set onboardingUrl(value: string | null) {\n if (value == null) this.removeAttribute('onboarding-url');\n else this.setAttribute('onboarding-url', value);\n }\n\n get isMobileOverride(): boolean | null {\n return this._parsed.isMobileOverride;\n }\n set isMobileOverride(value: boolean | null) {\n if (value == null) this.removeAttribute('is-mobile-override');\n else this.setAttribute('is-mobile-override', value ? 'true' : 'false');\n }\n\n get fallbackType(): 'email' | 'qr' | undefined {\n return this._parsed.fallbackType;\n }\n set fallbackType(value: 'email' | 'qr' | undefined) {\n if (value == null) this.removeAttribute('fallback-type');\n else this.setAttribute('fallback-type', value);\n }\n\n get appId(): string {\n return this._parsed.appId;\n }\n set appId(value: string) {\n this.setAttribute('app-id', value ?? '');\n }\n\n get publishableKey(): string {\n return this._parsed.publishableKey;\n }\n set publishableKey(value: string) {\n this.setAttribute('publishable-key', value ?? '');\n }\n\n get appName(): string | null {\n return this._parsed.appName;\n }\n set appName(value: string | null) {\n if (value == null) this.removeAttribute('app-name');\n else this.setAttribute('app-name', value);\n }\n\n get dialogTitle(): string | null {\n return this._parsed.dialogTitle;\n }\n set dialogTitle(value: string | null) {\n if (value == null) this.removeAttribute('dialog-title');\n else this.setAttribute('dialog-title', value);\n }\n\n get dialogDescription(): string | null {\n return this._parsed.dialogDescription;\n }\n set dialogDescription(value: string | null) {\n if (value == null) this.removeAttribute('dialog-description');\n else this.setAttribute('dialog-description', value);\n }\n\n get externalUserId(): string | null {\n return this._parsed.externalUserId;\n }\n set externalUserId(value: string | null) {\n if (value == null) this.removeAttribute('external-user-id');\n else this.setAttribute('external-user-id', value);\n }\n\n /**\n * Reset override: transitions to IDLE, clears ceremony and emits `mellon:cancelled` if was AUTHENTICATING.\n * Also emits `mellon:close` with the reason for the current state (success | cancel | error | user).\n * Host must call `reset()` before reopening if the WC stays in the DOM for a clean state.\n */\n override disconnectedCallback(): void {\n this._unregisterInteractions?.();\n this._unregisterInteractions = null;\n this.removeEventListener('keydown', this._boundEscapeKeydown, true);\n super.disconnectedCallback();\n }\n\n override reset(): void {\n this._transitionToIdle();\n }\n\n protected getTabKind(): TabKind {\n return this._parsed.tab;\n }\n\n protected getCoreAuthOptions(): { externalUserId?: string | null } {\n const externalUserId = this._resolveExternalUserId();\n return externalUserId ? { externalUserId } : {};\n }\n\n /** Single path: explicit attr > generated UUID for register > none. No special-case branches in getCoreAuthOptions. */\n private _resolveExternalUserId(): string | null {\n const explicit = this._parsed.externalUserId?.trim();\n if (explicit) return explicit;\n if (this.getTabKind() !== 'register') return null;\n this._generatedExternalUserId ??=\n typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : null;\n return this._generatedExternalUserId;\n }\n\n /** Passkey register is always allowed (external user id optional; SDK uses UUID when not set). */\n protected canStartAuth(): boolean {\n return true;\n }\n\n protected getEnvEvalParams(): Omit<RunEnvEvalParams, 'envStatusPort' | 'currentState'> {\n return {\n mode: tabToUIMode(this._parsed.tab),\n isMobileOverride: this._parsed.isMobileOverride ?? undefined,\n fallbackType: this._parsed.fallbackType,\n };\n }\n\n protected getCoreConfig(): { appId: string; publishableKey: string } | null {\n if (!this._parsed.appId || !this._parsed.publishableKey) return null;\n return { appId: this._parsed.appId, publishableKey: this._parsed.publishableKey };\n }\n\n protected getFallbackDetail(): MellonFallbackDetail {\n return { operation: this._parsed.tab };\n }\n\n /** Reflects open/mode in DOM (wrapper/overlay hidden). Syncs focus trap: activate when open, deactivate restores focus on close. */\n private _applyModalVisibility(): void {\n if (!this.shadowRoot) return;\n const wrapper = this.shadowRoot.querySelector<HTMLElement>(MODAL_SELECTORS.wrapper);\n if (wrapper) wrapper.hidden = !this._parsed.open;\n const overlay = this.shadowRoot.querySelector<HTMLElement>(MODAL_SELECTORS.overlay);\n if (overlay) overlay.hidden = this._parsed.mode !== 'modal';\n const panel = this.shadowRoot.querySelector<HTMLElement>(MODAL_SELECTORS.panel);\n if (panel) panel.setAttribute('aria-hidden', String(!this._parsed.open));\n\n if (this._parsed.open && wrapper) {\n if (!this._focusTrap) this._focusTrap = createFocusTrap(wrapper);\n this._focusTrap.activate();\n } else {\n this._focusTrap?.deactivate();\n }\n }\n\n protected _render(): void {\n if (!this.shadowRoot) return;\n ensureModalStructure(this.shadowRoot, this._parsed);\n this._applyModalVisibility();\n const vm = buildAuthModalViewModel(this.currentState, this._parsed, {\n registerSessionReady: this._parsed.tab === 'register' ? this.canStartAuth() : undefined,\n primaryButtonLabel: MODAL_PASSKEY_BUTTON_LABEL,\n primaryButtonAriaLabel: MODAL_PASSKEY_ARIA_LABEL,\n });\n const surface: IRenderSurface = { shadowRoot: this.shadowRoot };\n renderAuthModal(surface, vm);\n }\n}\n","/**\n * Web Component <trymellon-auth>. Shadow DOM open + attributes + render by state.\n * Option A (default): action=open-modal without trigger-only → emits mellon:open-request and shows internal modal.\n * Option B (escape hatch): trigger-only=\"true\" → only emits mellon:open-request; host mounts <trymellon-auth-modal> separately.\n */\nimport type { TabKind } from '../domain/types';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\nimport { authUiApplicationService } from '../application/auth-ui.application-service';\nimport { parseAttributesFromElement } from '../adapters/attributes/inline.adapter';\nimport type { ParsedAttributes } from '../adapters/attributes/inline.adapter';\nimport { DEFAULT_PARSED_ATTRIBUTES } from '../domain/contracts/constants';\nimport { buildAuthButtonViewModel } from '../domain/auth-viewmodels';\nimport { renderAuthButton } from '../adapters/render/auth.adapter';\nimport { registerAuthButtonInteractions } from '../adapters/interactions/dom.adapter';\nimport type { IRenderSurface } from '../ports/render.port';\nimport {\n createConstructableStylesheet,\n getStylesFallback,\n} from '../adapters/render/styles.adapter';\nimport type { MellonFallbackDetail } from '../ports';\nimport { toCoreAuthOptions } from '../adapters/infra/core-factory.adapter';\nimport { MELLON_CLOSE } from '../adapters/infra/event-bridge.adapter';\nimport { AuthElementBase } from './auth-element-base';\nimport { TryMellonAuthModalElement } from './trymellon-auth-modal.element';\nimport { OBSERVED_ATTRIBUTES_AUTH } from './constants';\nimport { MELLON_OPEN_REQUEST } from './ui-events';\n\nexport class TryMellonAuthElement extends AuthElementBase {\n static get observedAttributes(): string[] {\n return [...OBSERVED_ATTRIBUTES_AUTH];\n }\n\n protected _parsed: ParsedAttributes = { ...DEFAULT_PARSED_ATTRIBUTES };\n private _internalModal: TryMellonAuthModalElement | null = null;\n /** Element that opened the modal; single source for focus restore on close. */\n private _focusRestoreTarget: Element | null = null;\n private _unregisterInteractions: (() => void) | null = null;\n\n private _onInternalModalClose = (): void => {\n if (this._internalModal) this._internalModal.open = false;\n this._restoreFocusToTrigger();\n };\n\n private _restoreFocusToTrigger(): void {\n const el = this._focusRestoreTarget;\n this._focusRestoreTarget = null;\n if (!el?.isConnected || typeof (el as HTMLElement).focus !== 'function') return;\n (el as HTMLElement).focus();\n }\n\n connectedCallback(): void {\n if (this.shadowRoot) {\n this._registerInteractions();\n if (this._core !== null && this._unsubscribeBridge === null) {\n this.attachCore(this._core);\n }\n this._syncInternalModalAttributes();\n this._ensureInternalModal();\n return;\n }\n const shadow = this.attachShadow({ mode: 'open' });\n\n const sheet = createConstructableStylesheet();\n if (sheet) {\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const styleEl = document.createElement('style');\n styleEl.textContent = getStylesFallback();\n shadow.appendChild(styleEl);\n }\n\n this._parsed = parseAttributesFromElement(this);\n this._syncThemeAttribute();\n this._registerInteractions();\n this._render();\n this._reconcileCoreFromConfig();\n this._ensureInternalModal();\n }\n\n private _registerInteractions(): void {\n if (!this.shadowRoot) return;\n this._unregisterInteractions?.();\n this._unregisterInteractions = registerAuthButtonInteractions(this.shadowRoot, {\n onPrimaryClick: () => this._onPrimaryClick(),\n onFallbackClick: (type) => this.dispatchFallback(type),\n });\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, _newValue: string | null): void {\n if (!this.shadowRoot) return;\n const prevMode = this._parsed.mode;\n this._parsed = parseAttributesFromElement(this);\n if (name === 'button-variant' || name === 'theme') {\n this.invalidateRender();\n }\n if (name === 'app-id' || name === 'publishable-key') {\n this._reconcileCoreFromConfig();\n }\n if (name === 'mode' && (this._parsed.mode === 'register' || this._parsed.mode === 'login')) {\n const tab = this._parsed.mode;\n if (prevMode !== tab) {\n this._emitCancelledIfAuthenticating();\n this.setState(authUiApplicationService.tabChange(this.currentState, tab));\n }\n }\n this._syncThemeAttribute();\n this.scheduleRenderIfNeeded();\n this._syncInternalModalAttributes();\n this._ensureInternalModal();\n }\n\n private _onPrimaryClick(): void {\n if (this._parsed.action === 'open-modal') {\n this._focusRestoreTarget =\n document.activeElement instanceof Element ? document.activeElement : null;\n this.dispatchEvent(\n new CustomEvent(MELLON_OPEN_REQUEST, { detail: {}, bubbles: true, composed: true })\n );\n if (!this._parsed.triggerOnly && this._internalModal) this._internalModal.open = true;\n return;\n }\n this.startAuthFromClick();\n }\n\n protected getTabKind(): TabKind {\n return this._parsed.mode === 'auto' ? 'login' : this._parsed.mode;\n }\n\n protected getCoreAuthOptions(): { externalUserId?: string | null } {\n return toCoreAuthOptions(this._parsed.externalUserId);\n }\n\n protected canStartAuth(): boolean {\n return true;\n }\n\n protected getEnvEvalParams(): Omit<RunEnvEvalParams, 'envStatusPort' | 'currentState'> {\n return { mode: this._parsed.mode };\n }\n\n protected getCoreConfig(): { appId: string; publishableKey: string } | null {\n if (!this._parsed.appId || !this._parsed.publishableKey) return null;\n return { appId: this._parsed.appId, publishableKey: this._parsed.publishableKey };\n }\n\n protected getFallbackDetail(): MellonFallbackDetail {\n const operation =\n this._parsed.mode === 'login' || this._parsed.mode === 'register'\n ? this._parsed.mode\n : undefined;\n return operation !== undefined ? { operation } : {};\n }\n\n protected _render(): void {\n if (!this.shadowRoot) return;\n const vm = buildAuthButtonViewModel(this.currentState, this._parsed, {\n registerSessionReady: this._parsed.mode === 'register' ? this.canStartAuth() : undefined,\n });\n const surface: IRenderSurface = { shadowRoot: this.shadowRoot };\n renderAuthButton(surface, vm);\n }\n\n private _syncThemeAttribute(): void {\n if (this.getAttribute('theme') !== this._parsed.theme) {\n this.setAttribute('theme', this._parsed.theme);\n }\n }\n\n private _syncInternalModalAttributes(): void {\n if (!this._internalModal) return;\n this._internalModal.setAttribute('app-id', this._parsed.appId ?? '');\n this._internalModal.setAttribute('publishable-key', this._parsed.publishableKey ?? '');\n this._internalModal.setAttribute('theme', this._parsed.theme);\n const tab = this._parsed.mode === 'auto' ? 'login' : this._parsed.mode;\n this._internalModal.setAttribute('tab', tab);\n }\n\n private _ensureInternalModal(): void {\n if (this._parsed.action !== 'open-modal' || !this.shadowRoot) return;\n if (this._parsed.triggerOnly) {\n if (this._internalModal?.isConnected) {\n this._internalModal.removeEventListener(MELLON_CLOSE, this._onInternalModalClose);\n this._internalModal.remove();\n this._internalModal = null;\n }\n return;\n }\n if (this._internalModal?.isConnected) {\n this._syncInternalModalAttributes();\n return;\n }\n const modal = document.createElement('trymellon-auth-modal') as TryMellonAuthModalElement;\n this._internalModal = modal;\n this._syncInternalModalAttributes();\n modal.addEventListener(MELLON_CLOSE, this._onInternalModalClose);\n // Portal to body so overlay covers viewport; ancestors with transform/filter/backdrop-filter\n // would otherwise create a containing block and trap position:fixed (modal off to the side).\n if (typeof document !== 'undefined' && document.body) {\n document.body.appendChild(modal);\n } else {\n this.shadowRoot.appendChild(modal);\n }\n }\n\n override disconnectedCallback(): void {\n this._unregisterInteractions?.();\n this._unregisterInteractions = null;\n if (this._internalModal?.isConnected) {\n this._internalModal.removeEventListener(MELLON_CLOSE, this._onInternalModalClose);\n this._internalModal.remove();\n this._internalModal = null;\n }\n super.disconnectedCallback();\n }\n}\n","/** @trymellon/js/ui — Web Component entry. */\nimport { TryMellonAuthElement } from './presentation/trymellon-auth.element';\nimport { TryMellonAuthModalElement } from './presentation/trymellon-auth-modal.element';\n\nexport const UI_VERSION = '0.1.0';\n/** Canonical tag: button + internal modal (Option A) or trigger only (Option B with trigger-only). */\nexport const TRYMELLON_AUTH_TAG = 'trymellon-auth';\n/** Modal tag; used internally by <trymellon-auth> (Option A) or by host (Option B). */\nexport const TRYMELLON_AUTH_MODAL_TAG = 'trymellon-auth-modal';\n\nif (typeof customElements !== 'undefined' && !customElements.get(TRYMELLON_AUTH_TAG)) {\n customElements.define(TRYMELLON_AUTH_TAG, TryMellonAuthElement);\n}\nif (typeof customElements !== 'undefined' && !customElements.get(TRYMELLON_AUTH_MODAL_TAG)) {\n customElements.define(TRYMELLON_AUTH_MODAL_TAG, TryMellonAuthModalElement);\n}\n\nexport { TryMellonAuthElement, TryMellonAuthModalElement };\nexport { getNextState, INITIAL_UI_STATE } from './domain';\nexport {\n BASE_STYLES,\n createConstructableStylesheet,\n getStylesFallback,\n} from './adapters/render/styles.adapter';\nexport type { UIState, FSMEvent, EnvResolvedPayload, UIMode, TabKind } from './domain';\nexport type { ParsedAttributes, ThemeKind } from './adapters/attributes/inline.adapter';\nexport type { RenderOptions } from './ports';\nexport {\n eventBridgeAdapter,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n} from './adapters/infra/event-bridge.adapter';\nexport type {\n CoreWithEvents,\n CoreEventsPort,\n MellonSuccessDetail,\n MellonErrorDetail,\n MellonOperationDetail,\n MellonFallbackDetail,\n MellonOpenDetail,\n MellonCloseDetail,\n} from './ports';\n"],"mappings":"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","names":["resolveEnvState","payload","tabToReadyState","tab","getNextState","currentState","event","nextReady","INITIAL_UI_STATE","UI_STATES","UI_MODES","THEME_KINDS","TAB_KINDS","MODAL_DISPLAY_MODES","FALLBACK_TYPES","BUTTON_ACTIONS","BUTTON_VARIANTS","MODAL_VARIANTS","RECOMMENDED_FLOWS","isClientStatus","value","v","isOneOf","allowed","isUIState","UI_STATES","ensureUIState","INITIAL_UI_STATE","isUIMode","UI_MODES","isThemeKind","THEME_KINDS","isTabKind","TAB_KINDS","isModalDisplayMode","MODAL_DISPLAY_MODES","isButtonAction","BUTTON_ACTIONS","isButtonVariant","BUTTON_VARIANTS","isModalVariant","MODAL_VARIANTS","isEnvResolvedPayload","o","RECOMMENDED_FLOWS","FALLBACK_TYPES","isFSMEvent","t","DEFAULT_UI_MODE","DEFAULT_THEME","DEFAULT_MODAL_DISPLAY_MODE","DEFAULT_TAB","DEFAULT_TAB_LABELS","DEFAULT_BUTTON_ACTION","DEFAULT_BUTTON_VARIANT","DEFAULT_MODAL_VARIANT","DEFAULT_PARSED_ATTRIBUTES","DEFAULT_PARSED_MODAL_ATTRIBUTES","isParsedAttributes","value","o","isUIMode","isThemeKind","isButtonAction","isButtonVariant","isTabLabels","isParsedModalAttributes","isModalDisplayMode","isTabKind","isModalVariant","defaultParsedAttributes","DEFAULT_PARSED_ATTRIBUTES","defaultParsedModalAttributes","DEFAULT_PARSED_MODAL_ATTRIBUTES","ensureParsedAttributes","ensureParsedModalAttributes","applyTransition","currentState","event","state","ensureUIState","isFSMEvent","getNextState","buildAuthButtonViewModel","state","parsed","options","buildAuthModalViewModel","hasGetClientStatus","x","runEnvEval","params","INITIAL_UI_STATE","envStatusPort","currentState","ensureUIState","mode","isUIMode","isMobileOverride","fallbackType","stateEvaluating","applyTransition","status","rawStatus","isClientStatus","effectiveRecommendedFlow","payload","canStartAuth","currentState","applyTransition","applyStartAuthAndInvokeCore","mode","coreAuthPort","options","nextState","FALLBACK_EVENT","applyFallbackTransition","fallbackKind","authUiApplicationService","params","runEnvEval","tab","parseString","value","parseOptionalString","s","parseBoolean","v","parseOptionalBoolean","parseEnum","allowed","fallback","normalized","parseOptionalEnum","parseAttributesFromElement","element","raw","parseString","parseEnum","UI_MODES","DEFAULT_UI_MODE","parseOptionalString","THEME_KINDS","DEFAULT_THEME","BUTTON_ACTIONS","DEFAULT_BUTTON_ACTION","parseBoolean","BUTTON_VARIANTS","DEFAULT_BUTTON_VARIANT","ensureParsedAttributes","MELLON_ROOT_ID","MELLON_BTN_SELECTOR","MELLON_FALLBACK_BTN_SELECTOR","MELLON_ACTION_FALLBACK_EMAIL","MELLON_ACTION_FALLBACK_QR","PRIMARY_BUTTON_LABEL","MODAL_PASSKEY_BUTTON_LABEL","TRIGGER_ARIA_LABEL","MODAL_PASSKEY_ARIA_LABEL","SVG_NS","WRAPPER_CLASS","OVERLAY_CLASS","PANEL_CLASS","TABS_CLASS","CONTENT_WRAPPER_CLASS","SLOT_CROSS_DEVICE","SLOT_FALLBACK_CTA","MELLON_DIALOG_TITLE_ID","MELLON_DIALOG_DESC_ID","DIALOG_TITLE_TEXT","DIALOG_TITLE_WITH_APP","appName","DIALOG_DESC_TEXT","MODAL_SEPARATOR_TEXT","CROSS_DEVICE_WRAP_CLASS","MODAL_SEPARATOR_CLASS","MODAL_CLOSE_BUTTON_CLASS","MODAL_CLOSE_BUTTON_ARIA_LABEL","CROSS_DEVICE_CTA_TEXT","CROSS_DEVICE_CTA_CLASS","CROSS_DEVICE_QR_BUTTON_ARIA_LABEL","MELLON_QR_SKELETON_CLASS","MELLON_QR_ERROR_CLASS","MELLON_QR_SLOT_WRAP_CLASS","QR_SKELETON_TEXT","QR_TIMEOUT_ERROR_TEXT","createFingerprintIconSVG","svg","SVG_NS","path1","path2","path3","createPrimaryButtonDefault","disabled","label","PRIMARY_BUTTON_LABEL","ariaLabel","TRIGGER_ARIA_LABEL","btn","createPrimaryButtonPill","iconCircle","getPrimaryButtonBuilder","variant","getPrimaryButtonOptions","options","buildPrimaryButtonForReadyState","ensureRoot","surface","shadowRoot","root","MELLON_ROOT_ID","createParagraph","className","text","p","createFallbackButton","action","FALLBACK_BUTTON_CONFIG","MELLON_ACTION_FALLBACK_EMAIL","MELLON_ACTION_FALLBACK_QR","buildFallbackUI","state","wrap","msg","buildContentForState","fragment","render","safeState","ensureUIState","content","viewModelToRenderOptions","vm","modalViewModelToRenderOptions","renderAuthButton","surface","render","renderAuthModal","MELLON_MODAL_TABS_SELECTOR","TAB_ATTR","FOCUSABLE_SELECTOR","MELLON_MODAL_CLOSE_SELECTOR","fallbackActionToType","action","MELLON_ACTION_FALLBACK_EMAIL","MELLON_ACTION_FALLBACK_QR","registerAuthButtonInteractions","root","config","handler","e","target","fallbackBtn","MELLON_FALLBACK_BTN_SELECTOR","MELLON_BTN_SELECTOR","registerAuthModalInteractions","MELLON_MODAL_CLOSE_SELECTOR","MELLON_MODAL_TABS_SELECTOR","tab","TAB_ATTR","overlay","OVERLAY_CLASS","BASE_STYLES","SUPPORTS_ADOPTED_STYLESHEETS","createConstructableStylesheet","sheet","getStylesFallback","MODAL_EXTRA_STYLES","getModalStylesFallback","createModalConstructableStylesheet","ok","value","err","error","TryMellonError","_TryMellonError","code","message","details","DEFAULT_MESSAGES","createError","isTryMellonError","error","createNotSupportedError","createInvalidArgumentError","field","reason","createError","createCredentialError","operation","createEncodingError","type","validateUrl","url","fieldName","urlObj","createInvalidArgumentError","error","isTryMellonError","validateRange","value","min","max","validateBase64Url","s","DOM_EXCEPTION_ERROR_MAP","mapBackendErrorCodeToTryMellon","backendCode","normalized","mapWebAuthnError","name","message","errorCode","createError","isObject","value","isString","isNumber","isBoolean","isArray","validationError","message","details","err","createError","required","obj","key","validateChallengeRP","rp","data","isObject","isString","validationError","ok","validateChallengeUser","user","validatePubKeyCredParams","params","isArray","item","isNumber","validateUserEntity","userId","required","externalUserId","email","metadata","validateRegisterStartResponse","data","isObject","validationError","session_id","required","isString","challenge","rpResult","validateChallengeRP","userResult","validateChallengeUser","challengeStr","pubKeyCredParamsResult","validatePubKeyCredParams","timeout","isNumber","excludeCredentials","isArray","c","authenticatorSelection","ok","validateAuthStartResponse","ch","rpId","allowCredentials","userVerification","validateRegisterFinishResponse","credential_id","status","session_token","user","validateUserEntity","redirect_url","validateAuthFinishResponse","authenticated","signals","isBoolean","validateSessionValidateResponse","data","isObject","validationError","valid","required","user_id","external_user_id","tenant_id","app_id","isBoolean","isString","ok","validateEmailVerifyResponse","data","isObject","validationError","raw","isString","redirect_url","ok","ONBOARDING_STATUSES","REGISTER_PASSKEY_STATUSES","validateOnboardingStartResponse","data","isObject","validationError","session_id","required","onboarding_url","expires_in","isString","isNumber","ok","validateOnboardingStatusResponse","status","validateOnboardingRegisterResponse","challenge","parsedChallenge","chResult","validateOnboardingChallenge","rp","user","challengeStr","pubKeyCredParams","isArray","item","validateOnboardingRegisterPasskeyResponse","user_id","tenant_id","validateOnboardingCompleteResponse","session_token","validateCrossDeviceVerifyResponse","data","ok","isObject","validationError","isCreationOptionsShape","opts","o","isRequestOptionsShape","validateCrossDeviceInitResponse","payload","session_id","qr_url","expires_at","polling_token","isString","result","validateCrossDeviceStatusResponse","status","user_id","session_token","redirect_url","validateCrossDeviceContextResponse","rawType","type","options","MAX_CONTEXT_LENGTH","approval_context","optionalContextString","application_name","extra","value","maxLength","validateRecoveryVerifyResponse","data","isObject","validationError","challenge","required","recovery_session_id","isString","ok","validateRecoveryCompleteResponse","status","session_token","user","credential_id","user_id","redirect_url","userObj","ApiClient","httpClient","baseUrl","defaultHeaders","extra","path","body","validate","url","result","err","headers","request","validateRegisterStartResponse","validateAuthStartResponse","validateRegisterFinishResponse","validateAuthFinishResponse","sessionToken","validateSessionValidateResponse","options","ok","validateEmailVerifyResponse","validateOnboardingStartResponse","sessionId","validateOnboardingStatusResponse","validateOnboardingRegisterResponse","validateOnboardingRegisterPasskeyResponse","validateOnboardingCompleteResponse","validateCrossDeviceInitResponse","trimmed","pollingToken","validateCrossDeviceStatusResponse","validateCrossDeviceContextResponse","validateCrossDeviceVerifyResponse","externalUserId","otp","validateRecoveryVerifyResponse","recoverySessionId","credential","validateRecoveryCompleteResponse","isEnvelopeSuccess","data","isEnvelopeError","o","err","parseHttpErrorBody","errorData","statusText","mapBackendErrorCodeToTryMellon","body","errObj","message","rawCode","code","RETRY_DELAY_CAP_MS","generateRequestId","getRetryDelayMs","attempt","baseMs","delay","shouldRetryOnStatus","method","status","FetchHttpClient","timeoutMs","maxRetries","retryDelayMs","logger","url","headers","config","requestId","lastError","controller","timeoutId","response","errResult","createError","resolve","ok","raw","error","base64UrlEncode","buf","bytes","binary","b","createEncodingError","base64UrlDecode","s","base64","padding","padded","c","base64UrlDecodeToArrayBuffer","buffer","isValidCredentialResponse","response","serializeCredentialForRegister","credential","createError","clientDataJSON","attestationObject","base64UrlEncode","serializeCredentialForAuth","authenticatorData","signature","userHandle","isWebAuthnSupported","isPlatformAuthenticatorAvailable","getClientStatus","isPasskeySupported","platformAuthenticatorAvailable","validateCredentialStructure","credential","operation","createCredentialError","invokeCeremony","context","operation","eventEmitter","start","createOptions","invoke","finish","isWebAuthnSupported","error","createNotSupportedError","err","startResult","optionsResult","credential","createInvalidArgumentError","validateCredentialStructure","e","mapWebAuthnError","finishResult","ok","tryMellonError","createRegistrationOptions","serverChallengePayload","authenticatorType","validateBase64Url","challengeBuffer","base64UrlDecodeToArrayBuffer","userIdBuffer","authenticatorSelection","publicKey","cred","ok","e","err","mapWebAuthnError","createAuthenticationOptions","challenge","mediation","registerPasskey","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","result","invokeCeremony","startResult","ceremonyOptions","opts","credential","finishResult","serializeCredentialForRegister","authenticatePasskey","hasUserId","serializeCredentialForAuth","waitWithAbort","intervalMs","signal","resolve","onAbort","cleanup","timeout","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","OnboardingManager","apiClient","options","signal","startResult","err","session_id","attempt","createError","waitWithAbort","statusResult","status","onboarding_url","registerInfoResult","registerInfo","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","registerPasskeyResult","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","CrossDeviceManager","apiClient","options","sessionId","signal","pollingToken","err","createError","attempt","statusResult","redirectUrl","ok","waitWithAbort","contextResult","context","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","requestOptionsResult","createAuthenticationOptions","serializeCredentialForAuth","EventEmitter","event","handler","handlersSet","payload","DEFAULT_API_BASE_URL","DEFAULT_TELEMETRY_ENDPOINT","SANDBOX_SESSION_TOKEN","createDefaultTelemetrySender","endpoint","payload","body","buildTelemetryPayload","event","latencyMs","AuthService","apiClient","eventEmitter","sandbox","sandboxToken","telemetrySender","operation","options","externalUserId","externalId","ok","result","start","registerPasskey","buildTelemetryPayload","authenticatePasskey","recoverAccount","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","err","result","invokeCeremony","startResult","createRegistrationOptions","ceremonyOptions","credential","finishResult","serializeCredentialForRegister","credential_id","status","session_token","userPayload","redirect_url","ok","RecoveryService","apiClient","eventEmitter","options","recoverAccount","TryMellon","_TryMellon","config","appId","publishableKey","err","createInvalidArgumentError","apiBaseUrl","DEFAULT_API_BASE_URL","validateUrl","timeoutMs","validateRange","ok","e","isTryMellonError","SANDBOX_SESSION_TOKEN","maxRetries","retryDelayMs","httpClient","FetchHttpClient","originHeader","defaultHeaders","ApiClient","EventEmitter","createDefaultTelemetrySender","DEFAULT_TELEMETRY_ENDPOINT","AuthService","RecoveryService","OnboardingManager","CrossDeviceManager","isWebAuthnSupported","options","sessionToken","getClientStatus","event","handler","result","sessionId","signal","pollingToken","createCoreForUI","config","result","TryMellon","isCoreAuthPort","candidate","maybe","hasAuthenticate","hasRegister","hasOn","toCoreAuthOptions","externalUserId","MELLON_OPEN","MELLON_OPEN_REQUEST","MELLON_CLOSE","MELLON_SUCCESS","MELLON_ERROR","MELLON_START","MELLON_CANCELLED","MELLON_FALLBACK","MELLON_TAB_CHANGE","dispatchCustomEvent","host","name","detail","options","toPublicOperation","op","mapSuccessUser","raw","o","userId","result","isCoreStartPayload","isCoreSuccessPayload","isCoreErrorPayload","isCoreCancelledPayload","eventBridgeAdapter","core","unsubscribes","lastOperation","successEmittedThisCeremony","offStart","payload","MELLON_START","offSuccess","mappedUser","MELLON_SUCCESS","offError","code","MELLON_ERROR","offCancelled","MELLON_CANCELLED","off","mapClientStatusToUI","status","createEnvStatusAdapter","getClientStatus","createEnvStatusPortFromCore","core","candidate","getStatus","createMellonOpenEvent","detail","MELLON_OPEN","createMellonCloseEvent","MELLON_CLOSE","createMellonCancelledEvent","MELLON_CANCELLED","createMellonFallbackEvent","MELLON_FALLBACK","createMellonTabChangeEvent","MELLON_TAB_CHANGE","AuthController","INITIAL_UI_STATE","next","tab","nonce","detail","authUiApplicationService","core","options","canStartAuth","params","requestId","nextState","state","AuthElementBase","AuthController","next","detail","createMellonCancelledEvent","core","isCoreAuthPort","eventBridgeAdapter","e","type","createMellonFallbackEvent","params","createEnvStatusPortFromCore","nextState","config","createCoreForUI","nextConfig","state","parseTabLabels","value","DEFAULT_TAB_LABELS","parts","p","register","login","parseModalAttributesFromElement","element","raw","parseBoolean","parseEnum","MODAL_DISPLAY_MODES","DEFAULT_MODAL_DISPLAY_MODE","TAB_KINDS","DEFAULT_TAB","THEME_KINDS","DEFAULT_THEME","parseOptionalString","parseOptionalBoolean","parseOptionalEnum","FALLBACK_TYPES","parseString","MODAL_VARIANTS","DEFAULT_MODAL_VARIANT","ensureParsedModalAttributes","ensureWrapper","shadowRoot","wrapper","WRAPPER_CLASS","ensureOverlay","overlay","OVERLAY_CLASS","ensurePanel","panel","PANEL_CLASS","setPanelDialogAria","mode","MELLON_DIALOG_TITLE_ID","MELLON_DIALOG_DESC_ID","ensureDialogTitleAndDescription","parsed","titleEl","titleText","DIALOG_TITLE_WITH_APP","DIALOG_TITLE_TEXT","descEl","DIALOG_DESC_TEXT","ensureCloseButton","btn","MODAL_CLOSE_BUTTON_CLASS","MODAL_CLOSE_BUTTON_ARIA_LABEL","ensureTabs","tabLabels","tabs","TABS_CLASS","btnRegister","btnLogin","afterDesc","ensureModalContentWrapper","CONTENT_WRAPPER_CLASS","afterTabs","createQrIconSVG","svg","SVG_NS","path","createCrossDeviceDefaultContent","frag","wrap","CROSS_DEVICE_CTA_CLASS","p","CROSS_DEVICE_CTA_TEXT","MELLON_ACTION_FALLBACK_QR","CROSS_DEVICE_QR_BUTTON_ARIA_LABEL","createQrSkeletonNode","el","MELLON_QR_SKELETON_CLASS","label","QR_SKELETON_TEXT","dots","createQrErrorNode","MELLON_QR_ERROR_CLASS","QR_TIMEOUT_ERROR_TEXT","ensureCrossDeviceSlot","CROSS_DEVICE_WRAP_CLASS","slotWrap","MELLON_QR_SLOT_WRAP_CLASS","slot","SLOT_CROSS_DEVICE","created","ensureSeparator","MODAL_SEPARATOR_CLASS","sep","span","MODAL_SEPARATOR_TEXT","ensureDefaultSlotWithRoot","root","MELLON_ROOT_ID","ensureFallbackSlot","SLOT_FALLBACK_CTA","syncTabAriaSelected","activeTab","reg","log","ensureModalStructure","isFocusableCandidate","el","getFocusables","container","FOCUSABLE_SELECTOR","createFocusTrap","previousActiveElement","keydownBound","isActive","handleKeydown","e","focusables","current","currentIndex","lastIndex","nextIndex","next","activate","first","deactivate","doc","toRestore","body","prevTabindex","MODAL_WRAPPER_CLASS","MODAL_OVERLAY_CLASS","MODAL_PANEL_CLASS","OBSERVED_ATTRIBUTES_AUTH","OBSERVED_ATTRIBUTES_MODAL","MODAL_SELECTORS","MELLON_CLOSE_REASON_DEFAULT","CLOSE_REASON_BY_STATE","closeDetailFromState","state","MELLON_CLOSE_REASON_DEFAULT","TryMellonAuthModalElement","AuthElementBase","OBSERVED_ATTRIBUTES_MODAL","parseModalAttributesFromElement","e","shadow","sheet","createModalConstructableStylesheet","styleEl","getModalStylesFallback","ensureModalStructure","registerAuthModalInteractions","tab","createMellonTabChangeEvent","type","name","oldValue","_newValue","detail","createMellonOpenEvent","authUiApplicationService","root","wrap","CROSS_DEVICE_WRAP_CLASS","slot","SLOT_CROSS_DEVICE","ms","wrapElement","onSlotChange","w","createMellonCloseEvent","value","externalUserId","explicit","wrapper","MODAL_SELECTORS","overlay","panel","createFocusTrap","vm","buildAuthModalViewModel","MODAL_PASSKEY_BUTTON_LABEL","MODAL_PASSKEY_ARIA_LABEL","surface","renderAuthModal","TryMellonAuthElement","AuthElementBase","OBSERVED_ATTRIBUTES_AUTH","DEFAULT_PARSED_ATTRIBUTES","el","shadow","sheet","createConstructableStylesheet","styleEl","getStylesFallback","parseAttributesFromElement","registerAuthButtonInteractions","type","name","_oldValue","_newValue","prevMode","tab","authUiApplicationService","MELLON_OPEN_REQUEST","toCoreAuthOptions","operation","vm","buildAuthButtonViewModel","surface","renderAuthButton","MELLON_CLOSE","modal","UI_VERSION","TRYMELLON_AUTH_TAG","TRYMELLON_AUTH_MODAL_TAG","TryMellonAuthElement","TryMellonAuthModalElement"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ui/domain/fsm/fsm.ts","../../src/ui/domain/fsm/constants.ts","../../src/ui/domain/validators/constants.ts","../../src/ui/domain/validators/validators-state.ts","../../src/ui/domain/contracts/constants.ts","../../src/ui/domain/validators/validators-attributes.ts","../../src/ui/application/transition.use-case.ts","../../src/ui/domain/viewmodels/auth-viewmodels.ts","../../src/ui/application/evaluate-env.use-case.ts","../../src/ui/application/auth-ui.application-service.ts","../../src/ui/adapters/attributes/parse.utils.ts","../../src/ui/adapters/attributes/inline.adapter.ts","../../src/ui/adapters/render/constants.ts","../../src/ui/adapters/render/shadow.adapter.ts","../../src/ui/adapters/render/auth.adapter.ts","../../src/ui/adapters/interactions/constants.ts","../../src/ui/adapters/interactions/dom.adapter.ts","../../src/ui/adapters/render/styles.adapter.ts","../../src/utils/result.ts","../../src/errors.ts","../../src/core/validators/helpers.ts","../../src/core/validators/register-auth.ts","../../src/core/validators/session.ts","../../src/core/validators/email.ts","../../src/core/validators/onboarding.ts","../../src/core/validators/cross-device.ts","../../src/core/validators/recovery.ts","../../src/core/api.ts","../../src/core/fetch-client.ts","../../src/utils/base64url.ts","../../src/core/webauthn-utils.ts","../../src/utils/support.ts","../../src/utils/validation.ts","../../src/core/ceremony.ts","../../src/core/webauthn.ts","../../src/core/polling-utils.ts","../../src/core/onboarding-manager.ts","../../src/core/cross-device-manager.ts","../../src/core/events.ts","../../src/core/constants.ts","../../src/core/adapters/telemetry-sender.ts","../../src/core/ports/telemetry.ts","../../src/core/services/auth-service.ts","../../src/core/recover.ts","../../src/core/services/recovery-service.ts","../../src/core/trymellon.ts","../../src/ui/adapters/infra/core-factory.adapter.ts","../../src/ui/adapters/infra/constants.ts","../../src/ui/adapters/infra/event-bridge.adapter.ts","../../src/ui/adapters/infra/env-status.adapter.ts","../../src/ui/presentation/ui-events.ts","../../src/ui/presentation/auth-controller.ts","../../src/ui/presentation/auth-element-base.ts","../../src/ui/adapters/attributes/modal.adapter.ts","../../src/ui/adapters/render/modal-structure.adapter.ts","../../src/ui/adapters/interactions/focus-trap.adapter.ts","../../src/ui/presentation/constants.ts","../../src/ui/presentation/trymellon-auth-modal.element.ts","../../src/ui/presentation/trymellon-auth.element.ts","../../src/ui/index.ts"],"sourcesContent":["/**\n * Pure UI FSM — no DOM, no I/O. (currentState, event) → nextState.\n * Transitions per 02-fsm-estado-modal.\n */\nimport type { UIState, FSMEvent, EnvResolvedPayload } from './types';\n\nfunction resolveEnvState(payload: EnvResolvedPayload): UIState {\n if (payload.recommendedFlow === 'fallback') {\n if (payload.fallbackType === 'email') return 'FALLBACK_EMAIL';\n if (payload.fallbackType === 'qr') return 'FALLBACK_QR';\n return 'FALLBACK';\n }\n switch (payload.mode) {\n case 'login':\n return 'READY_LOGIN';\n case 'register':\n return 'READY_REGISTER';\n case 'auto':\n default:\n return 'READY';\n }\n}\n\nfunction tabToReadyState(tab: 'register' | 'login'): UIState {\n return tab === 'register' ? 'READY_REGISTER' : 'READY_LOGIN';\n}\n\n/**\n * Next FSM state from current state and event. RESET from any state → IDLE.\n * Undefined transitions leave state unchanged (idempotent).\n */\nexport function getNextState(currentState: UIState, event: FSMEvent): UIState {\n if (currentState == null || event == null) return 'IDLE';\n if (event.type === 'RESET') return 'IDLE';\n\n if (event.type === 'TAB_CHANGE') {\n const tab = event.payload?.tab;\n if (tab !== 'register' && tab !== 'login') return currentState;\n const nextReady = tabToReadyState(tab);\n switch (currentState) {\n case 'READY':\n case 'READY_REGISTER':\n case 'READY_LOGIN':\n case 'FALLBACK':\n case 'FALLBACK_EMAIL':\n case 'FALLBACK_QR':\n case 'AUTHENTICATING':\n case 'ERROR':\n return nextReady;\n default:\n return currentState;\n }\n }\n\n switch (currentState) {\n case 'IDLE':\n if (event.type === 'ENV_EVAL_START') return 'EVALUATING_ENV';\n break;\n\n case 'EVALUATING_ENV':\n if (event.type === 'ENV_RESOLVED') return resolveEnvState(event.payload);\n if (event.type === 'ENV_DETACH') return 'IDLE';\n if (event.type === 'ENV_ERROR') return 'ERROR';\n break;\n\n case 'READY':\n case 'READY_REGISTER':\n case 'READY_LOGIN':\n if (event.type === 'START_AUTH') return 'AUTHENTICATING';\n break;\n\n case 'AUTHENTICATING':\n if (event.type === 'AUTH_SUCCESS') return 'SUCCESS';\n if (event.type === 'AUTH_ERROR') return 'ERROR';\n if (event.type === 'AUTH_FALLBACK') return 'FALLBACK';\n if (event.type === 'AUTH_FALLBACK_EMAIL') return 'FALLBACK_EMAIL';\n if (event.type === 'AUTH_FALLBACK_QR') return 'FALLBACK_QR';\n break;\n\n default:\n break;\n }\n\n return currentState;\n}\n","/**\n * FSM constants. Single source for initial state.\n */\n/** Initial FSM state (pre-attach). */\nexport const INITIAL_UI_STATE = 'IDLE' as const;\n","/**\n * Validator constants: enum arrays for type guards and parseEnum. Single source of truth.\n */\nimport type { UIState } from '../fsm/types';\nimport type {\n ThemeKind,\n ModalDisplayMode,\n ButtonAction,\n ButtonVariant,\n ModalVariant,\n} from '../contracts/types';\n\nexport const UI_STATES: readonly UIState[] = [\n 'IDLE',\n 'EVALUATING_ENV',\n 'READY',\n 'READY_REGISTER',\n 'READY_LOGIN',\n 'AUTHENTICATING',\n 'SUCCESS',\n 'ERROR',\n 'FALLBACK',\n 'FALLBACK_EMAIL',\n 'FALLBACK_QR',\n];\n\nexport const UI_MODES = ['login', 'register', 'auto'] as const;\nexport const THEME_KINDS: readonly ThemeKind[] = ['light', 'dark'];\nexport const TAB_KINDS = ['register', 'login'] as const;\nexport const MODAL_DISPLAY_MODES: readonly ModalDisplayMode[] = ['modal', 'inline'];\nexport const FALLBACK_TYPES = ['email', 'qr'] as const;\nexport const BUTTON_ACTIONS: readonly ButtonAction[] = ['direct-auth', 'open-modal'];\nexport const BUTTON_VARIANTS: readonly ButtonVariant[] = ['default', 'pill'];\nexport const MODAL_VARIANTS: readonly ModalVariant[] = ['default', 'minimal'];\n\nexport const RECOMMENDED_FLOWS = ['passkey', 'fallback'] as const;\n","/**\n * FSM state and event validators. Pure type guards and HOFs; no dependencies outside domain.\n */\nimport type {\n UIState,\n UIMode,\n EnvResolvedPayload,\n TabKind,\n FSMEvent,\n UIClientStatus,\n} from '../fsm/types';\nimport type {\n ThemeKind,\n ModalDisplayMode,\n ButtonAction,\n ButtonVariant,\n ModalVariant,\n} from '../contracts/types';\nimport { INITIAL_UI_STATE } from '../fsm/constants';\nimport {\n UI_STATES,\n UI_MODES,\n THEME_KINDS,\n TAB_KINDS,\n MODAL_DISPLAY_MODES,\n FALLBACK_TYPES,\n BUTTON_ACTIONS,\n BUTTON_VARIANTS,\n MODAL_VARIANTS,\n RECOMMENDED_FLOWS,\n} from './constants';\n\nexport {\n UI_STATES,\n UI_MODES,\n THEME_KINDS,\n TAB_KINDS,\n MODAL_DISPLAY_MODES,\n FALLBACK_TYPES,\n BUTTON_ACTIONS,\n BUTTON_VARIANTS,\n MODAL_VARIANTS,\n};\n\n/** Type guard: getClientStatus result (port) as UIClientStatus. */\nexport function isClientStatus(value: unknown): value is UIClientStatus {\n if (value == null || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n if (typeof v.isPasskeySupported !== 'boolean') return false;\n if (typeof v.platformAuthenticatorAvailable !== 'boolean') return false;\n if (v.recommendedFlow !== 'passkey' && v.recommendedFlow !== 'fallback') return false;\n return true;\n}\n\nfunction isOneOf<T extends string>(value: unknown, allowed: readonly T[]): value is T {\n return typeof value === 'string' && (allowed as readonly string[]).includes(value);\n}\n\nexport function isUIState(value: unknown): value is UIState {\n return isOneOf(value, UI_STATES);\n}\n\nexport function ensureUIState(value: unknown): UIState {\n return isUIState(value) ? value : (INITIAL_UI_STATE as UIState);\n}\n\nexport function isUIMode(value: unknown): value is UIMode {\n return isOneOf(value, UI_MODES);\n}\n\nexport function isThemeKind(value: unknown): value is ThemeKind {\n return isOneOf(value, THEME_KINDS);\n}\n\nexport function isTabKind(value: unknown): value is TabKind {\n return isOneOf(value, TAB_KINDS);\n}\n\nexport function isModalDisplayMode(value: unknown): value is ModalDisplayMode {\n return isOneOf(value, MODAL_DISPLAY_MODES);\n}\n\nexport function isButtonAction(value: unknown): value is ButtonAction {\n return isOneOf(value, BUTTON_ACTIONS);\n}\n\nexport function isButtonVariant(value: unknown): value is ButtonVariant {\n return isOneOf(value, BUTTON_VARIANTS);\n}\n\nexport function isModalVariant(value: unknown): value is ModalVariant {\n return isOneOf(value, MODAL_VARIANTS);\n}\n\nexport function isEnvResolvedPayload(value: unknown): value is EnvResolvedPayload {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n isOneOf(o.recommendedFlow, RECOMMENDED_FLOWS) &&\n isUIMode(o.mode) &&\n (o.fallbackType === undefined || isOneOf(o.fallbackType, FALLBACK_TYPES))\n );\n}\n\nexport function isFSMEvent(value: unknown): value is FSMEvent {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n const t = o.type;\n if (typeof t !== 'string') return false;\n switch (t) {\n case 'ENV_EVAL_START':\n case 'ENV_DETACH':\n case 'ENV_ERROR':\n case 'RESET':\n case 'START_AUTH':\n case 'AUTH_SUCCESS':\n case 'AUTH_ERROR':\n case 'AUTH_FALLBACK':\n case 'AUTH_FALLBACK_EMAIL':\n case 'AUTH_FALLBACK_QR':\n return true;\n case 'ENV_RESOLVED':\n return isEnvResolvedPayload(o.payload);\n case 'TAB_CHANGE':\n return (\n o.payload != null &&\n typeof o.payload === 'object' &&\n isTabKind((o.payload as Record<string, unknown>).tab)\n );\n default:\n return false;\n }\n}\n","/**\n * Contract constants: default values for parsed attributes. Single source of truth.\n */\nimport type { UIMode } from '../fsm/types';\nimport type {\n ThemeKind,\n ModalDisplayMode,\n ModalTabKind,\n TabLabels,\n ButtonAction,\n ButtonVariant,\n ModalVariant,\n ParsedAttributes,\n ParsedModalAttributes,\n} from './types';\n\nexport const DEFAULT_UI_MODE: UIMode = 'login';\nexport const DEFAULT_THEME: ThemeKind = 'light';\nexport const DEFAULT_MODAL_DISPLAY_MODE: ModalDisplayMode = 'modal';\nexport const DEFAULT_TAB: ModalTabKind = 'register';\n/** Register tab = \"Register\" to avoid duplicating \"Create account\" with slot content (e.g. label above QR). */\nexport const DEFAULT_TAB_LABELS: TabLabels = { register: 'Register', login: 'Sign in' };\n\nexport const DEFAULT_BUTTON_ACTION: ButtonAction = 'open-modal';\nexport const DEFAULT_BUTTON_VARIANT: ButtonVariant = 'default';\nexport const DEFAULT_MODAL_VARIANT: ModalVariant = 'default';\n\n/** Safe default for ParsedAttributes. */\nexport const DEFAULT_PARSED_ATTRIBUTES: ParsedAttributes = {\n appId: '',\n publishableKey: '',\n mode: DEFAULT_UI_MODE,\n externalUserId: null,\n theme: DEFAULT_THEME,\n action: DEFAULT_BUTTON_ACTION,\n triggerOnly: false,\n buttonVariant: DEFAULT_BUTTON_VARIANT,\n buttonLabel: null,\n buttonAriaLabel: null,\n};\n\n/** Safe default for ParsedModalAttributes. */\nexport const DEFAULT_PARSED_MODAL_ATTRIBUTES: ParsedModalAttributes = {\n open: false,\n mode: DEFAULT_MODAL_DISPLAY_MODE,\n tab: DEFAULT_TAB,\n tabLabels: DEFAULT_TAB_LABELS,\n theme: DEFAULT_THEME,\n sessionId: null,\n onboardingUrl: null,\n isMobileOverride: null,\n appId: '',\n publishableKey: '',\n appName: null,\n dialogTitle: null,\n dialogDescription: null,\n externalUserId: null,\n modalVariant: DEFAULT_MODAL_VARIANT,\n};\n","/**\n * Validators for parsed attributes (root and modal). Pure type guards and HOFs.\n */\nimport type { ParsedAttributes, TabLabels, ParsedModalAttributes } from '../contracts/types';\nimport { DEFAULT_PARSED_ATTRIBUTES, DEFAULT_PARSED_MODAL_ATTRIBUTES } from '../contracts/constants';\nimport {\n isUIMode,\n isThemeKind,\n isTabKind,\n isModalDisplayMode,\n isButtonAction,\n isButtonVariant,\n isModalVariant,\n} from './validators-state';\n\nexport function isParsedAttributes(value: unknown): value is ParsedAttributes {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.appId === 'string' &&\n typeof o.publishableKey === 'string' &&\n isUIMode(o.mode) &&\n (o.externalUserId === null || typeof o.externalUserId === 'string') &&\n isThemeKind(o.theme) &&\n isButtonAction(o.action) &&\n typeof o.triggerOnly === 'boolean' &&\n isButtonVariant(o.buttonVariant)\n );\n}\n\nexport function isTabLabels(value: unknown): value is TabLabels {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return typeof o.register === 'string' && typeof o.login === 'string';\n}\n\nexport function isParsedModalAttributes(value: unknown): value is ParsedModalAttributes {\n if (value == null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.open === 'boolean' &&\n isModalDisplayMode(o.mode) &&\n isTabKind(o.tab) &&\n isTabLabels(o.tabLabels) &&\n isThemeKind(o.theme) &&\n (o.sessionId === null || typeof o.sessionId === 'string') &&\n (o.onboardingUrl === null || typeof o.onboardingUrl === 'string') &&\n (o.isMobileOverride === null || typeof o.isMobileOverride === 'boolean') &&\n (o.fallbackType === undefined || o.fallbackType === 'email' || o.fallbackType === 'qr') &&\n typeof o.appId === 'string' &&\n typeof o.publishableKey === 'string' &&\n (o.appName == null || typeof o.appName === 'string') &&\n (o.dialogTitle == null || typeof o.dialogTitle === 'string') &&\n (o.dialogDescription == null || typeof o.dialogDescription === 'string') &&\n (o.externalUserId == null || typeof o.externalUserId === 'string') &&\n isModalVariant(o.modalVariant)\n );\n}\n\nexport function defaultParsedAttributes(): ParsedAttributes {\n return DEFAULT_PARSED_ATTRIBUTES;\n}\n\nexport function defaultParsedModalAttributes(): ParsedModalAttributes {\n return DEFAULT_PARSED_MODAL_ATTRIBUTES;\n}\n\nexport function ensureParsedAttributes(value: unknown): ParsedAttributes {\n return isParsedAttributes(value) ? value : defaultParsedAttributes();\n}\n\nexport function ensureParsedModalAttributes(value: unknown): ParsedModalAttributes {\n return isParsedModalAttributes(value) ? value : defaultParsedModalAttributes();\n}\n","/**\n * Use case: pure FSM transition. Validates types at boundary; delegates to domain getNextState.\n */\nimport { getNextState } from '../domain/fsm/fsm';\nimport type { UIState } from '../domain';\nimport { ensureUIState, isFSMEvent } from '../domain/validators';\n\n/** Applies event to FSM and returns next state. Invalid input → idempotent safe state. */\nexport function applyTransition(currentState: unknown, event: unknown): UIState {\n const state = ensureUIState(currentState);\n if (!isFSMEvent(event)) return state;\n return getNextState(state, event);\n}\n","/**\n * ViewModels for auth presentation. Group UIState + props needed for render.\n * No DOM dependencies; built from parsed attributes.\n */\nimport type { UIState, UIMode } from '../fsm/types';\nimport type {\n ThemeKind,\n ButtonVariant,\n ParsedAttributes,\n ParsedModalAttributes,\n TabLabels,\n ModalTabKind,\n} from '../contracts/types';\n\n/** ViewModel for the auth button/trigger content (trymellon-auth). */\nexport type AuthButtonViewModel = {\n state: UIState;\n theme: ThemeKind;\n mode: UIMode;\n buttonVariant: ButtonVariant;\n registerSessionReady?: boolean;\n primaryButtonLabel?: string;\n primaryButtonAriaLabel?: string;\n};\n\n/** ViewModel for the modal FSM content (trymellon-auth-modal). */\nexport type AuthModalViewModel = {\n state: UIState;\n theme: ThemeKind;\n tab: ModalTabKind;\n tabLabels: TabLabels;\n registerSessionReady?: boolean;\n primaryButtonLabel: string;\n primaryButtonAriaLabel: string;\n};\n\nexport function buildAuthButtonViewModel(\n state: UIState,\n parsed: ParsedAttributes,\n options?: {\n registerSessionReady?: boolean;\n primaryButtonLabel?: string;\n primaryButtonAriaLabel?: string;\n }\n): AuthButtonViewModel {\n return {\n state,\n theme: parsed.theme,\n mode: parsed.mode,\n buttonVariant: parsed.buttonVariant,\n ...(parsed.mode === 'register' &&\n options?.registerSessionReady !== undefined && {\n registerSessionReady: options.registerSessionReady,\n }),\n ...(options?.primaryButtonLabel !== undefined && {\n primaryButtonLabel: options.primaryButtonLabel,\n }),\n ...(options?.primaryButtonAriaLabel !== undefined && {\n primaryButtonAriaLabel: options.primaryButtonAriaLabel,\n }),\n };\n}\n\nexport function buildAuthModalViewModel(\n state: UIState,\n parsed: ParsedModalAttributes,\n options?: {\n registerSessionReady?: boolean;\n primaryButtonLabel?: string;\n primaryButtonAriaLabel?: string;\n }\n): AuthModalViewModel {\n return {\n state,\n theme: parsed.theme,\n tab: parsed.tab,\n tabLabels: parsed.tabLabels,\n ...(parsed.tab === 'register' &&\n options?.registerSessionReady !== undefined && {\n registerSessionReady: options.registerSessionReady,\n }),\n primaryButtonLabel: options?.primaryButtonLabel ?? 'Try Passkey',\n primaryButtonAriaLabel: options?.primaryButtonAriaLabel ?? 'Try Passkey, use this device',\n };\n}\n","/**\n * Use case: evaluate environment (getClientStatus) and return next FSM state. Validates params and port response at boundary; domain + EnvStatusPort only. No DOM.\n */\nimport type { EnvResolvedPayload, UIState, UIMode, UIClientStatus } from '../domain/types';\nimport type { EnvStatusPort } from '../ports/env-evaluator.port';\nimport { ensureUIState, isClientStatus, isUIMode } from '../domain/validators';\nimport { INITIAL_UI_STATE } from '../domain';\nimport { applyTransition } from './transition.use-case';\n\nexport type RunEnvEvalParams = {\n envStatusPort: EnvStatusPort;\n currentState: UIState;\n mode: UIMode;\n isMobileOverride?: boolean;\n /** When recommendedFlow is fallback, allows fixing FALLBACK_EMAIL vs FALLBACK_QR (e.g. modal). */\n fallbackType?: 'email' | 'qr';\n};\n\n/** Type guard: value has getClientStatus (EnvStatusPort). Invalid params/port → IDLE. */\nfunction hasGetClientStatus(x: unknown): x is EnvStatusPort {\n return typeof (x as Record<string, unknown>)?.getClientStatus === 'function';\n}\n\nexport async function runEnvEval(params: RunEnvEvalParams): Promise<UIState> {\n if (!hasGetClientStatus(params.envStatusPort)) return INITIAL_UI_STATE;\n\n const envStatusPort = params.envStatusPort;\n const currentState = ensureUIState(params.currentState);\n const mode = isUIMode(params.mode) ? params.mode : 'login';\n const isMobileOverride = params.isMobileOverride === true;\n const fallbackType =\n params.fallbackType === 'email' || params.fallbackType === 'qr'\n ? params.fallbackType\n : undefined;\n\n const stateEvaluating = applyTransition(currentState, { type: 'ENV_EVAL_START' });\n\n let status: UIClientStatus;\n try {\n const rawStatus = await envStatusPort.getClientStatus();\n if (!isClientStatus(rawStatus)) {\n return applyTransition(stateEvaluating, { type: 'ENV_ERROR' });\n }\n status = rawStatus;\n } catch {\n return applyTransition(stateEvaluating, { type: 'ENV_ERROR' });\n }\n\n const effectiveRecommendedFlow =\n isMobileOverride === true ? ('fallback' as const) : status.recommendedFlow;\n\n const payload: EnvResolvedPayload = {\n recommendedFlow: effectiveRecommendedFlow,\n mode,\n ...(effectiveRecommendedFlow === 'fallback' && fallbackType != null && { fallbackType }),\n };\n\n return applyTransition(stateEvaluating, { type: 'ENV_RESOLVED', payload });\n}\n","/**\n * Application facade: orchestrates use cases (applyTransition, runEnvEval) and core delegation. One method per UC; domain + ports only. Stale-response token: caller (WC) responsibility; stateless.\n */\nimport type { UIState, UIMode, TabKind } from '../domain/types';\nimport type { FSMEvent } from '../domain/types';\nimport type { CoreAuthPort, CoreAuthOptions } from '../ports/core-events.port';\nimport { applyTransition } from './transition.use-case';\nimport { runEnvEval, type RunEnvEvalParams } from './evaluate-env.use-case';\n\n/** Application facade contract: high-level methods per use case. */\nexport interface AuthUiApplicationService {\n /** Transition ENV_EVAL_START → EVALUATING_ENV (so WC shows evaluating state before await). */\n envEvalStart(currentState: UIState): UIState;\n\n /**\n * EvaluateEnvironment: evaluates env via port and returns final FSM state.\n * Always resolves with UIState. Caller (WC) must discard stale responses by comparing\n * a per-instance requestId after await (last-wins per component).\n */\n evaluateEnv(params: RunEnvEvalParams): Promise<UIState>;\n\n /** START_AUTH transition and core delegation (authenticate/register). */\n startAuth(\n currentState: UIState,\n mode: UIMode,\n coreAuthPort: CoreAuthPort,\n options?: CoreAuthOptions\n ): UIState;\n\n /** AUTH_SUCCESS transition. */\n handleAuthSuccess(currentState: UIState): UIState;\n\n /** AUTH_ERROR transition. */\n handleAuthError(currentState: UIState): UIState;\n\n /** Applies AUTH_SUCCESS only if state is AUTHENTICATING. Returns new state or null (avoids duplicating guard in WCs). */\n tryHandleAuthSuccess(currentState: UIState): UIState | null;\n\n /** Applies AUTH_ERROR only if state is AUTHENTICATING. Returns new state or null (avoids duplicating guard in WCs). */\n tryHandleAuthError(currentState: UIState): UIState | null;\n\n /** AUTH_FALLBACK[_EMAIL|_QR] transition by channel. */\n handleFallback(currentState: UIState, fallbackKind?: 'email' | 'qr'): UIState;\n\n /** TAB_CHANGE transition. */\n tabChange(currentState: UIState, tab: TabKind): UIState;\n\n /** RESET → IDLE transition. */\n reset(currentState: UIState): UIState;\n}\n\n/**\n * Pure helper: returns whether the FSM allows starting AUTH from the given state.\n * Uses applyTransition as single source of truth: if START_AUTH does not change state, it is not allowed.\n */\nexport function canStartAuth(currentState: UIState): boolean {\n const nextState = applyTransition(currentState, { type: 'START_AUTH' });\n return nextState !== currentState;\n}\n\nfunction applyStartAuthAndInvokeCore(\n currentState: UIState,\n mode: UIMode,\n coreAuthPort: CoreAuthPort,\n options?: CoreAuthOptions\n): UIState {\n const nextState = applyTransition(currentState, { type: 'START_AUTH' });\n if (mode === 'register') {\n coreAuthPort.register(options);\n } else {\n coreAuthPort.authenticate(options);\n }\n return nextState;\n}\n\n/** Fallback kind → FSM event. One lookup; generic is the default key. */\nconst FALLBACK_EVENT: Record<'email' | 'qr' | 'generic', FSMEvent> = {\n email: { type: 'AUTH_FALLBACK_EMAIL' },\n qr: { type: 'AUTH_FALLBACK_QR' },\n generic: { type: 'AUTH_FALLBACK' },\n};\n\nfunction applyFallbackTransition(currentState: UIState, fallbackKind?: 'email' | 'qr'): UIState {\n const key: 'email' | 'qr' | 'generic' =\n fallbackKind === 'email' ? 'email' : fallbackKind === 'qr' ? 'qr' : 'generic';\n return applyTransition(currentState, FALLBACK_EVENT[key]);\n}\n\n/** Stateless facade implementation; orchestrates use cases and ports. */\nexport const authUiApplicationService: AuthUiApplicationService = {\n envEvalStart(currentState) {\n return applyTransition(currentState, { type: 'ENV_EVAL_START' });\n },\n\n evaluateEnv(params) {\n return runEnvEval(params);\n },\n\n startAuth(currentState, mode, coreAuthPort, options) {\n return applyStartAuthAndInvokeCore(currentState, mode, coreAuthPort, options);\n },\n\n handleAuthSuccess(currentState) {\n return applyTransition(currentState, { type: 'AUTH_SUCCESS' });\n },\n\n handleAuthError(currentState) {\n return applyTransition(currentState, { type: 'AUTH_ERROR' });\n },\n\n tryHandleAuthSuccess(currentState) {\n if (currentState !== 'AUTHENTICATING') return null;\n return applyTransition(currentState, { type: 'AUTH_SUCCESS' });\n },\n\n tryHandleAuthError(currentState) {\n if (currentState !== 'AUTHENTICATING') return null;\n return applyTransition(currentState, { type: 'AUTH_ERROR' });\n },\n\n handleFallback(currentState, fallbackKind) {\n return applyFallbackTransition(currentState, fallbackKind);\n },\n\n tabChange(currentState, tab) {\n return applyTransition(currentState, { type: 'TAB_CHANGE', payload: { tab } });\n },\n\n reset(currentState) {\n return applyTransition(currentState, { type: 'RESET' });\n },\n};\n","/**\n * Pure helpers for DOM attribute parsing (string | null) → type. Shared by inline and modal adapters. No external deps; adapters layer.\n */\n\nexport function parseString(value: string | null): string {\n if (value == null || value.trim() === '') return '';\n return value.trim();\n}\n\nexport function parseOptionalString(value: string | null): string | null {\n const s = parseString(value);\n return s === '' ? null : s;\n}\n\n/**\n * Parses boolean attribute (HTML semantics: presence = true). Any present value including \"\" is true; only null is false.\n */\nexport function parseBoolean(value: string | null): boolean {\n if (value == null) return false;\n const v = value.trim().toLowerCase();\n return v === 'true' || v === '1' || v === '';\n}\n\nexport function parseOptionalBoolean(value: string | null): boolean | null {\n if (value == null || value.trim() === '') return null;\n const v = value.trim().toLowerCase();\n if (v === 'true' || v === '1') return true;\n if (v === 'false' || v === '0') return false;\n return null;\n}\n\n/**\n * Parses string to one of allowed values; null or empty → fallback. Normalizes trim + lowercase.\n */\nexport function parseEnum<T extends string>(\n value: string | null,\n allowed: readonly T[],\n fallback: T\n): T {\n if (value == null || value.trim() === '') return fallback;\n const normalized = value.trim().toLowerCase();\n if (allowed.includes(normalized as T)) return normalized as T;\n return fallback;\n}\n\n/**\n * Like parseEnum but returns undefined when attribute is missing or invalid. For optional fields without default.\n */\nexport function parseOptionalEnum<T extends string>(\n value: string | null,\n allowed: readonly T[]\n): T | undefined {\n if (value == null || value.trim() === '') return undefined;\n const normalized = value.trim().toLowerCase();\n if (allowed.includes(normalized as T)) return normalized as T;\n return undefined;\n}\n","/**\n * Parses and validates observedAttributes for inline WC. Uses parseEnum + domain enum arrays and defaults.\n */\nimport type { ParsedAttributes } from '../../domain/contracts/types';\nimport {\n UI_MODES,\n THEME_KINDS,\n BUTTON_ACTIONS,\n BUTTON_VARIANTS,\n DEFAULT_UI_MODE,\n DEFAULT_THEME,\n DEFAULT_BUTTON_ACTION,\n DEFAULT_BUTTON_VARIANT,\n} from '../../domain';\nimport { ensureParsedAttributes } from '../../domain/validators';\nimport { parseString, parseOptionalString, parseEnum, parseBoolean } from './parse.utils';\n\nexport type { ThemeKind, ParsedAttributes } from '../../domain/contracts/types';\n\nexport function parseAttributesFromElement(element: HTMLElement): ParsedAttributes {\n const raw = {\n appId: parseString(element.getAttribute('app-id')),\n publishableKey: parseString(element.getAttribute('publishable-key')),\n mode: parseEnum(element.getAttribute('mode'), UI_MODES, DEFAULT_UI_MODE),\n externalUserId: parseOptionalString(element.getAttribute('external-user-id')),\n theme: parseEnum(element.getAttribute('theme'), THEME_KINDS, DEFAULT_THEME),\n action: parseEnum(element.getAttribute('action'), BUTTON_ACTIONS, DEFAULT_BUTTON_ACTION),\n triggerOnly: parseBoolean(element.getAttribute('trigger-only')),\n buttonVariant: parseEnum(\n element.getAttribute('button-variant'),\n BUTTON_VARIANTS,\n DEFAULT_BUTTON_VARIANT\n ),\n buttonLabel: parseOptionalString(element.getAttribute('button-label')),\n buttonAriaLabel: parseOptionalString(element.getAttribute('button-aria-label')),\n };\n return ensureParsedAttributes(raw);\n}\n","/**\n * Centralized constants for the render layer (Shadow DOM, modal structure, selectors, labels).\n * Single source for IDs, class names, selectors, and copy used by shadow.adapter and modal-structure.adapter.\n */\n\n/** Main container ID in Shadow DOM; shared by inline and modal. */\nexport const MELLON_ROOT_ID = 'mellon-root';\n\n/** Primary auth (passkey) button selector. */\nexport const MELLON_BTN_SELECTOR = '.mellon-btn';\n\n/** Fallback button selector (data-mellon-action^=\"fallback\"). */\nexport const MELLON_FALLBACK_BTN_SELECTOR = '[data-mellon-action^=\"fallback\"]';\n\n/** data-mellon-action value for email fallback. */\nexport const MELLON_ACTION_FALLBACK_EMAIL = 'fallback-email';\n\n/** data-mellon-action value for QR fallback. */\nexport const MELLON_ACTION_FALLBACK_QR = 'fallback-qr';\n\n/** Primary button label when used as trigger (opens modal). */\nexport const PRIMARY_BUTTON_LABEL = 'TryMellon';\n\n/** Primary button label when inside modal (passkey on this device). Same structure as landing. */\nexport const MODAL_PASSKEY_BUTTON_LABEL = 'Try Passkey';\n\n/** aria-label for trigger/CTA (context without visual; not icon-only). */\nexport const TRIGGER_ARIA_LABEL = 'TryMellon, open authentication';\n\n/** aria-label for passkey button inside modal. */\nexport const MODAL_PASSKEY_ARIA_LABEL = 'Try Passkey, use this device';\n\n/** Internal: SVG namespace for fingerprint icon. */\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\n\n// --- Modal structure (modal-structure.adapter) ---\n\nexport const WRAPPER_CLASS = 'mellon-modal-wrapper';\nexport const OVERLAY_CLASS = 'mellon-modal-overlay';\nexport const PANEL_CLASS = 'mellon-modal-panel';\nexport const TABS_CLASS = 'mellon-modal-tabs';\nexport const CONTENT_WRAPPER_CLASS = 'mellon-modal-content';\n\n/** Slot name for host-injected QR / cross-device UI. Use <trymellon-auth-modal><div slot=\"cross-device\">...</div></trymellon-auth-modal>. */\nexport const SLOT_CROSS_DEVICE = 'cross-device';\n\nexport const SLOT_FALLBACK_CTA = 'fallback-cta';\n\n/** IDs for dialog aria-labelledby / aria-describedby. */\nexport const MELLON_DIALOG_TITLE_ID = 'mellon-dialog-title';\nexport const MELLON_DIALOG_DESC_ID = 'mellon-dialog-desc';\n\nexport const DIALOG_TITLE_TEXT = 'TryMellon — Sign in or register';\n/** Title when app name is set: \"{appName} — Sign in or register\". */\nexport const DIALOG_TITLE_WITH_APP = (appName: string): string =>\n `${appName} — Sign in or register`;\nexport const DIALOG_DESC_TEXT = 'Pick Register or Sign in to continue.';\n/** Separator between QR/cross-device and Try Passkey (with lines: —— or ——). */\nexport const MODAL_SEPARATOR_TEXT = 'Or sign in with';\nexport const CROSS_DEVICE_WRAP_CLASS = 'mellon-cross-device-wrap';\nexport const MODAL_SEPARATOR_CLASS = 'mellon-modal-separator';\n\n/** Modal close button (top-right, inside panel). */\nexport const MODAL_CLOSE_BUTTON_CLASS = 'mellon-modal-close-btn';\nexport const MODAL_CLOSE_BUTTON_ARIA_LABEL = 'Close dialog';\n\n/** Cross-device CTA (default slot content when host does not inject QR). Always visible above \"or\" and Try Passkey. */\nexport const CROSS_DEVICE_CTA_TEXT = 'Try from another device';\nexport const CROSS_DEVICE_CTA_CLASS = 'mellon-cross-device-cta';\n/** Aria-label for QR button (icon-only, no visible text). */\nexport const CROSS_DEVICE_QR_BUTTON_ARIA_LABEL = 'Try with QR';\n\n/** QR area: skeleton and timeout (owned by modal). */\nexport const MELLON_QR_SKELETON_CLASS = 'mellon-cross-device-skeleton';\nexport const MELLON_QR_ERROR_CLASS = 'mellon-cross-device-error';\nexport const MELLON_QR_SLOT_WRAP_CLASS = 'mellon-cross-device-slot-wrap';\nexport const QR_SKELETON_TEXT = 'Loading QRs';\nexport const QR_TIMEOUT_ERROR_TEXT = 'QR could not be loaded. Try again.';\n/** Default timeout (ms) when modal expects injected QR; host can override via qr-load-timeout-ms. */\nexport const QR_LOAD_TIMEOUT_MS_DEFAULT = 12_000;\n","/**\n * WC Shadow DOM render. Validates state at boundary (domain validators). No innerHTML/outerHTML; createElement/setAttribute only.\n * Constants: render/constants.ts. Re-exports public constants for consumers (e.g. interactions, presentation).\n */\nimport type { UIState } from '../../domain';\nimport type { ButtonVariant } from '../../domain/contracts/types';\nimport { ensureUIState } from '../../domain/validators';\nimport type { IRenderSurface, RenderOptions } from '../../ports/render.port';\nimport {\n MELLON_ROOT_ID,\n MELLON_BTN_SELECTOR,\n MELLON_FALLBACK_BTN_SELECTOR,\n MELLON_ACTION_FALLBACK_EMAIL,\n MELLON_ACTION_FALLBACK_QR,\n PRIMARY_BUTTON_LABEL,\n MODAL_PASSKEY_BUTTON_LABEL,\n TRIGGER_ARIA_LABEL,\n MODAL_PASSKEY_ARIA_LABEL,\n SVG_NS,\n} from './constants';\n\nexport { MELLON_ROOT_ID, MELLON_BTN_SELECTOR, MELLON_FALLBACK_BTN_SELECTOR };\nexport { MELLON_ACTION_FALLBACK_EMAIL, MELLON_ACTION_FALLBACK_QR };\nexport {\n PRIMARY_BUTTON_LABEL,\n MODAL_PASSKEY_BUTTON_LABEL,\n TRIGGER_ARIA_LABEL,\n MODAL_PASSKEY_ARIA_LABEL,\n};\n\n/** Fingerprint icon as inline SVG (no external resources). createElementNS only. */\nfunction createFingerprintIconSVG(): SVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('class', 'mellon-btn-icon');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n\n const path1 = document.createElementNS(SVG_NS, 'path');\n path1.setAttribute('d', 'M12 22a10 10 0 0 0 10-10 10 10 0 0 0-20 0 10 10 0 0 0 10 10Z');\n const path2 = document.createElementNS(SVG_NS, 'path');\n path2.setAttribute('d', 'M12 14a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2 2 2 0 0 0 2 2Z');\n const path3 = document.createElementNS(SVG_NS, 'path');\n path3.setAttribute('d', 'M5 19.05A9 9 0 0 1 3 12a9 9 0 0 1 2-5.05');\n\n svg.appendChild(path1);\n svg.appendChild(path2);\n svg.appendChild(path3);\n return svg;\n}\n\n/** Primary button default: fingerprint icon + visible label + aria-label. */\nfunction createPrimaryButtonDefault(\n disabled: boolean,\n label: string = PRIMARY_BUTTON_LABEL,\n ariaLabel: string = TRIGGER_ARIA_LABEL\n): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn';\n btn.setAttribute('aria-label', ariaLabel);\n btn.disabled = disabled;\n btn.appendChild(createFingerprintIconSVG());\n btn.appendChild(document.createTextNode(label));\n return btn;\n}\n\n/** Primary button pill: landing-style (rounded-full, circle with icon + label), touch target ≥48px. */\nfunction createPrimaryButtonPill(\n disabled: boolean,\n label: string = PRIMARY_BUTTON_LABEL,\n ariaLabel: string = TRIGGER_ARIA_LABEL\n): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn mellon-btn-pill';\n btn.setAttribute('aria-label', ariaLabel);\n btn.disabled = disabled;\n const iconCircle = document.createElement('span');\n iconCircle.className = 'mellon-btn-pill-icon-circle';\n iconCircle.setAttribute('aria-hidden', 'true');\n iconCircle.appendChild(createFingerprintIconSVG());\n btn.appendChild(iconCircle);\n btn.appendChild(document.createTextNode(label));\n return btn;\n}\n\n/** HOF: returns the primary button builder for the given variant (stateless). */\nfunction getPrimaryButtonBuilder(\n variant: ButtonVariant,\n label: string = PRIMARY_BUTTON_LABEL,\n ariaLabel: string = TRIGGER_ARIA_LABEL\n): (disabled: boolean) => HTMLButtonElement {\n return (disabled: boolean) =>\n variant === 'pill'\n ? createPrimaryButtonPill(disabled, label, ariaLabel)\n : createPrimaryButtonDefault(disabled, label, ariaLabel);\n}\n\n/** Resolves primary button options from RenderOptions (single source for defaults). */\nfunction getPrimaryButtonOptions(options: RenderOptions): {\n variant: ButtonVariant;\n label: string;\n ariaLabel: string;\n} {\n return {\n variant: options.buttonVariant ?? 'default',\n label: options.primaryButtonLabel ?? PRIMARY_BUTTON_LABEL,\n ariaLabel: options.primaryButtonAriaLabel ?? TRIGGER_ARIA_LABEL,\n };\n}\n\n/** Builds the primary passkey button for READY_LOGIN / READY_REGISTER / READY (DRY). */\nfunction buildPrimaryButtonForReadyState(options: RenderOptions): HTMLButtonElement {\n const { variant, label, ariaLabel } = getPrimaryButtonOptions(options);\n return getPrimaryButtonBuilder(variant, label, ariaLabel)(false);\n}\n\nfunction ensureRoot(surface: IRenderSurface): HTMLElement {\n const { shadowRoot } = surface;\n let root = shadowRoot.getElementById(MELLON_ROOT_ID);\n if (!root) {\n root = document.createElement('div');\n root.id = MELLON_ROOT_ID;\n root.className = 'mellon-root';\n shadowRoot.appendChild(root);\n }\n return root;\n}\n\nfunction createParagraph(className: string, text: string): HTMLParagraphElement {\n const p = document.createElement('p');\n p.className = className;\n p.textContent = text;\n return p;\n}\n\n/** Fallback button with data-mellon-action for host click handling. createElement/setAttribute only. */\nfunction createFallbackButton(\n action: 'fallback' | typeof MELLON_ACTION_FALLBACK_EMAIL | typeof MELLON_ACTION_FALLBACK_QR,\n label: string\n): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn mellon-btn-fallback';\n btn.setAttribute('data-mellon-action', action);\n btn.textContent = label;\n return btn;\n}\n\ntype FallbackState = 'FALLBACK' | 'FALLBACK_EMAIL' | 'FALLBACK_QR';\ntype FallbackAction =\n | 'fallback'\n | typeof MELLON_ACTION_FALLBACK_EMAIL\n | typeof MELLON_ACTION_FALLBACK_QR;\n\nconst FALLBACK_BUTTON_CONFIG: Record<FallbackState, { action: FallbackAction; label: string }> = {\n FALLBACK: { action: 'fallback', label: 'Continuar' },\n FALLBACK_EMAIL: { action: MELLON_ACTION_FALLBACK_EMAIL, label: 'Continuar con email' },\n FALLBACK_QR: { action: MELLON_ACTION_FALLBACK_QR, label: 'Continuar con QR' },\n};\n\nfunction buildFallbackUI(state: FallbackState): HTMLElement {\n const wrap = document.createElement('div');\n wrap.className = 'mellon-fallback';\n const msg = document.createElement('p');\n msg.className = 'mellon-message';\n msg.textContent = 'Fallback disponible.';\n wrap.appendChild(msg);\n const { action, label } = FALLBACK_BUTTON_CONFIG[state];\n wrap.appendChild(createFallbackButton(action, label));\n return wrap;\n}\n\nfunction buildContentForState(state: UIState, options: RenderOptions): DocumentFragment {\n const fragment = document.createDocumentFragment();\n\n switch (state) {\n case 'IDLE':\n case 'EVALUATING_ENV':\n fragment.appendChild(createParagraph('mellon-loading', 'Loading…'));\n break;\n\n case 'READY_LOGIN':\n fragment.appendChild(buildPrimaryButtonForReadyState(options));\n break;\n\n case 'READY_REGISTER':\n if (options.registerSessionReady === false) {\n fragment.appendChild(createParagraph('mellon-loading', 'Preparando registro…'));\n } else {\n fragment.appendChild(buildPrimaryButtonForReadyState(options));\n }\n break;\n\n case 'READY':\n fragment.appendChild(buildPrimaryButtonForReadyState(options));\n break;\n\n case 'AUTHENTICATING':\n fragment.appendChild(createParagraph('mellon-loading', 'Authenticating…'));\n break;\n\n case 'SUCCESS':\n fragment.appendChild(createParagraph('mellon-message', 'Success.'));\n break;\n\n case 'ERROR':\n fragment.appendChild(createParagraph('mellon-message', 'Something went wrong.'));\n break;\n\n case 'FALLBACK':\n case 'FALLBACK_EMAIL':\n case 'FALLBACK_QR':\n fragment.appendChild(buildFallbackUI(state));\n break;\n\n default:\n fragment.appendChild(createParagraph('mellon-loading', 'Loading…'));\n }\n\n return fragment;\n}\n\n/** Updates render surface from FSM state. Validates state at boundary; invalid → IDLE (fail-safe). */\nexport function render(surface: IRenderSurface, state: unknown, options: RenderOptions = {}): void {\n const safeState = ensureUIState(state);\n const root = ensureRoot(surface);\n const content = buildContentForState(safeState, options);\n root.replaceChildren(...Array.from(content.childNodes));\n}\n","/**\n * Auth render helpers: viewmodel → RenderOptions → shadow-render.\n * Single place to translate AuthButtonViewModel / AuthModalViewModel to the existing render() contract.\n */\nimport type { IRenderSurface } from '../../ports/render.port';\nimport type { RenderOptions } from '../../ports/render.port';\nimport type { AuthButtonViewModel, AuthModalViewModel } from '../../domain/auth-viewmodels';\nimport { tabToUIMode } from '../../domain/types';\nimport { render } from './shadow.adapter';\n\nfunction viewModelToRenderOptions(vm: AuthButtonViewModel): RenderOptions {\n return {\n theme: vm.theme,\n mode: vm.mode,\n buttonVariant: vm.buttonVariant,\n registerSessionReady: vm.registerSessionReady,\n primaryButtonLabel: vm.primaryButtonLabel,\n primaryButtonAriaLabel: vm.primaryButtonAriaLabel,\n };\n}\n\nfunction modalViewModelToRenderOptions(vm: AuthModalViewModel): RenderOptions {\n return {\n theme: vm.theme,\n mode: tabToUIMode(vm.tab),\n buttonVariant: 'pill',\n registerSessionReady: vm.registerSessionReady,\n primaryButtonLabel: vm.primaryButtonLabel,\n primaryButtonAriaLabel: vm.primaryButtonAriaLabel,\n };\n}\n\n/**\n * Renders the auth button/trigger FSM content onto the surface using the viewmodel.\n * Uses the existing shadow-render adapter; does not know DOM beyond the surface.\n */\nexport function renderAuthButton(surface: IRenderSurface, vm: AuthButtonViewModel): void {\n render(surface, vm.state, viewModelToRenderOptions(vm));\n}\n\n/**\n * Renders the auth modal FSM content onto the surface using the viewmodel.\n * Does not create modal structure (wrapper/overlay/panel); the WC must call ensureModalStructure first if applicable.\n */\nexport function renderAuthModal(surface: IRenderSurface, vm: AuthModalViewModel): void {\n render(surface, vm.state, modalViewModelToRenderOptions(vm));\n}\n","/**\n * Centralized constants for the interactions layer (click delegation, focus trap).\n * Selectors and attribute names used by dom.adapter and focus-trap.adapter.\n */\n\n/** Modal tabs container selector (register/login tab buttons). */\nexport const MELLON_MODAL_TABS_SELECTOR = '.mellon-modal-tabs';\n\n/** Attribute name for tab value on buttons (register | login). */\nexport const TAB_ATTR = 'data-tab';\n\n/** Focusable elements for focus trap (a11y). Excludes disabled and [tabindex=\"-1\"]. */\nexport const FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/** Selector for any explicit \\\"close modal\\\" control inside the modal content. */\nexport const MELLON_MODAL_CLOSE_SELECTOR = '[data-mellon-modal-close=\"true\"]';\n","/**\n * DOM interaction delegation in Shadow Root: clicks on primary button, fallback, modal tabs and close controls.\n * Semantic callbacks. Constants: interactions/constants.ts + render/constants.ts.\n */\nimport {\n MELLON_BTN_SELECTOR,\n MELLON_FALLBACK_BTN_SELECTOR,\n MELLON_ACTION_FALLBACK_EMAIL,\n MELLON_ACTION_FALLBACK_QR,\n OVERLAY_CLASS,\n} from '../render/constants';\nimport type { ModalTabKind } from '../../domain/contracts/types';\nimport { MELLON_MODAL_TABS_SELECTOR, MELLON_MODAL_CLOSE_SELECTOR, TAB_ATTR } from './constants';\n\n/** Maps data-mellon-action to fallback type. Generic \"fallback\" → undefined (same callback path). */\nfunction fallbackActionToType(action: string | null): 'email' | 'qr' | undefined {\n if (action === MELLON_ACTION_FALLBACK_EMAIL) return 'email';\n if (action === MELLON_ACTION_FALLBACK_QR) return 'qr';\n return undefined;\n}\n\nexport type AuthButtonInteractionConfig = {\n onPrimaryClick(): void;\n /** type undefined = generic \"Continuar\" (data-mellon-action=\"fallback\"). */\n onFallbackClick(type?: 'email' | 'qr'): void;\n};\n\nexport type AuthModalInteractionConfig = {\n onTabChange(tab: ModalTabKind): void;\n onPrimaryClick(): void;\n /** type undefined = generic fallback. */\n onFallbackClick(type?: 'email' | 'qr'): void;\n /** Called when user clicks the grey backdrop outside the modal panel. */\n onOverlayClick?(): void;\n /** Called when user clicks any control marked with data-mellon-modal-close=\"true\" inside the modal. */\n onCloseClick?(): void;\n};\n\n/**\n * Registers click delegation for the auth button: primary vs fallback.\n * Checks fallback first (more specific), then primary.\n * @returns Function to remove listeners (teardown).\n */\nexport function registerAuthButtonInteractions(\n root: ShadowRoot,\n config: AuthButtonInteractionConfig\n): () => void {\n const handler = (e: Event): void => {\n const target = e.target instanceof Element ? e.target : null;\n if (!target) return;\n\n const fallbackBtn = target.closest(MELLON_FALLBACK_BTN_SELECTOR);\n if (fallbackBtn instanceof HTMLButtonElement) {\n config.onFallbackClick(fallbackActionToType(fallbackBtn.getAttribute('data-mellon-action')));\n return;\n }\n\n if (target.closest(MELLON_BTN_SELECTOR)) {\n config.onPrimaryClick();\n }\n };\n\n root.addEventListener('click', handler);\n return () => root.removeEventListener('click', handler);\n}\n\n/**\n * Registers click delegation for the modal: close controls, tabs (register/login), primary button and overlay.\n * Order: explicit close → fallback → tabs → primary → overlay.\n * @returns Function to remove listeners (teardown).\n */\nexport function registerAuthModalInteractions(\n root: ShadowRoot,\n config: AuthModalInteractionConfig\n): () => void {\n const handler = (e: Event): void => {\n const target = e.target instanceof Element ? e.target : null;\n if (!target) return;\n\n if (config.onCloseClick) {\n const closeBtn = target.closest(MELLON_MODAL_CLOSE_SELECTOR);\n if (closeBtn instanceof HTMLElement) {\n config.onCloseClick();\n return;\n }\n }\n\n const fallbackBtn = target.closest(MELLON_FALLBACK_BTN_SELECTOR);\n if (fallbackBtn instanceof HTMLButtonElement) {\n config.onFallbackClick(fallbackActionToType(fallbackBtn.getAttribute('data-mellon-action')));\n return;\n }\n\n const tabsContainer = root.querySelector(MELLON_MODAL_TABS_SELECTOR);\n if (tabsContainer?.contains(target)) {\n const tabEl = target.closest(`[${TAB_ATTR}]`);\n const tab = tabEl?.getAttribute(TAB_ATTR);\n if (tab === 'register' || tab === 'login') {\n config.onTabChange(tab as ModalTabKind);\n return;\n }\n }\n\n if (target.closest(MELLON_BTN_SELECTOR)) {\n config.onPrimaryClick();\n return;\n }\n\n if (config.onOverlayClick) {\n const overlay = root.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (overlay && target === overlay) {\n config.onOverlayClick();\n }\n }\n };\n\n root.addEventListener('click', handler);\n return () => root.removeEventListener('click', handler);\n}\n","/**\n * WC styles. Injected via adoptedStyleSheets or <style> + textContent. No innerHTML.\n * Constructable Stylesheet when supported; <style> fallback (e.g. Safari <16.4).\n */\n\n/**\n * Host overrides via CSS custom properties. Delegation: --mellon-* fallback to MDS-like tokens\n * (--surface-elevated, --text-strong, etc.) so the host can drive look without coupling.\n * Default: white-label minimal TryMellon — neutral with a cool tint (220°), WCAG AA.\n * Theming and accessibility are configurable via WC attributes and host CSS.\n */\nexport const BASE_STYLES = `\n:host {\n display: block;\n max-width: 100%;\n border: none;\n outline: none;\n /* Inherit --font-sans from host (e.g. landing: Noto Sans JP) or --mellon-font-sans; fallback system stack. */\n font-family: var(--font-sans, var(--mellon-font-sans, system-ui, -apple-system, sans-serif));\n --mellon-surface: var(--mellon-surface, hsl(var(--surface-elevated, 220 14% 98%)));\n --mellon-text: var(--mellon-text, hsl(var(--text-strong, 220 12% 14%)));\n --mellon-text-muted: var(--mellon-text-muted, hsl(var(--text-muted, 220 10% 48%)));\n --mellon-border: var(--mellon-border, hsl(var(--border-strong, 220 10% 90%)));\n --mellon-primary: var(--mellon-primary, hsl(var(--primary, 217 91% 58%)));\n --mellon-primary-contrast: var(--mellon-primary-contrast, #fff);\n --mellon-radius: var(--mellon-radius, var(--radius, 8px));\n --mellon-focus-ring: var(--mellon-focus-ring, hsl(217 91% 50%));\n --mellon-overlay: var(--mellon-overlay, rgba(0,0,0,0.5));\n /* Panel padding: keeps content away from edges; host can override. */\n --mellon-modal-panel-padding: var(--mellon-modal-panel-padding, 2rem);\n /* Cross-device CTA: text colour (grey between strong and muted). */\n --mellon-cta-text-color: var(--mellon-cta-text-color, var(--mellon-text-muted));\n /* Separator: line and \"or\" text (standard UI divider). */\n --mellon-separator-line: var(--mellon-border);\n --mellon-separator-text: var(--mellon-text-muted);\n /* QR icon button (cross-device). */\n --mellon-qr-btn-bg: var(--mellon-qr-btn-bg, transparent);\n --mellon-qr-btn-border: var(--mellon-qr-btn-border, var(--mellon-border));\n --mellon-qr-btn-color: var(--mellon-qr-btn-color, var(--mellon-text));\n}\n:host([theme=\"dark\"]) {\n --mellon-surface: var(--mellon-surface, hsl(var(--surface-elevated, 220 12% 11%)));\n --mellon-text: var(--mellon-text, hsl(var(--text-strong, 220 10% 96%)));\n --mellon-text-muted: var(--mellon-text-muted, hsl(var(--text-muted, 220 8% 62%)));\n --mellon-border: var(--mellon-border, hsl(var(--border-strong, 220 10% 22%)));\n --mellon-primary: var(--mellon-primary, hsl(var(--primary, 217 96% 72%)));\n --mellon-primary-contrast: var(--mellon-primary-contrast, #fff);\n --mellon-focus-ring: var(--mellon-focus-ring, hsl(217 96% 65%));\n}\n/* Pill variant: landing-style button (circle + label) uses same tokens. */\n:host([button-variant=\"pill\"]) .mellon-btn-pill {\n --mellon-btn-bg: var(--mellon-surface);\n --mellon-btn-border: var(--mellon-border);\n --mellon-btn-text: var(--mellon-text);\n}\n.mellon-root {\n padding: 1rem;\n min-width: 0;\n background: var(--mellon-surface);\n color: var(--mellon-text);\n border-radius: var(--mellon-radius);\n}\n.mellon-loading,\n.mellon-message {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mellon-text-muted);\n}\n.mellon-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n min-height: 48px;\n padding: 12px 24px;\n font-size: 1rem;\n font-weight: 500;\n background: var(--mellon-primary);\n color: var(--mellon-primary-contrast);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n}\n.mellon-btn:hover:not(:disabled) {\n opacity: 0.92;\n}\n.mellon-btn:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n.mellon-btn .mellon-btn-icon {\n width: 1.25em;\n height: 1.25em;\n flex-shrink: 0;\n}\n.mellon-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n.mellon-btn-pill {\n min-height: 48px;\n min-width: 48px;\n padding: 0.5rem 1.25rem;\n border-radius: 9999px;\n border: none;\n background: var(--mellon-surface);\n color: var(--mellon-text);\n gap: 0.75rem;\n}\n.mellon-btn-pill .mellon-btn-pill-icon-circle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.275em;\n height: 1.275em;\n border-radius: 50%;\n border: 2px solid currentColor;\n flex-shrink: 0;\n}\n.mellon-btn-pill .mellon-btn-pill-icon-circle .mellon-btn-icon {\n width: 0.85em;\n height: 0.85em;\n}\n@media (prefers-reduced-motion: reduce) {\n .mellon-btn, .mellon-modal-wrapper { transition: none; }\n}\n`.trim();\n\n/** Evaluated at load. Browser-only SDK; would be false in SSR. */\nconst SUPPORTS_ADOPTED_STYLESHEETS =\n typeof ShadowRoot !== 'undefined' &&\n 'adoptedStyleSheets' in ShadowRoot.prototype &&\n typeof CSSStyleSheet !== 'undefined' &&\n 'replaceSync' in CSSStyleSheet.prototype;\n\n/** Returns CSSStyleSheet for adoptedStyleSheets when supported; null otherwise (use <style> + textContent). */\nexport function createConstructableStylesheet(): CSSStyleSheet | null {\n if (!SUPPORTS_ADOPTED_STYLESHEETS) return null;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(BASE_STYLES);\n return sheet;\n } catch {\n return null;\n }\n}\n\n/** Returns CSS string for <style> textContent (fallback). */\nexport function getStylesFallback(): string {\n return BASE_STYLES;\n}\n\n/** Extra styles for trymellon-auth-modal: overlay, panel, tabs. */\nexport const MODAL_EXTRA_STYLES = `\n/* Host: full viewport when open, no border (only the inner panel has border). */\n:host {\n border: none;\n outline: none;\n}\n:host([open=\"true\"]) {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n pointer-events: none;\n}\n:host([open=\"true\"]) .mellon-modal-wrapper {\n pointer-events: auto;\n}\n/* Wrapper: fills host, no border. Overlay + panel are the only visible layers. */\n.mellon-modal-wrapper {\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border: none;\n outline: none;\n}\n/* Overlay: full viewport, transparent grey only (no border). */\n.mellon-modal-overlay {\n position: fixed;\n inset: 0;\n background: var(--mellon-overlay, rgba(0,0,0,0.5));\n z-index: 1;\n border: none;\n}\n/* Panel: vertical gap 2rem (top/bottom) so it doesn't sit flush with viewport edge; sides 1.5rem. Match landing font via --font-sans. */\n.mellon-modal-panel {\n position: fixed;\n inset: max(2rem, env(safe-area-inset-top)) max(1.5rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(1.5rem, env(safe-area-inset-left));\n margin: auto;\n z-index: 2;\n width: calc(100% - 3rem);\n max-width: 30rem;\n max-height: min(90vh, 34rem);\n overflow-y: auto;\n overflow-x: hidden;\n box-sizing: border-box;\n background: var(--mellon-surface);\n color: var(--mellon-text);\n font-family: var(--font-sans, var(--mellon-font-sans, inherit));\n border-radius: 12px;\n border: 1px solid var(--mellon-border);\n padding: var(--mellon-modal-panel-padding);\n box-shadow: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04);\n -webkit-overflow-scrolling: touch;\n}\n/* Close button: circular \"X\" in the top-right corner, aligned with panel padding. */\n.mellon-modal-close-btn {\n position: absolute;\n top: 0.75rem;\n right: 0.75rem;\n left: auto;\n bottom: auto;\n width: 2.25rem; /* 36px */\n height: 2.25rem; /* 36px */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 9999px;\n border: none;\n background: color-mix(in srgb, var(--mellon-surface) 80%, #000 20%);\n color: var(--mellon-text-muted);\n cursor: pointer;\n padding: 0;\n font-size: 1.1rem;\n line-height: 1;\n}\n.mellon-modal-close-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mellon-surface) 70%, #000 30%);\n color: var(--mellon-text);\n}\n.mellon-modal-close-btn:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n:host([theme=\"dark\"]) .mellon-modal-panel {\n box-shadow: 0 8px 24px -4px rgba(0,0,0,0.35), 0 4px 8px -4px rgba(0,0,0,0.2);\n}\n/* Dialog title and description: centered, with vertical breathing room. */\n.mellon-dialog-title,\n.mellon-dialog-desc {\n margin: 0 0 0.75rem;\n padding: 0;\n font-size: 1rem;\n line-height: 1.5;\n color: var(--mellon-text);\n text-align: center;\n}\n.mellon-dialog-title {\n font-weight: 600;\n font-size: 1.125rem;\n margin-top: 1.25rem;\n}\n.mellon-dialog-desc {\n color: var(--mellon-text-muted);\n font-size: 0.875rem;\n margin-bottom: 1rem;\n}\n/* Modal spacing scale: base 0.5rem (8px); sections 0.75–1rem; tight 0.25rem. */\n.mellon-modal-tabs {\n display: flex;\n gap: 0;\n padding: 0 0 0.75rem;\n border-bottom: none;\n}\n.mellon-modal-tabs button {\n flex: 1;\n min-height: 2.75rem;\n padding: 0.625rem 1rem;\n font-size: 0.875rem;\n font-weight: 400;\n background: transparent;\n color: var(--mellon-text-muted);\n border: none;\n border-bottom: 1px solid var(--mellon-border);\n cursor: pointer;\n}\n.mellon-modal-tabs button[aria-selected=\"true\"] {\n border-bottom-color: var(--mellon-primary);\n font-weight: 600;\n color: var(--mellon-text);\n}\n.mellon-modal-tabs button:hover {\n color: var(--mellon-text);\n}\n.mellon-modal-tabs button:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n/* Content wrapper: QR wrap → separator \"or\" → passkey; all centered with consistent vertical gap. */\n.mellon-modal-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5rem; /* 8px */\n}\n/* QR / cross-device area: centered; no min-height when empty to avoid extra space. */\n.mellon-cross-device-wrap {\n min-height: 11.25rem; /* 180px */\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n margin-top: 0.85rem; /* ~10% más margen con el top (tabs) */\n margin-bottom: 0.5rem; /* 8px */\n}\n/* Skeleton and error (modal-owned): visibility by data-qr-area-state. */\n.mellon-cross-device-skeleton,\n.mellon-cross-device-error {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mellon-cta-text-color);\n text-align: center;\n width: 11.25rem; /* 180px */\n height: 11.25rem; /* 180px */\n padding: 0 0.75rem; /* 0 12px */\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 0.75rem;\n border: 1px dashed var(--mellon-separator-line);\n box-sizing: border-box;\n background: var(--mellon-surface-elevated, rgba(128, 128, 128, 0.12));\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"default\"] .mellon-cross-device-error,\n.mellon-cross-device-wrap[data-qr-area-state=\"loaded\"] .mellon-cross-device-skeleton,\n.mellon-cross-device-wrap[data-qr-area-state=\"loaded\"] .mellon-cross-device-error {\n display: none;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"waiting\"] .mellon-cross-device-slot-wrap,\n.mellon-cross-device-wrap[data-qr-area-state=\"waiting\"] .mellon-cross-device-error {\n display: none;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"waiting\"] .mellon-cross-device-skeleton {\n display: flex;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"timeout\"] .mellon-cross-device-slot-wrap,\n.mellon-cross-device-wrap[data-qr-area-state=\"timeout\"] .mellon-cross-device-skeleton {\n display: none;\n}\n.mellon-cross-device-wrap[data-qr-area-state=\"timeout\"] .mellon-cross-device-error {\n display: flex;\n}\n.mellon-cross-device-slot-wrap {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 11.25rem; /* 180px */\n height: 11.25rem; /* 180px */\n}\n/* Default slot content: \"Try from another device\" (variable colour) + QR icon button; centered in column. */\n.mellon-cross-device-cta {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.75rem;\n width: fit-content;\n max-width: 100%;\n margin-top: 0.5rem;\n margin-left: auto;\n margin-right: auto;\n}\n.mellon-cross-device-cta-text {\n margin: 0;\n font-size: 0.875rem;\n color: var(--mellon-cta-text-color);\n}\n.mellon-cross-device-cta .mellon-btn-qr-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 48px;\n min-height: 48px;\n padding: 0.5rem;\n background: var(--mellon-qr-btn-bg);\n color: var(--mellon-qr-btn-color);\n border: 1px solid var(--mellon-qr-btn-border);\n border-radius: var(--mellon-radius);\n cursor: pointer;\n}\n.mellon-cross-device-cta .mellon-btn-qr-icon:hover:not(:disabled) {\n background: var(--mellon-separator-line);\n}\n.mellon-cross-device-cta .mellon-btn-qr-icon:focus-visible {\n outline: 2px solid var(--mellon-focus-ring);\n outline-offset: 2px;\n}\n.mellon-qr-icon {\n width: 1.75rem;\n height: 1.75rem;\n}\n/* Separator: standard UI divider — line | \"or\" | line (all colours via variables). ~15% más margen con el bloque de arriba. */\n.mellon-modal-separator {\n display: flex;\n align-items: center;\n gap: 1rem;\n width: 100%;\n margin-top: 0.875rem; /* 0.75rem + ~15% */\n margin-bottom: 0;\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--mellon-separator-text);\n}\n.mellon-modal-separator::before,\n.mellon-modal-separator::after {\n content: '';\n flex: 1;\n min-width: 0;\n height: 0;\n border-bottom: 1px solid var(--mellon-separator-line);\n}\n.mellon-modal-separator .mellon-separator-text {\n text-transform: uppercase;\n letter-spacing: 0.08em;\n font-size: 0.75rem;\n flex-shrink: 0;\n position: relative;\n padding: 0.375rem 1.25rem;\n background: transparent;\n z-index: 0;\n}\n.mellon-modal-separator .mellon-separator-text::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n width: 140%;\n height: 220%;\n transform: translate(-50%, -50%) rotate(45deg);\n border-radius: 0.35rem;\n border: 2px solid var(--mellon-separator-line);\n background: color-mix(in srgb, var(--mellon-surface) 80%, var(--mellon-text) 20%);\n z-index: -1;\n}\n/* Passkey slot/root centered in content wrapper. Less space between separator and this block. */\n.mellon-modal-separator + .mellon-root {\n margin-top: -0.25rem;\n}\n.mellon-modal-content .mellon-root {\n display: flex;\n justify-content: center;\n width: 100%;\n}\n/* QR skeleton loading dots: \"Loading QRs\" + animated trailing dots while waiting. */\n.mellon-qr-dots {\n display: inline-block;\n width: 1.5em;\n text-align: left;\n overflow: hidden;\n}\n.mellon-qr-dots::after {\n content: '...';\n display: inline-block;\n animation: mellon-qr-dots 1s steps(4, end) infinite;\n}\n@keyframes mellon-qr-dots {\n 0% {\n clip-path: inset(0 100% 0 0);\n }\n 33% {\n clip-path: inset(0 66% 0 0);\n }\n 66% {\n clip-path: inset(0 33% 0 0);\n }\n 100% {\n clip-path: inset(0 0 0 0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .mellon-qr-dots::after {\n animation: none;\n }\n}\n/* Minimal variant: opaque backdrop + panel (no reliance on host CSS vars when modal is in body). */\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-overlay {\n background: rgba(0, 0, 0, 0.65);\n}\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-panel {\n border-radius: 1rem;\n border-width: 2px;\n border-style: solid;\n}\n:host([theme=\"dark\"]) [data-mellon-modal-variant=\"minimal\"] {\n --mellon-border: rgba(255, 255, 255, 0.9);\n}\n:host([theme=\"light\"]) [data-mellon-modal-variant=\"minimal\"] {\n --mellon-border: rgba(0, 0, 0, 0.15);\n}\n:host([theme=\"dark\"]) [data-mellon-modal-variant=\"minimal\"] .mellon-modal-panel {\n background: #0f0f0f;\n}\n:host([theme=\"light\"]) [data-mellon-modal-variant=\"minimal\"] .mellon-modal-panel {\n background: #ffffff;\n}\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-tabs {\n padding: 0.5rem 1rem 0;\n border-bottom-width: 2px;\n}\n[data-mellon-modal-variant=\"minimal\"] .mellon-modal-tabs button {\n padding: 0.4rem 0.6rem;\n font-size: 0.8125rem;\n}\n/* Responsive: narrow viewports — minimum padding so 5% does not get too small. */\n@media (max-width: 22.5rem) {\n .mellon-modal-panel {\n --mellon-modal-panel-padding: max(1rem, 5%);\n }\n .mellon-modal-tabs {\n padding: 0.75rem 0;\n }\n .mellon-modal-tabs button {\n padding: 0.625rem 0.75rem;\n }\n .mellon-modal-content {\n gap: 0.75rem;\n }\n}\n/* Responsive: very short viewport (e.g. landscape) — ensure panel scrolls. */\n@media (max-height: 400px) {\n .mellon-modal-panel {\n max-height: calc(100dvh - 4rem);\n }\n}\n`.trim();\n\n/** Returns BASE_STYLES + MODAL_EXTRA_STYLES for modal WC. */\nexport function getModalStylesFallback(): string {\n return BASE_STYLES + '\\n' + MODAL_EXTRA_STYLES;\n}\n\n/** Constructable stylesheet for modal (base + overlay/panel/tabs). */\nexport function createModalConstructableStylesheet(): CSSStyleSheet | null {\n if (!SUPPORTS_ADOPTED_STYLESHEETS) return null;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(BASE_STYLES + '\\n' + MODAL_EXTRA_STYLES);\n return sheet;\n } catch {\n return null;\n }\n}\n","export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport function map<T, E, U>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E> {\n if (result.ok) {\n return ok(mapper(result.value));\n }\n return result;\n}\n\nexport function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F> {\n if (!result.ok) {\n return err(mapper(result.error));\n }\n return result;\n}\n\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (result.ok) {\n return result.value;\n }\n throw result.error;\n}\n","export type TryMellonErrorCode =\n | 'NOT_SUPPORTED'\n | 'USER_CANCELLED'\n | 'PASSKEY_NOT_FOUND'\n | 'SESSION_EXPIRED'\n | 'NETWORK_FAILURE'\n | 'INVALID_ARGUMENT'\n | 'TIMEOUT'\n | 'ABORTED'\n | 'ABORT_ERROR'\n | 'CHALLENGE_MISMATCH'\n | 'UNKNOWN_ERROR';\n\nexport class TryMellonError extends Error {\n readonly code: TryMellonErrorCode;\n readonly details?: unknown;\n readonly isTryMellonError = true;\n\n constructor(code: TryMellonErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TryMellonError';\n this.code = code;\n this.details = details;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TryMellonError);\n }\n }\n}\n\nconst DEFAULT_MESSAGES: Record<TryMellonErrorCode, string> = {\n NOT_SUPPORTED: 'WebAuthn is not supported in this environment',\n USER_CANCELLED: 'User cancelled the operation',\n PASSKEY_NOT_FOUND: 'Passkey not found',\n SESSION_EXPIRED: 'Session has expired',\n NETWORK_FAILURE: 'Network request failed',\n INVALID_ARGUMENT: 'Invalid argument provided',\n TIMEOUT: 'Operation timed out',\n ABORTED: 'Operation was aborted',\n ABORT_ERROR: 'Operation aborted by user or timeout',\n CHALLENGE_MISMATCH: 'This link was already used or expired. Please try again from your computer.',\n UNKNOWN_ERROR: 'An unknown error occurred',\n};\n\nexport function createError(\n code: TryMellonErrorCode,\n message?: string,\n details?: unknown\n): TryMellonError {\n return new TryMellonError(code, message ?? DEFAULT_MESSAGES[code], details);\n}\n\nexport function isTryMellonError(error: unknown): error is TryMellonError {\n return (\n error instanceof TryMellonError ||\n (typeof error === 'object' &&\n error !== null &&\n 'isTryMellonError' in error &&\n (error as TryMellonError).isTryMellonError === true)\n );\n}\n\nexport function createNotSupportedError(): TryMellonError {\n return createError('NOT_SUPPORTED');\n}\n\nexport function createUserCancelledError(): TryMellonError {\n return createError('USER_CANCELLED');\n}\n\nexport function createNetworkError(cause?: Error): TryMellonError {\n return createError('NETWORK_FAILURE', undefined, {\n cause: cause?.message,\n originalError: cause,\n });\n}\n\nexport function createTimeoutError(): TryMellonError {\n return createError('TIMEOUT');\n}\n\nexport function createInvalidArgumentError(field: string, reason: string): TryMellonError {\n return createError('INVALID_ARGUMENT', `Invalid argument: ${field} - ${reason}`, {\n field,\n reason,\n });\n}\n\nexport function createCredentialError(operation: 'create' | 'get'): TryMellonError {\n return createError('UNKNOWN_ERROR', `Failed to ${operation} credential`, { operation });\n}\n\nexport function createEncodingError(type: 'encode' | 'decode'): TryMellonError {\n return createError(\n 'NOT_SUPPORTED',\n `No base64 ${type === 'encode' ? 'encoding' : 'decoding'} available`,\n { type }\n );\n}\n\nexport function validateNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (!value || typeof value !== 'string' || value.trim() === '') {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n}\n\nexport function validateUrl(url: string, fieldName: string): void {\n try {\n const urlObj = new URL(url);\n if (urlObj.protocol !== 'https:' && urlObj.protocol !== 'http:') {\n throw createInvalidArgumentError(fieldName, 'must use http or https protocol');\n }\n } catch (error) {\n if (isTryMellonError(error)) {\n throw error;\n }\n throw createInvalidArgumentError(fieldName, 'must be a valid URL');\n }\n}\n\nexport function validateRange(value: number, fieldName: string, min: number, max: number): void {\n if (!Number.isFinite(value)) {\n throw createInvalidArgumentError(fieldName, 'must be a finite number');\n }\n if (value < min || value > max) {\n throw createInvalidArgumentError(fieldName, `must be between ${min} and ${max}`);\n }\n}\n\nexport function validateBase64Url(s: string, fieldName: string): void {\n if (typeof s !== 'string' || s.length === 0) {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n if (!/^[A-Za-z0-9_-]+$/.test(s)) {\n throw createInvalidArgumentError(fieldName, 'must be a valid base64url string');\n }\n}\n\nconst DOM_EXCEPTION_ERROR_MAP: Record<string, TryMellonErrorCode> = {\n NotAllowedError: 'USER_CANCELLED',\n AbortError: 'ABORTED',\n NotSupportedError: 'NOT_SUPPORTED',\n SecurityError: 'NOT_SUPPORTED',\n InvalidStateError: 'UNKNOWN_ERROR',\n UnknownError: 'UNKNOWN_ERROR',\n};\n\n/**\n * Maps backend API error codes (fintech envelope) to TryMellonErrorCode.\n * Pure, testable. Unknown codes map to UNKNOWN_ERROR.\n * Defensive: non-string input returns UNKNOWN_ERROR (no throw).\n */\nexport function mapBackendErrorCodeToTryMellon(backendCode: string): TryMellonErrorCode {\n if (typeof backendCode !== 'string') return 'UNKNOWN_ERROR';\n const normalized = backendCode.toLowerCase().trim();\n const map: Record<string, TryMellonErrorCode> = {\n challenge_mismatch: 'CHALLENGE_MISMATCH',\n session_expired: 'SESSION_EXPIRED',\n unauthorized: 'SESSION_EXPIRED',\n validation_error: 'INVALID_ARGUMENT',\n invalid_argument: 'INVALID_ARGUMENT',\n user_not_found: 'SESSION_EXPIRED',\n passkey_not_found: 'PASSKEY_NOT_FOUND',\n };\n return map[normalized] ?? 'UNKNOWN_ERROR';\n}\n\nexport function mapWebAuthnError(error: unknown): TryMellonError {\n if (error instanceof DOMException) {\n const name = error.name;\n const message = error.message || 'WebAuthn operation failed';\n const errorCode = DOM_EXCEPTION_ERROR_MAP[name] ?? 'UNKNOWN_ERROR';\n return createError(errorCode, message, { originalError: error });\n }\n\n if (error instanceof Error) {\n return createError('UNKNOWN_ERROR', error.message, { originalError: error });\n }\n\n return createError('UNKNOWN_ERROR', 'An unknown error occurred', {\n originalError: error,\n });\n}\n","import { err, ok, type Result } from '../../utils/result';\nimport { createError, type TryMellonError } from '../../errors';\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nexport function validationError(\n message: string,\n details?: { field?: string; expected?: string; originalData?: unknown }\n): Result<never, TryMellonError> {\n return err(\n createError('UNKNOWN_ERROR', message, {\n ...details,\n originalData: details?.originalData,\n })\n );\n}\n\nexport function required(obj: Record<string, unknown>, key: string): unknown {\n return obj[key];\n}\n\nexport function optionalString(obj: Record<string, unknown>, key: string): string | undefined {\n const v = obj[key];\n return v === undefined ? undefined : typeof v === 'string' ? v : undefined;\n}\n\n// DRY Helpers for common TryMellon objects\n\nexport function validateChallengeRP(rp: unknown, data: unknown): Result<true, TryMellonError> {\n if (!isObject(rp) || !isString(rp.name) || !isString(rp.id)) {\n return validationError('Invalid API response: challenge.rp must have name and id strings', {\n originalData: data,\n });\n }\n return ok(true);\n}\n\nexport function validateChallengeUser(user: unknown, data: unknown): Result<true, TryMellonError> {\n if (\n !isObject(user) ||\n !isString(user.id) ||\n !isString(user.name) ||\n !isString(user.displayName)\n ) {\n return validationError(\n 'Invalid API response: challenge.user must have id, name, displayName strings',\n { originalData: data }\n );\n }\n return ok(true);\n}\n\nexport function validatePubKeyCredParams(\n params: unknown,\n data: unknown\n): Result<true, TryMellonError> {\n if (!isArray(params)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of params) {\n if (!isObject(item) || item.type !== 'public-key' || !isNumber(item.alg)) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n { originalData: data }\n );\n }\n }\n return ok(true);\n}\n\nexport function validateUserEntity(\n user: unknown,\n data: unknown\n): Result<\n { user_id: string; external_user_id: string; email?: string; metadata?: Record<string, unknown> },\n TryMellonError\n> {\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const userId = required(user, 'user_id');\n const externalUserId = required(user, 'external_user_id');\n if (!isString(userId) || !isString(externalUserId)) {\n return validationError(\n 'Invalid API response: user must have user_id and external_user_id strings',\n { originalData: data }\n );\n }\n\n const email = user.email;\n const metadata = user.metadata;\n if (email !== undefined && !isString(email)) {\n return validationError('Invalid API response: user.email must be string', {\n originalData: data,\n });\n }\n if (metadata !== undefined && (typeof metadata !== 'object' || metadata === null)) {\n return validationError('Invalid API response: user.metadata must be object', {\n originalData: data,\n });\n }\n\n return ok({\n user_id: userId,\n external_user_id: externalUserId,\n ...(email !== undefined && { email }),\n ...(metadata !== undefined && { metadata: metadata as Record<string, unknown> }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n RegisterStartResponse,\n AuthStartResponse,\n RegisterFinishResponse,\n AuthFinishResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport {\n isObject,\n isString,\n isNumber,\n isBoolean,\n isArray,\n validationError,\n required,\n validateChallengeRP,\n validateChallengeUser,\n validatePubKeyCredParams,\n validateUserEntity,\n} from './helpers';\n\nexport function validateRegisterStartResponse(\n data: unknown\n): Result<RegisterStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const rpResult = validateChallengeRP(required(challenge, 'rp'), data);\n if (!rpResult.ok) return rpResult;\n\n const userResult = validateChallengeUser(required(challenge, 'user'), data);\n if (!userResult.ok) return userResult;\n\n const challengeStr = required(challenge, 'challenge');\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n\n const pubKeyCredParamsResult = validatePubKeyCredParams(\n required(challenge, 'pubKeyCredParams'),\n data\n );\n if (!pubKeyCredParamsResult.ok) return pubKeyCredParamsResult;\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const excludeCredentials = challenge.excludeCredentials;\n if (excludeCredentials !== undefined) {\n if (!isArray(excludeCredentials)) {\n return validationError('Invalid API response: excludeCredentials must be array', {\n originalData: data,\n });\n }\n for (const c of excludeCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: excludeCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const authenticatorSelection = challenge.authenticatorSelection;\n if (authenticatorSelection !== undefined && !isObject(authenticatorSelection)) {\n return validationError('Invalid API response: authenticatorSelection must be object', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n challenge: {\n rp: challenge.rp as RegisterStartResponse['challenge']['rp'],\n user: challenge.user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams:\n challenge.pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n ...(timeout !== undefined && { timeout }),\n ...(excludeCredentials !== undefined && {\n excludeCredentials:\n excludeCredentials as RegisterStartResponse['challenge']['excludeCredentials'],\n }),\n ...(authenticatorSelection !== undefined && {\n authenticatorSelection:\n authenticatorSelection as RegisterStartResponse['challenge']['authenticatorSelection'],\n }),\n },\n });\n}\n\nexport function validateAuthStartResponse(\n data: unknown\n): Result<AuthStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const ch = required(challenge, 'challenge');\n const rpId = required(challenge, 'rpId');\n const allowCredentials = challenge.allowCredentials;\n if (!isString(ch)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isString(rpId)) {\n return validationError('Invalid API response: challenge.rpId must be string', {\n originalData: data,\n });\n }\n if (allowCredentials !== undefined && !isArray(allowCredentials)) {\n return validationError('Invalid API response: allowCredentials must be array', {\n originalData: data,\n });\n }\n if (allowCredentials) {\n for (const c of allowCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: allowCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const userVerification = challenge.userVerification;\n if (\n userVerification !== undefined &&\n !['required', 'preferred', 'discouraged'].includes(String(userVerification))\n ) {\n return validationError(\n 'Invalid API response: userVerification must be required|preferred|discouraged',\n {\n originalData: data,\n }\n );\n }\n\n return ok({\n session_id,\n challenge: {\n challenge: ch,\n rpId,\n allowCredentials:\n (allowCredentials as AuthStartResponse['challenge']['allowCredentials']) ?? [],\n ...(timeout !== undefined && { timeout }),\n ...(userVerification !== undefined && {\n userVerification: userVerification as AuthStartResponse['challenge']['userVerification'],\n }),\n },\n });\n}\n\nexport function validateRegisterFinishResponse(\n data: unknown\n): Result<RegisterFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const credential_id = required(data, 'credential_id');\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n const redirect_url = data.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n credential_id,\n status,\n session_token,\n user: userResult.value,\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n\nexport function validateAuthFinishResponse(\n data: unknown\n): Result<AuthFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const authenticated = required(data, 'authenticated');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const signals = required(data, 'signals');\n\n if (!isBoolean(authenticated)) {\n return validationError('Invalid API response: authenticated must be boolean', {\n field: 'authenticated',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n if (signals !== undefined && !isObject(signals)) {\n return validationError('Invalid API response: signals must be object', {\n originalData: data,\n });\n }\n\n const redirect_url = data.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n authenticated,\n session_token,\n user: userResult.value,\n signals: signals as AuthFinishResponse['signals'],\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { SessionValidateResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isBoolean, required, validationError } from './helpers';\n\nexport function validateSessionValidateResponse(\n data: unknown\n): Result<SessionValidateResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const valid = required(data, 'valid');\n const user_id = required(data, 'user_id');\n const external_user_id = required(data, 'external_user_id');\n const tenant_id = required(data, 'tenant_id');\n const app_id = required(data, 'app_id');\n\n if (!isBoolean(valid)) {\n return validationError('Invalid API response: valid must be boolean', {\n field: 'valid',\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n field: 'user_id',\n originalData: data,\n });\n }\n if (!isString(external_user_id)) {\n return validationError('Invalid API response: external_user_id must be string', {\n field: 'external_user_id',\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n field: 'tenant_id',\n originalData: data,\n });\n }\n if (!isString(app_id)) {\n return validationError('Invalid API response: app_id must be string', {\n field: 'app_id',\n originalData: data,\n });\n }\n\n return ok({\n valid,\n user_id,\n external_user_id,\n tenant_id,\n app_id,\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\n\nexport function validateEmailVerifyResponse(\n data: unknown\n): Result<{ sessionToken: string; redirectUrl?: string }, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const raw =\n (data as Record<string, unknown>).session_token ??\n (data as Record<string, unknown>).sessionToken;\n if (!isString(raw)) {\n return validationError('Invalid API response: session_token/sessionToken must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n const redirect_url = (data as Record<string, unknown>).redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n sessionToken: raw,\n ...(redirect_url !== undefined && { redirectUrl: redirect_url }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterResponse,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteResponse,\n RegisterStartResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isNumber, isArray, required, validationError } from './helpers';\n\nconst ONBOARDING_STATUSES = ['pending_passkey', 'pending_data', 'completed'] as const;\nconst REGISTER_PASSKEY_STATUSES = ['pending_data', 'completed'] as const;\n\nexport function validateOnboardingStartResponse(\n data: unknown\n): Result<OnboardingStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n field: 'onboarding_url',\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n field: 'expires_in',\n originalData: data,\n });\n }\n\n return ok({ session_id, onboarding_url, expires_in });\n}\n\nexport function validateOnboardingStatusResponse(\n data: unknown\n): Result<OnboardingStatusResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (\n !isString(status) ||\n !ONBOARDING_STATUSES.includes(status as (typeof ONBOARDING_STATUSES)[number])\n ) {\n return validationError(\n 'Invalid API response: status must be pending_passkey|pending_data|completed',\n {\n field: 'status',\n originalData: data,\n }\n );\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as OnboardingStatusResponse['status'],\n onboarding_url,\n expires_in,\n });\n}\n\n/** Response may include optional challenge for same-device passkey registration */\nexport type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {\n challenge?: RegisterStartResponse['challenge'];\n};\n\nexport function validateOnboardingRegisterResponse(\n data: unknown\n): Result<OnboardingRegisterResponseWithChallenge, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (status !== 'pending_passkey') {\n return validationError('Invalid API response: status must be pending_passkey', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n\n const challenge = data.challenge;\n let parsedChallenge: RegisterStartResponse['challenge'] | undefined;\n if (challenge !== undefined) {\n const chResult = validateOnboardingChallenge(challenge);\n if (!chResult.ok) return chResult;\n parsedChallenge = chResult.value;\n }\n\n return ok({\n session_id,\n status: 'pending_passkey',\n onboarding_url,\n ...(parsedChallenge !== undefined && { challenge: parsedChallenge }),\n });\n}\n\nfunction validateOnboardingChallenge(\n data: unknown\n): Result<RegisterStartResponse['challenge'], TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: challenge must be object', {\n originalData: data,\n });\n }\n\n const rp = required(data, 'rp');\n const user = required(data, 'user');\n const challengeStr = required(data, 'challenge');\n const pubKeyCredParams = required(data, 'pubKeyCredParams');\n\n if (\n !isObject(rp) ||\n !isString((rp as Record<string, unknown>).name) ||\n !isString((rp as Record<string, unknown>).id)\n ) {\n return validationError('Invalid API response: challenge.rp must have name and id', {\n originalData: data,\n });\n }\n if (\n !isObject(user) ||\n !isString((user as Record<string, unknown>).id) ||\n !isString((user as Record<string, unknown>).name) ||\n !isString((user as Record<string, unknown>).displayName)\n ) {\n return validationError('Invalid API response: challenge.user must have id, name, displayName', {\n originalData: data,\n });\n }\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isArray(pubKeyCredParams)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of pubKeyCredParams) {\n if (\n !isObject(item) ||\n (item as Record<string, unknown>).type !== 'public-key' ||\n !isNumber((item as Record<string, unknown>).alg)\n ) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n {\n originalData: data,\n }\n );\n }\n }\n\n return ok({\n rp: rp as RegisterStartResponse['challenge']['rp'],\n user: user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams: pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n });\n}\n\nexport function validateOnboardingRegisterPasskeyResponse(\n data: unknown\n): Result<OnboardingRegisterPasskeyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (\n !isString(status) ||\n !REGISTER_PASSKEY_STATUSES.includes(status as (typeof REGISTER_PASSKEY_STATUSES)[number])\n ) {\n return validationError('Invalid API response: status must be pending_data|completed', {\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n status: status as OnboardingRegisterPasskeyResponse['status'],\n user_id,\n tenant_id,\n });\n}\n\nexport function validateOnboardingCompleteResponse(\n data: unknown\n): Result<OnboardingCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n const session_token = required(data, 'session_token');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (status !== 'completed') {\n return validationError('Invalid API response: status must be completed', {\n originalData: data,\n });\n }\n if (!isString(user_id) || !isString(tenant_id) || !isString(session_token)) {\n return validationError(\n 'Invalid API response: user_id, tenant_id, session_token must be strings',\n { originalData: data }\n );\n }\n\n return ok({\n session_id,\n status: 'completed',\n user_id,\n tenant_id,\n session_token,\n });\n}\n","import { ok } from '../../utils/result';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n} from '../../types';\n\n/**\n * Validates the response for cross-device verify and verify-registration endpoints.\n * Backend returns 204 No Content; body may be undefined, null, or empty object.\n * Accepts only those; rejects any other shape to detect unexpected API responses.\n */\nexport function validateCrossDeviceVerifyResponse(data: unknown): Result<void, TryMellonError> {\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n if (isObject(data) && Object.keys(data).length === 0) {\n return ok(undefined);\n }\n return validationError('Invalid API response: expected empty body (204)', {\n originalData: data,\n });\n}\n\nfunction isCreationOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return (\n typeof o.challenge === 'string' &&\n o.rp != null &&\n typeof o.rp === 'object' &&\n o.user != null &&\n typeof o.user === 'object' &&\n Array.isArray((o as { pubKeyCredParams?: unknown }).pubKeyCredParams)\n );\n}\n\nfunction isRequestOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return typeof o.challenge === 'string' && typeof o.rpId === 'string';\n}\n\n/**\n * Accepts either the unwrapped payload { session_id, qr_url, expires_at } or the fintech\n * envelope { ok: true, resultado: { session_id, qr_url, expires_at } } so the flow works\n * regardless of whether the fetch-client unwraps before calling this validator.\n */\nexport function validateCrossDeviceInitResponse(\n data: unknown\n): Result<CrossDeviceInitResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const payload =\n 'resultado' in data && isObject((data as { resultado: unknown }).resultado)\n ? (data as { resultado: Record<string, unknown> }).resultado\n : data;\n\n const session_id = payload.session_id;\n const qr_url = payload.qr_url;\n const expires_at = payload.expires_at;\n const polling_token = payload.polling_token;\n\n if (\n !isString(session_id) ||\n !isString(qr_url) ||\n !isString(expires_at) ||\n !isString(polling_token)\n ) {\n return validationError('Invalid API response: missing required fields', { originalData: data });\n }\n\n const result: CrossDeviceInitResult = {\n session_id,\n qr_url,\n expires_at,\n polling_token,\n };\n if (payload.external_user_id !== undefined && isString(payload.external_user_id)) {\n result.external_user_id = payload.external_user_id;\n }\n return ok(result);\n}\n\n/**\n * Accepts either the unwrapped payload { status, user_id?, session_token?, redirect_url? } or the\n * fintech envelope { ok: true, resultado: { ... } } so the flow works regardless of unwrapping.\n */\nexport function validateCrossDeviceStatusResponse(\n data: unknown\n): Result<CrossDeviceStatusResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const payload =\n 'resultado' in data && isObject((data as { resultado: unknown }).resultado)\n ? (data as { resultado: Record<string, unknown> }).resultado\n : data;\n\n const status = payload.status;\n if (!isString(status) || !['pending', 'authenticated', 'completed'].includes(status)) {\n return validationError('Invalid API response: invalid status', { originalData: data });\n }\n\n const user_id = payload.user_id;\n const session_token = payload.session_token;\n const redirect_url = payload.redirect_url;\n\n if (user_id !== undefined && !isString(user_id)) {\n return validationError('Invalid API response: user_id must be a string when present', {\n originalData: data,\n });\n }\n if (session_token !== undefined && !isString(session_token)) {\n return validationError('Invalid API response: session_token must be a string when present', {\n originalData: data,\n });\n }\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be a string when present', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as CrossDeviceStatusResult['status'],\n user_id: user_id as string | undefined,\n session_token: session_token as string | undefined,\n redirect_url: redirect_url as string | undefined,\n });\n}\n\nexport function validateCrossDeviceContextResponse(\n data: unknown\n): Result<CrossDeviceContextResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const rawType = data.type;\n const type =\n rawType === 'registration' ? 'registration' : rawType === 'auth' ? 'auth' : ('auth' as const);\n\n const options = data.options;\n if (!isObject(options)) {\n return validationError('Invalid API response: options are required', { originalData: data });\n }\n\n const MAX_CONTEXT_LENGTH = 200;\n const approval_context = optionalContextString(data.approval_context, MAX_CONTEXT_LENGTH);\n const application_name = optionalContextString(data.application_name, MAX_CONTEXT_LENGTH);\n if (approval_context === false || application_name === false) {\n return validationError(\n 'Invalid API response: approval_context/application_name must be string max 200 chars',\n {\n originalData: data,\n }\n );\n }\n\n const extra: { approval_context?: string; application_name?: string } = {};\n if (typeof approval_context === 'string') extra.approval_context = approval_context;\n if (typeof application_name === 'string') extra.application_name = application_name;\n\n if (type === 'registration') {\n if (!isCreationOptionsShape(options)) {\n return validationError(\n 'Invalid API response: registration options must have challenge, rp, user, pubKeyCredParams',\n { originalData: data }\n );\n }\n return ok({\n type: 'registration',\n options,\n ...extra,\n } as CrossDeviceContextResult);\n }\n\n if (!isRequestOptionsShape(options)) {\n return validationError('Invalid API response: auth options must have challenge and rpId', {\n originalData: data,\n });\n }\n return ok({ type: 'auth', options, ...extra } as CrossDeviceContextResult);\n}\n\n/** Returns string if valid (optional, max len), undefined if missing, false if invalid. */\nfunction optionalContextString(value: unknown, maxLength: number): string | undefined | false {\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') return false;\n if (value.length > maxLength) return false;\n return value;\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { RecoveryVerifyResponse, RecoveryCompleteResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateRecoveryVerifyResponse(\n data: unknown\n): Result<RecoveryVerifyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const challenge = required(data, 'challenge');\n const recovery_session_id = required(data, 'recovery_session_id');\n\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n if (!isString(recovery_session_id)) {\n return validationError('Invalid API response: recovery_session_id must be string', {\n field: 'recovery_session_id',\n originalData: data,\n });\n }\n\n return ok({\n challenge: challenge as Record<string, unknown>,\n recovery_session_id,\n });\n}\n\nexport function validateRecoveryCompleteResponse(\n data: unknown\n): Result<RecoveryCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const credential_id = required(data, 'credential_id');\n\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const user_id = required(user, 'user_id');\n if (!isString(user_id)) {\n return validationError('Invalid API response: user.user_id must be string', {\n field: 'user.user_id',\n originalData: data,\n });\n }\n\n const dataObj = data as Record<string, unknown>;\n const redirect_url = dataObj.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n field: 'redirect_url',\n originalData: data,\n });\n }\n\n const userObj = user as Record<string, unknown>;\n return ok({\n status,\n session_token,\n credential_id,\n user: {\n user_id,\n external_user_id: isString(userObj.external_user_id) ? userObj.external_user_id : undefined,\n email: isString(userObj.email) ? userObj.email : undefined,\n metadata: isObject(userObj.metadata)\n ? (userObj.metadata as Record<string, unknown>)\n : undefined,\n },\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n","import type { HttpClient } from './http-client';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport {\n validateRegisterStartResponse,\n validateAuthStartResponse,\n validateRegisterFinishResponse,\n validateAuthFinishResponse,\n validateSessionValidateResponse,\n validateEmailVerifyResponse,\n validateOnboardingStartResponse,\n validateOnboardingStatusResponse,\n validateOnboardingRegisterResponse,\n validateOnboardingRegisterPasskeyResponse,\n validateOnboardingCompleteResponse,\n validateCrossDeviceInitResponse,\n validateCrossDeviceStatusResponse,\n validateCrossDeviceContextResponse,\n validateCrossDeviceVerifyResponse,\n validateRecoveryVerifyResponse,\n validateRecoveryCompleteResponse,\n} from './validators';\nimport type {\n RegisterStartRequest,\n RegisterStartResponse,\n AuthStartRequest,\n AuthStartResponse,\n RegisterFinishRequest,\n RegisterFinishResponse,\n AuthFinishRequest,\n AuthFinishResponse,\n SessionValidateResponse,\n OnboardingStartRequest,\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterPasskeyRequest,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteRequest,\n OnboardingCompleteResponse,\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n CrossDeviceVerifyRequest,\n CrossDeviceVerifyRegistrationRequest,\n RecoveryVerifyResponse,\n RecoveryCompleteResponse,\n} from '../types';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nexport class ApiClient {\n constructor(\n private readonly httpClient: HttpClient,\n private readonly baseUrl: string,\n private readonly defaultHeaders: Record<string, string> = {}\n ) {}\n\n private mergeHeaders(extra?: Record<string, string>): Record<string, string> {\n return { ...this.defaultHeaders, ...extra };\n }\n\n private async post<Req, Res>(\n path: string,\n body: Req,\n validate: (data: unknown) => Result<Res, TryMellonError>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.post<unknown>(url, body, this.mergeHeaders());\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n private async get<Res>(\n path: string,\n validate: (data: unknown) => Result<Res, TryMellonError>,\n headers?: Record<string, string>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.get<unknown>(url, this.mergeHeaders(headers));\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n async startRegister(\n request: RegisterStartRequest\n ): Promise<Result<RegisterStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/start', request, validateRegisterStartResponse);\n }\n\n async startAuth(request: AuthStartRequest): Promise<Result<AuthStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/start', request, validateAuthStartResponse);\n }\n\n async finishRegister(\n request: RegisterFinishRequest\n ): Promise<Result<RegisterFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/finish', request, validateRegisterFinishResponse);\n }\n\n async finishAuthentication(\n request: AuthFinishRequest\n ): Promise<Result<AuthFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/finish', request, validateAuthFinishResponse);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n return this.get('/v1/sessions/validate', validateSessionValidateResponse, {\n Authorization: `Bearer ${sessionToken}`,\n });\n }\n\n async startEmailFallback(options: {\n userId: string;\n email: string;\n }): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/fallback/email/start`;\n const result = await this.httpClient.post<unknown>(\n url,\n { userId: options.userId, email: options.email },\n this.mergeHeaders()\n );\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyEmailCode(options: {\n userId: string;\n code: string;\n successUrl?: string;\n }): Promise<Result<{ sessionToken: string; redirectUrl?: string }, TryMellonError>> {\n const body: Record<string, unknown> = { userId: options.userId, code: options.code };\n if (options.successUrl) body.success_url = options.successUrl;\n return this.post('/v1/fallback/email/verify', body, validateEmailVerifyResponse);\n }\n\n async startOnboarding(\n request: OnboardingStartRequest\n ): Promise<Result<OnboardingStartResponse, TryMellonError>> {\n return this.post('/v1/onboarding/start', request, validateOnboardingStartResponse);\n }\n\n async getOnboardingStatus(\n sessionId: string\n ): Promise<Result<OnboardingStatusResponse, TryMellonError>> {\n return this.get(`/v1/onboarding/${sessionId}/status`, validateOnboardingStatusResponse);\n }\n\n async getOnboardingRegister(\n sessionId: string\n ): Promise<Result<OnboardingRegisterResponseWithChallenge, TryMellonError>> {\n return this.get(`/v1/onboarding/${sessionId}/register`, validateOnboardingRegisterResponse);\n }\n\n async registerOnboardingPasskey(\n sessionId: string,\n request: OnboardingRegisterPasskeyRequest\n ): Promise<Result<OnboardingRegisterPasskeyResponse, TryMellonError>> {\n return this.post(\n `/v1/onboarding/${sessionId}/register-passkey`,\n request,\n validateOnboardingRegisterPasskeyResponse\n );\n }\n\n async completeOnboarding(\n sessionId: string,\n request: OnboardingCompleteRequest\n ): Promise<Result<OnboardingCompleteResponse, TryMellonError>> {\n return this.post(\n `/v1/onboarding/${sessionId}/complete`,\n request,\n validateOnboardingCompleteResponse\n );\n }\n\n async initCrossDeviceAuth(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post('/v1/auth/cross-device/init', {}, validateCrossDeviceInitResponse);\n }\n\n async initCrossDeviceRegistration(options?: {\n externalUserId?: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n const trimmed =\n typeof options?.externalUserId === 'string' ? options.externalUserId.trim() : '';\n const body = trimmed.length > 0 ? { external_user_id: trimmed } : {};\n return this.post(\n '/v1/auth/cross-device/init-registration',\n body,\n validateCrossDeviceInitResponse\n );\n }\n\n async getCrossDeviceStatus(\n sessionId: string,\n pollingToken?: string | null\n ): Promise<Result<CrossDeviceStatusResult, TryMellonError>> {\n const headers: Record<string, string> = {};\n if (typeof pollingToken === 'string' && pollingToken.length > 0) {\n headers['X-Polling-Token'] = pollingToken;\n }\n return this.get(\n `/v1/auth/cross-device/status/${sessionId}`,\n validateCrossDeviceStatusResponse,\n Object.keys(headers).length > 0 ? headers : undefined\n );\n }\n\n /**\n * Fetches WebAuthn options for the cross-device session.\n * Contract: response is CrossDeviceContextResult (auth | registration).\n * Use result.value.type to branch: 'auth' → credentials.get + verify;\n * 'registration' → credentials.create + verify-registration.\n */\n async getCrossDeviceContext(\n sessionId: string\n ): Promise<Result<CrossDeviceContextResult, TryMellonError>> {\n return this.get(\n `/v1/auth/cross-device/context/${sessionId}`,\n validateCrossDeviceContextResponse\n );\n }\n\n async verifyCrossDeviceAuth(\n request: CrossDeviceVerifyRequest\n ): Promise<Result<void, TryMellonError>> {\n return this.post('/v1/auth/cross-device/verify', request, validateCrossDeviceVerifyResponse);\n }\n\n async verifyCrossDeviceRegistration(\n request: CrossDeviceVerifyRegistrationRequest\n ): Promise<Result<void, TryMellonError>> {\n return this.post(\n '/v1/auth/cross-device/verify-registration',\n request,\n validateCrossDeviceVerifyResponse\n );\n }\n\n async verifyAccountRecoveryOtp(\n externalUserId: string,\n otp: string\n ): Promise<Result<RecoveryVerifyResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/verify',\n { external_id: externalUserId, otp },\n validateRecoveryVerifyResponse\n );\n }\n\n async completeAccountRecovery(\n recoverySessionId: string,\n credential: Record<string, unknown>\n ): Promise<Result<RecoveryCompleteResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/complete',\n { recovery_session_id: recoverySessionId, credential },\n validateRecoveryCompleteResponse\n );\n }\n}\n","import type { HttpClient } from './http-client';\nimport type { Logger } from './ports/logger';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport {\n createError,\n mapBackendErrorCodeToTryMellon,\n type TryMellonError,\n type TryMellonErrorCode,\n} from '../errors';\n\n/** Fintech success envelope: { ok: true, resultado: T } */\nfunction isEnvelopeSuccess(data: unknown): data is { ok: true; resultado: unknown } {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as Record<string, unknown>).ok === true &&\n 'resultado' in (data as Record<string, unknown>)\n );\n}\n\n/** Fintech error envelope: { ok: false, error: { code, message } } */\nfunction isEnvelopeError(\n data: unknown\n): data is { ok: false; error: { code: string; message: string; details?: unknown } } {\n if (typeof data !== 'object' || data === null) return false;\n const o = data as Record<string, unknown>;\n if (o.ok !== false || !o.error || typeof o.error !== 'object') return false;\n const err = o.error as Record<string, unknown>;\n return typeof err.code === 'string' && typeof err.message === 'string';\n}\n\n/**\n * Pure function: parses HTTP error body (fintech envelope or fallbacks) into message and code.\n * Concentrates all error-body parsing in one place for testability and single responsibility.\n */\nexport function parseHttpErrorBody(\n errorData: unknown,\n statusText: string\n): { message: string; code: TryMellonErrorCode } {\n if (isEnvelopeError(errorData)) {\n return {\n message: errorData.error.message,\n code: mapBackendErrorCodeToTryMellon(errorData.error.code),\n };\n }\n const body = errorData as\n | { message?: string; error?: string | { code?: string; message?: string } }\n | undefined;\n const errObj = body?.error;\n if (\n typeof errObj === 'object' &&\n errObj !== null &&\n 'code' in errObj &&\n typeof (errObj as { code: string }).code === 'string'\n ) {\n return {\n message: (errObj as { message?: string }).message ?? body?.message ?? statusText,\n code: mapBackendErrorCodeToTryMellon((errObj as { code: string }).code),\n };\n }\n const message = body?.message ?? statusText;\n const rawCode = body?.error;\n const code =\n typeof rawCode === 'string'\n ? mapBackendErrorCodeToTryMellon(rawCode)\n : rawCode === undefined\n ? 'NETWORK_FAILURE'\n : mapBackendErrorCodeToTryMellon(String(rawCode));\n return { message, code };\n}\n\nconst RETRY_DELAY_CAP_MS = 30_000;\n\n/**\n * Generates a unique request ID. Uses globalThis.crypto.randomUUID only (Elite: no Node crypto).\n * @throws Error when Web Crypto API is not available (Edge/browser must provide it).\n */\nfunction generateRequestId(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID();\n }\n throw new Error('Web Crypto API is required but not available.');\n}\n\n/**\n * Exponential backoff delay for a given attempt (0-based).\n * Cap at RETRY_DELAY_CAP_MS.\n */\nexport function getRetryDelayMs(attempt: number, baseMs: number): number {\n const delay = baseMs * Math.pow(2, attempt);\n return Math.min(delay, RETRY_DELAY_CAP_MS);\n}\n\nfunction shouldRetryOnStatus(method: string, status: number): boolean {\n if (method !== 'GET') return false;\n return status >= 500 || status === 429;\n}\n\nexport class FetchHttpClient implements HttpClient {\n constructor(\n private readonly timeoutMs: number,\n private readonly maxRetries: number = 0,\n private readonly retryDelayMs: number = 1000,\n private readonly logger?: Logger\n ) {}\n\n async get<T>(url: string, headers?: Record<string, string>): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, { method: 'GET', headers });\n }\n\n async post<T>(\n url: string,\n body: unknown,\n headers?: Record<string, string>\n ): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: { 'Content-Type': 'application/json', ...headers },\n });\n }\n\n private async request<T>(url: string, config: RequestInit): Promise<Result<T, TryMellonError>> {\n const method = (config.method ?? 'GET').toUpperCase();\n const requestId = generateRequestId();\n const headers = new Headers(config.headers as HeadersInit);\n headers.set('X-Request-Id', requestId);\n\n if (this.logger) {\n this.logger.debug('request', { requestId, url, method });\n }\n\n let lastError: TryMellonError | Error | unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...config,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorData: unknown;\n try {\n errorData = await response.json();\n } catch {\n // Ignore JSON parse error\n }\n\n const { message, code } = parseHttpErrorBody(errorData, response.statusText);\n const errResult = createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: errorData,\n });\n\n if (shouldRetryOnStatus(method, response.status) && attempt < this.maxRetries) {\n lastError = errResult;\n clearTimeout(timeoutId);\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n continue;\n }\n\n return err(errResult);\n }\n\n if (response.status === 204) {\n return ok(undefined as T);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n return ok(undefined as T);\n }\n const raw = (await response.json()) as unknown;\n if (isEnvelopeSuccess(raw)) {\n return ok((raw as { ok: true; resultado: T }).resultado);\n }\n const o = raw as Record<string, unknown>;\n if (typeof raw === 'object' && raw !== null && o.ok === true && !('resultado' in o)) {\n return ok(undefined as T);\n }\n if (isEnvelopeError(raw)) {\n const { message, code } = parseHttpErrorBody(raw, response.statusText);\n return err(\n createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: raw,\n })\n );\n }\n return ok(raw as T);\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n lastError = error;\n const isGet = method === 'GET';\n if (isGet && attempt < this.maxRetries) {\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n } else {\n break;\n }\n }\n }\n\n if (lastError instanceof Error && lastError.name === 'AbortError') {\n return err(createError('TIMEOUT', 'Request timed out', { requestId }));\n }\n\n return err(\n createError(\n 'NETWORK_FAILURE',\n lastError instanceof Error ? lastError.message : 'Request failed',\n { requestId, cause: lastError }\n )\n );\n }\n}\n","import { createEncodingError } from '../errors';\n\n/**\n * Encodes an ArrayBuffer to base64url using globalThis.btoa (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when btoa is unavailable\n */\nexport function base64UrlEncode(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join('');\n\n if (typeof globalThis.btoa === 'undefined') {\n throw createEncodingError('encode');\n }\n const base64 = globalThis.btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Decodes a base64url string to Uint8Array using globalThis.atob (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when atob is unavailable\n */\nexport function base64UrlDecode(s: string): Uint8Array {\n if (typeof globalThis.atob === 'undefined') {\n throw createEncodingError('decode');\n }\n\n const base64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const padding = base64.length % 4;\n const padded = padding === 0 ? base64 : base64 + '='.repeat(4 - padding);\n const binary = globalThis.atob(padded);\n\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n\n/** Decodes base64url to ArrayBuffer (delegates to base64UrlDecode). */\nexport function base64UrlDecodeToArrayBuffer(s: string): ArrayBuffer {\n const bytes = base64UrlDecode(s);\n const buffer = new ArrayBuffer(bytes.length);\n new Uint8Array(buffer).set(bytes);\n return buffer;\n}\n","import { createError } from '../errors';\nimport { base64UrlEncode } from '../utils/base64url';\nimport type { RegisterFinishRequest, AuthFinishRequest } from '../types';\n\ntype SerializedCredentialForRegister = RegisterFinishRequest['credential'];\ntype SerializedCredentialForAuth = AuthFinishRequest['credential'];\n\n/**\n * Type guard to verify whether a credential response is valid.\n */\nfunction isValidCredentialResponse(\n response: unknown\n): response is AuthenticatorAssertionResponse | AuthenticatorAttestationResponse {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'clientDataJSON' in response &&\n response.clientDataJSON instanceof ArrayBuffer\n );\n}\n\n/**\n * Serializes a credential for registration (finish).\n * Includes attestationObject required for registration verification.\n *\n * @param credential - WebAuthn credential from navigator.credentials.create()\n * @returns Serialized credential in Base64URL format\n * @throws {TryMellonError} If the credential does not have the expected structure for registration\n */\nexport function serializeCredentialForRegister(\n credential: PublicKeyCredential\n): SerializedCredentialForRegister {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('attestationObject' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for register: attestationObject is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const attestationObject = (response as AuthenticatorAttestationResponse).attestationObject;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n clientDataJSON: base64UrlEncode(clientDataJSON),\n attestationObject: base64UrlEncode(attestationObject),\n },\n type: 'public-key',\n };\n}\n\n/**\n * Serializes a credential for authentication (finish).\n * Includes authenticatorData, signature, and optionally userHandle.\n *\n * @param credential - WebAuthn credential from navigator.credentials.get()\n * @returns Serialized credential in Base64URL format\n * @throws {TryMellonError} If the credential does not have the expected structure for authentication\n */\nexport function serializeCredentialForAuth(\n credential: PublicKeyCredential\n): SerializedCredentialForAuth {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('authenticatorData' in response) || !('signature' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for auth: authenticatorData or signature is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const authenticatorData = (response as AuthenticatorAssertionResponse).authenticatorData;\n const signature = (response as AuthenticatorAssertionResponse).signature;\n const userHandle = (response as AuthenticatorAssertionResponse).userHandle;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n authenticatorData: base64UrlEncode(authenticatorData),\n clientDataJSON: base64UrlEncode(clientDataJSON),\n signature: base64UrlEncode(signature),\n ...(userHandle && { userHandle: base64UrlEncode(userHandle) }),\n },\n type: 'public-key',\n };\n}\n","import type { ClientStatus } from '../types';\n\nexport function isWebAuthnSupported(): boolean {\n try {\n if (typeof navigator === 'undefined' || !navigator.credentials) {\n return false;\n }\n\n if (typeof PublicKeyCredential === 'undefined') {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n try {\n if (!isWebAuthnSupported()) {\n return false;\n }\n\n if (typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable !== 'function') {\n return false;\n }\n\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\nexport async function getClientStatus(): Promise<ClientStatus> {\n const isPasskeySupported = isWebAuthnSupported();\n const platformAuthenticatorAvailable = await isPlatformAuthenticatorAvailable();\n\n return {\n isPasskeySupported,\n platformAuthenticatorAvailable,\n recommendedFlow: isPasskeySupported ? 'passkey' : 'fallback',\n };\n}\n","import { createCredentialError } from '../errors';\n\nexport function validateCredentialStructure(\n credential: unknown,\n operation: 'create' | 'get' = 'create'\n): asserts credential is PublicKeyCredential {\n if (\n !credential ||\n typeof credential !== 'object' ||\n !('id' in credential) ||\n !('rawId' in credential) ||\n !('response' in credential)\n ) {\n throw createCredentialError(operation);\n }\n}\n","import type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { isWebAuthnSupported } from '../utils/support';\nimport type { EventEmitter } from './events';\nimport type { TryMellonError } from '../errors';\nimport { mapWebAuthnError, createNotSupportedError, createInvalidArgumentError } from '../errors';\nimport { validateCredentialStructure } from '../utils/validation';\n\nexport type CeremonyOperation = 'register' | 'authenticate';\n\nexport interface InvokeCeremonyContext<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n> {\n operation: CeremonyOperation;\n eventEmitter: EventEmitter;\n start: () => Promise<Result<TStartResult, TryMellonError>>;\n createOptions: (startResult: TStartResult) => Result<TCeremonyOptions, TryMellonError>;\n invoke: (options: TCeremonyOptions) => Promise<Credential | null>;\n finish: (\n startResult: TStartResult,\n credential: PublicKeyCredential\n ) => Promise<Result<TFinishResult, TryMellonError>>;\n}\n\n/**\n * Orchestrates a generic WebAuthn flow (Ceremony) to remove duplicated code in the SDK.\n * Encapsulates start call, options creation, browser credentials API invocation,\n * base structure validation, and finish call.\n */\nexport async function invokeCeremony<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n>(\n context: InvokeCeremonyContext<TStartResult, TFinishResult, TCeremonyOptions>\n): Promise<Result<TFinishResult, TryMellonError>> {\n const { operation, eventEmitter, start, createOptions, invoke, finish } = context;\n\n try {\n eventEmitter.emit('start', { type: 'start', operation });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 1. Obtener challenge del servidor\n const startResult = await start();\n if (!startResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: startResult.error });\n return err(startResult.error);\n }\n\n // 2. Create options\n const optionsResult = createOptions(startResult.value);\n if (!optionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: optionsResult.error });\n return err(optionsResult.error);\n }\n\n // 3. Invoke browser\n const credential = (await invoke(optionsResult.value)) as PublicKeyCredential;\n if (!credential) {\n const error = createInvalidArgumentError(\n 'credential',\n `${operation === 'register' ? 'creation' : 'retrieval'} failed`\n );\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Completar en servidor (success lo emite el caller con token/user; 03-eventos-seguridad)\n const finishResult = await finish(startResult.value, credential);\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n return ok(finishResult.value);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n","import { createInvalidArgumentError, validateBase64Url, mapWebAuthnError } from '../errors';\nimport { base64UrlDecodeToArrayBuffer } from '../utils/base64url';\nimport type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n RegisterStartResponse,\n AuthStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Creates credential creation options for WebAuthn.\n * Converts server response to WebAuthn API format.\n * WebAuthn protocol: challenge and rp.id are taken from the server only; do not override.\n * Exported for use by OnboardingManager (same-device) and CrossDeviceManager (QR registration).\n *\n * @param serverChallengePayload - Value of the `.challenge` property from RegisterStartResponse\n * (the nested object with challenge, user, rp, pubKeyCredParams, etc.). Not the full API response.\n */\nexport function createRegistrationOptions(\n serverChallengePayload: RegisterStartResponse['challenge'],\n authenticatorType?: 'platform' | 'cross-platform'\n): Result<CredentialCreationOptions, TryMellonError> {\n try {\n validateBase64Url(serverChallengePayload.challenge, 'challenge');\n validateBase64Url(serverChallengePayload.user.id, 'user.id');\n\n const challengeBuffer = base64UrlDecodeToArrayBuffer(serverChallengePayload.challenge);\n const userIdBuffer = base64UrlDecodeToArrayBuffer(serverChallengePayload.user.id);\n\n // Construir authenticatorSelection: priorizar servidor, permitir override de authenticatorType\n let authenticatorSelection: AuthenticatorSelectionCriteria = {\n userVerification: 'preferred',\n };\n\n if (serverChallengePayload.authenticatorSelection) {\n // Usar valores del servidor como base\n authenticatorSelection = {\n ...serverChallengePayload.authenticatorSelection,\n };\n }\n\n // Si el usuario especifica authenticatorType, sobrescribir authenticatorAttachment\n if (authenticatorType) {\n authenticatorSelection = {\n ...authenticatorSelection,\n authenticatorAttachment: authenticatorType,\n };\n }\n\n const publicKey: PublicKeyCredentialCreationOptions = {\n rp: {\n id: serverChallengePayload.rp.id,\n name: serverChallengePayload.rp.name,\n },\n user: {\n id: userIdBuffer,\n name: serverChallengePayload.user.name,\n displayName: serverChallengePayload.user.displayName,\n },\n challenge: challengeBuffer,\n pubKeyCredParams: serverChallengePayload.pubKeyCredParams,\n ...(serverChallengePayload.timeout !== undefined && {\n timeout: serverChallengePayload.timeout,\n }),\n attestation: 'none',\n authenticatorSelection,\n ...(serverChallengePayload.excludeCredentials && {\n excludeCredentials: serverChallengePayload.excludeCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n };\n\n return ok({ publicKey });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Creates authentication options for WebAuthn.\n * Converts server response to WebAuthn API format.\n * WebAuthn protocol: challenge and rpId are taken from the server only; do not override.\n */\nexport function createAuthenticationOptions(\n challenge: AuthStartResponse['challenge'],\n mediation?: AuthenticateOptions['mediation']\n): Result<CredentialRequestOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n\n return ok({\n publicKey: {\n challenge: challengeBuffer,\n rpId: challenge.rpId,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n userVerification: challenge.userVerification ?? 'preferred',\n ...(challenge.allowCredentials && {\n allowCredentials: challenge.allowCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n },\n ...(mediation !== undefined && { mediation }),\n });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Registers a new passkey for a user.\n * Handles the full WebAuthn registration flow.\n */\nexport async function registerPasskey(\n options: RegisterOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RegisterResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const result = await invokeCeremony<\n RegisterStartResponse,\n RegisterResult,\n CredentialCreationOptions\n >({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.startRegister({ external_user_id: extId }),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge, options.authenticatorType),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.create(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishRegister({\n session_id: startResult.session_id,\n credential: serializeCredentialForRegister(credential),\n ...(options.successUrl && { success_url: options.successUrl }),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n success: true,\n credentialId: finishResult.value.credential_id,\n credential_id: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n ...(finishResult.value.redirect_url && { redirectUrl: finishResult.value.redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n\n/**\n * Authenticates a user with their passkey.\n * Handles the full WebAuthn authentication flow.\n */\nexport async function authenticatePasskey(\n options: AuthenticateOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<AuthenticateResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n const hasUserId = extId !== undefined && typeof extId === 'string' && extId.trim() !== '';\n\n const result = await invokeCeremony<\n AuthStartResponse,\n AuthenticateResult,\n CredentialRequestOptions\n >({\n operation: 'authenticate',\n eventEmitter,\n start: () =>\n apiClient.startAuth(hasUserId ? { external_user_id: (extId as string).trim() } : {}),\n createOptions: (startResult) =>\n createAuthenticationOptions(startResult.challenge, options.mediation),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.get(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishAuthentication({\n session_id: startResult.session_id,\n credential: serializeCredentialForAuth(credential),\n ...(options.successUrl && { success_url: options.successUrl }),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n authenticated: finishResult.value.authenticated,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n signals: finishResult.value.signals,\n ...(finishResult.value.redirect_url && { redirectUrl: finishResult.value.redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'authenticate',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n","export async function waitWithAbort(\n intervalMs: number,\n signal?: AbortSignal\n): Promise<'aborted' | 'completed'> {\n // Fast path when no signal is provided: simple sleep.\n if (!signal) {\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n return 'completed';\n }\n\n if (signal.aborted) {\n return 'aborted';\n }\n\n return new Promise<'aborted' | 'completed'>((resolve) => {\n const onAbort = () => {\n cleanup();\n resolve('aborted');\n };\n\n const cleanup = () => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n };\n\n const timeout = setTimeout(() => {\n cleanup();\n resolve('completed');\n }, intervalMs);\n\n signal.addEventListener('abort', onAbort);\n });\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type { OnboardingStartOptions, OnboardingCompleteResult } from '../types';\nimport { createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\nimport { waitWithAbort } from './polling-utils';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class OnboardingManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Executes the full onboarding flow in a single call.\n * 1. Starts onboarding\n * 2. Polls for 'pending_passkey' or 'completed' status\n * 3. If pending_passkey: when API returns challenge, registers passkey (WebAuthn) then completes onboarding\n * 4. If pending_passkey but API does not return challenge: returns NOT_SUPPORTED with onboarding_url for user to complete elsewhere\n */\n async startFlow(\n options: OnboardingStartOptions & { company_name?: string },\n signal?: AbortSignal\n ): Promise<Result<OnboardingCompleteResult, TryMellonError>> {\n const startResult = await this.apiClient.startOnboarding({ user_role: options.user_role });\n if (!startResult.ok) return err(startResult.error);\n\n const { session_id } = startResult.value;\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const waitResult = await waitWithAbort(POLL_INTERVAL_MS, signal);\n if (waitResult === 'aborted') {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const statusResult = await this.apiClient.getOnboardingStatus(session_id);\n if (!statusResult.ok) return err(statusResult.error);\n\n const status = statusResult.value.status;\n const onboarding_url = statusResult.value.onboarding_url;\n\n if (status === 'pending_passkey') {\n const registerInfoResult = await this.apiClient.getOnboardingRegister(session_id);\n if (!registerInfoResult.ok) return err(registerInfoResult.error);\n\n const registerInfo = registerInfoResult.value as OnboardingRegisterResponseWithChallenge;\n\n if (!registerInfo.challenge) {\n return err(\n createError(\n 'NOT_SUPPORTED',\n 'Onboarding requires user action - complete passkey registration at the provided onboarding_url',\n { onboarding_url }\n )\n );\n }\n\n const creationOptionsResult = createRegistrationOptions(registerInfo.challenge);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n const registerPasskeyResult = await this.apiClient.registerOnboardingPasskey(session_id, {\n credential: serializedCredential,\n challenge: registerInfo.challenge.challenge,\n });\n if (!registerPasskeyResult.ok) return err(registerPasskeyResult.error);\n\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n\n if (status === 'completed') {\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n }\n\n return err(createError('TIMEOUT', 'Onboarding timed out'));\n }\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceContextAuth,\n CrossDeviceContextRegistration,\n} from '../types';\nimport { createAuthenticationOptions, createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport { waitWithAbort } from './polling-utils';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class CrossDeviceManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Initializes a cross-device authentication session.\n * Typically called by the desktop side to get a QR code URL.\n */\n async init(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceAuth();\n }\n\n /**\n * Initializes a cross-device registration session (create account via QR).\n * Typically called by the desktop side to get a QR code URL for new users.\n * Pass externalUserId for known users; omit for anonymous registration.\n */\n async initRegistration(options?: {\n externalUserId?: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceRegistration(options);\n }\n\n /**\n * High-level helper to poll for session status until it is completed.\n * Typically called by the desktop side after showing the QR code.\n * Pass pollingToken from init() result so the backend can verify the poller is the initiator.\n */\n async waitForSession(\n sessionId: string,\n signal?: AbortSignal,\n pollingToken?: string | null\n ): Promise<\n Result<{ session_token: string; user_id: string; redirectUrl?: string }, TryMellonError>\n > {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n const statusResult = await this.apiClient.getCrossDeviceStatus(sessionId, pollingToken);\n if (!statusResult.ok) return err(statusResult.error);\n\n if (statusResult.value.status === 'completed') {\n if (!statusResult.value.session_token || !statusResult.value.user_id) {\n return err(createError('UNKNOWN_ERROR', 'Missing data in completed session'));\n }\n const redirectUrl =\n statusResult.value.redirect_url != null && statusResult.value.redirect_url !== ''\n ? statusResult.value.redirect_url\n : undefined;\n return ok({\n session_token: statusResult.value.session_token,\n user_id: statusResult.value.user_id,\n ...(redirectUrl !== undefined && { redirectUrl }),\n });\n }\n\n const waitResult = await waitWithAbort(POLL_INTERVAL_MS, signal);\n if (waitResult === 'aborted') {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n }\n\n return err(createError('TIMEOUT', 'Cross-device authentication timed out'));\n }\n\n /**\n * Approves a cross-device session.\n * Typically called by the mobile side after scanning a QR code.\n * Branches by context type: registration → credentials.create + verify-registration;\n * auth → credentials.get + verify.\n */\n async approve(sessionId: string): Promise<Result<void, TryMellonError>> {\n const contextResult = await this.apiClient.getCrossDeviceContext(sessionId);\n if (!contextResult.ok) return err(contextResult.error);\n\n const context = contextResult.value;\n\n if (context.type === 'registration') {\n return this.executeRegistrationApproval(sessionId, context);\n }\n return this.executeAuthApproval(sessionId, context);\n }\n\n /**\n * Executes the registration branch: create credential and verify-registration.\n */\n private async executeRegistrationApproval(\n sessionId: string,\n context: CrossDeviceContextRegistration\n ): Promise<Result<void, TryMellonError>> {\n const creationOptionsResult = createRegistrationOptions(context.options);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceRegistration({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n\n /**\n * Executes the auth branch: get credential and verify.\n */\n private async executeAuthApproval(\n sessionId: string,\n context: CrossDeviceContextAuth\n ): Promise<Result<void, TryMellonError>> {\n const requestOptionsResult = createAuthenticationOptions(context.options);\n if (!requestOptionsResult.ok) return err(requestOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.get(requestOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'get');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForAuth(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceAuth({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n}\n","import type { EventHandler, EventPayload, TryMellonEvent } from '../types';\n\nexport class EventEmitter {\n private handlers: Map<TryMellonEvent, Set<EventHandler>>;\n\n constructor() {\n this.handlers = new Map();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n let handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n handlersSet = new Set();\n this.handlers.set(event, handlersSet);\n }\n\n handlersSet.add(handler);\n\n return () => {\n this.off(event, handler);\n };\n }\n\n off(event: TryMellonEvent, handler: EventHandler): void {\n const handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n return;\n }\n handlersSet.delete(handler);\n if (handlersSet.size === 0) {\n this.handlers.delete(event);\n }\n }\n\n emit(event: TryMellonEvent, payload: EventPayload): void {\n const handlersSet = this.handlers.get(event);\n if (handlersSet) {\n for (const handler of handlersSet) {\n try {\n handler(payload);\n } catch {\n // Silently ignore handler errors to prevent one handler from breaking others\n // Handler errors are the responsibility of the handler implementation\n }\n }\n }\n }\n\n removeAllListeners(): void {\n this.handlers.clear();\n }\n}\n","export const COSE_ALGORITHM_ES256 = -7;\nexport const COSE_ALGORITHM_RS256 = -257;\n\nexport const DEFAULT_API_BASE_URL = 'https://api.trymellonauth.com';\nexport const DEFAULT_TELEMETRY_ENDPOINT = 'https://api.trymellonauth.com/v1/telemetry';\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\nexport const MIN_TIMEOUT_MS = 1000;\nexport const MAX_TIMEOUT_MS = 300000;\nexport const MIN_MAX_RETRIES = 0;\nexport const MAX_MAX_RETRIES = 10;\nexport const MIN_RETRY_DELAY_MS = 100;\nexport const MAX_RETRY_DELAY_MS = 10000;\n\n/**\n * Fixed session token returned by register() and authenticate() when sandbox mode is enabled.\n * Backends MUST NOT accept this token in production; only in development for testing the integration flow.\n */\nexport const SANDBOX_SESSION_TOKEN = 'trymellon_sandbox_session_token_v1';\n","import type { TelemetrySender, TelemetryPayload } from '../ports/telemetry';\n\n/**\n * Default telemetry sender: sends payload via sendBeacon (or fetch) to the given endpoint.\n * No retries; fire-and-forget.\n */\nexport function createDefaultTelemetrySender(endpoint: string): TelemetrySender {\n return {\n async send(payload: TelemetryPayload): Promise<void> {\n const body = JSON.stringify(payload);\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n navigator.sendBeacon(endpoint, body);\n return;\n }\n if (typeof fetch !== 'undefined') {\n await fetch(endpoint, {\n method: 'POST',\n body,\n headers: { 'Content-Type': 'application/json' },\n keepalive: true,\n });\n }\n },\n };\n}\n","export type TelemetryEvent = 'register' | 'authenticate';\n\nexport type TelemetryPayload = {\n event: TelemetryEvent;\n latencyMs: number;\n ok: true;\n};\n\nexport interface TelemetrySender {\n send(payload: TelemetryPayload): Promise<void>;\n}\n\n/**\n * Builds the minimal telemetry payload (no PII).\n */\nexport function buildTelemetryPayload(event: TelemetryEvent, latencyMs: number): TelemetryPayload {\n return { event, latencyMs, ok: true };\n}\n","import type { ApiClient } from '../api';\nimport type { EventEmitter } from '../events';\nimport type {\n AuthenticateOptions,\n AuthenticateResult,\n RegisterOptions,\n RegisterResult,\n} from '../../types';\nimport type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { buildTelemetryPayload, type TelemetrySender } from '../ports/telemetry';\nimport { registerPasskey, authenticatePasskey } from '../webauthn';\n\ntype AuthOperation = 'register' | 'authenticate';\n\ntype AuthOptions = RegisterOptions | AuthenticateOptions;\n\nexport class AuthService {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly eventEmitter: EventEmitter,\n private readonly sandbox: boolean,\n private readonly sandboxToken: string,\n private readonly telemetrySender?: TelemetrySender\n ) {}\n\n private async sandboxAuthResult(\n operation: AuthOperation,\n options: AuthOptions\n ): Promise<Result<RegisterResult | AuthenticateResult, TryMellonError>> {\n const externalUserId =\n 'externalUserId' in options\n ? (options.externalUserId ?? options.external_user_id ?? 'sandbox')\n : (options.external_user_id ?? options.externalUserId ?? 'sandbox');\n const externalId = typeof externalUserId === 'string' ? externalUserId : 'sandbox';\n\n if (operation === 'register') {\n return Promise.resolve(\n ok({\n success: true,\n credentialId: '',\n status: 'sandbox',\n sessionToken: this.sandboxToken,\n user: { userId: 'sandbox-user', externalUserId: externalId },\n })\n );\n }\n\n return Promise.resolve(\n ok({\n authenticated: true,\n sessionToken: this.sandboxToken,\n user: { userId: 'sandbox-user', externalUserId: externalId },\n })\n );\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n if (this.sandbox) {\n const result = await this.sandboxAuthResult('register', options);\n if (result.ok) {\n this.eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result as Result<RegisterResult, TryMellonError>;\n }\n\n const start = Date.now();\n const result = await registerPasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('register', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n if (this.sandbox) {\n const result = await this.sandboxAuthResult('authenticate', options);\n if (result.ok) {\n this.eventEmitter.emit('success', {\n type: 'success',\n operation: 'authenticate',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result as Result<AuthenticateResult, TryMellonError>;\n }\n\n const start = Date.now();\n const result = await authenticatePasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('authenticate', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n}\n","import type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RecoverAccountOptions,\n RecoverAccountResult,\n RecoveryVerifyResponse,\n RegisterStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { createInvalidArgumentError } from '../errors';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { createRegistrationOptions } from './webauthn';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Recovers an account using an email OTP and creates a new passkey credential.\n * Manages the complete orchestrated WebAuthn registration flow for recovery.\n */\nexport async function recoverAccount(\n options: RecoverAccountOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RecoverAccountResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n if (!options.otp || typeof options.otp !== 'string' || options.otp.trim().length !== 6) {\n const error = createInvalidArgumentError('otp', 'must be a 6-digit string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const result = await invokeCeremony<\n RecoveryVerifyResponse,\n RecoverAccountResult,\n CredentialCreationOptions\n >({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.verifyAccountRecoveryOtp(extId, options.otp),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge as RegisterStartResponse['challenge']),\n invoke: async (ceremonyOptions) => navigator.credentials.create(ceremonyOptions),\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.completeAccountRecovery(\n startResult.recovery_session_id,\n serializeCredentialForRegister(credential)\n );\n\n if (!finishResult.ok) return err(finishResult.error);\n\n const {\n credential_id,\n status,\n session_token,\n user: userPayload,\n redirect_url,\n } = finishResult.value;\n return ok({\n success: true,\n credentialId: credential_id,\n status,\n sessionToken: session_token,\n user: {\n userId: userPayload.user_id,\n externalUserId: userPayload.external_user_id,\n email: userPayload.email,\n metadata: userPayload.metadata,\n },\n ...(redirect_url !== undefined && { redirectUrl: redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n","import type { ApiClient } from '../api';\nimport type { EventEmitter } from '../events';\nimport type { RecoverAccountOptions, RecoverAccountResult } from '../../types';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { recoverAccount } from '../recover';\n\nexport class RecoveryService {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly eventEmitter: EventEmitter\n ) {}\n\n recover(options: RecoverAccountOptions): Promise<Result<RecoverAccountResult, TryMellonError>> {\n return recoverAccount(options, this.apiClient, this.eventEmitter);\n }\n}\n","import { ApiClient } from './api';\nimport { FetchHttpClient } from './fetch-client';\nimport { OnboardingManager } from './onboarding-manager';\nimport { CrossDeviceManager } from './cross-device-manager';\nimport { EventEmitter } from './events';\nimport { isWebAuthnSupported, getClientStatus } from '../utils/support';\nimport { validateUrl, validateRange, createInvalidArgumentError } from '../errors';\nimport {\n DEFAULT_API_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_RETRY_DELAY_MS,\n DEFAULT_TELEMETRY_ENDPOINT,\n MIN_TIMEOUT_MS,\n MAX_TIMEOUT_MS,\n MIN_MAX_RETRIES,\n MAX_MAX_RETRIES,\n MIN_RETRY_DELAY_MS,\n MAX_RETRY_DELAY_MS,\n SANDBOX_SESSION_TOKEN,\n} from './constants';\nimport { createDefaultTelemetrySender } from './adapters/telemetry-sender';\nimport type { TelemetrySender } from './ports/telemetry';\nimport type {\n TryMellonConfig,\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n ClientStatus,\n TryMellonEvent,\n EventHandler,\n EmailFallbackStartOptions,\n EmailFallbackVerifyOptions,\n EmailFallbackVerifyResult,\n SessionValidateResponse,\n RecoverAccountOptions,\n} from '../types';\nimport { ok, err, type Result } from '../utils/result';\nimport { type TryMellonError, isTryMellonError } from '../errors';\nimport { AuthService } from './services/auth-service';\nimport { RecoveryService } from './services/recovery-service';\n\ndeclare const __VERSION__: string;\n\nexport class TryMellon {\n private readonly sandbox: boolean;\n private readonly sandboxToken: string;\n private apiClient: ApiClient;\n private eventEmitter: EventEmitter;\n private telemetrySender: TelemetrySender | undefined;\n private crossDeviceManager: CrossDeviceManager;\n private authService: AuthService;\n private recoveryService: RecoveryService;\n public onboarding: OnboardingManager;\n\n /**\n * Creates a new TryMellon instance.\n * Validates config and returns a Result.\n * @param config SDK configuration\n */\n static create(config: TryMellonConfig): Result<TryMellon, TryMellonError> {\n try {\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n return err(createInvalidArgumentError('appId', 'must be a non-empty string'));\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n return err(createInvalidArgumentError('publishableKey', 'must be a non-empty string'));\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n // Safe to instantiate now\n return ok(new TryMellon(config));\n } catch (e) {\n if (isTryMellonError(e)) {\n return err(e);\n }\n return err(createInvalidArgumentError('config', (e as Error).message));\n }\n }\n\n /**\n * @deprecated Use `TryMellon.create(config)` instead to handle validation errors safely.\n * This constructor will throw errors if configuration is invalid.\n */\n constructor(config: TryMellonConfig) {\n this.sandbox = config.sandbox === true;\n this.sandboxToken =\n this.sandbox && config.sandboxToken != null && config.sandboxToken !== ''\n ? config.sandboxToken\n : SANDBOX_SESSION_TOKEN;\n\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n // Legacy validation for direct constructor usage (still throws to maintain behavior for legacy code,\n // but create() handles this safely before calling constructor)\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n throw createInvalidArgumentError('appId', 'must be a non-empty string');\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n throw createInvalidArgumentError('publishableKey', 'must be a non-empty string');\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n // validateUrl throws, which is expected for the constructor. create() catches it.\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const httpClient = new FetchHttpClient(timeoutMs, maxRetries, retryDelayMs, config.logger);\n\n const originHeader =\n config.origin ??\n (typeof window !== 'undefined' && window?.location?.origin\n ? window.location.origin\n : undefined);\n\n const defaultHeaders: Record<string, string> = {\n 'X-App-Id': appId.trim(),\n Authorization: `Bearer ${publishableKey.trim()}`,\n ...(originHeader && { Origin: originHeader }),\n };\n\n this.apiClient = new ApiClient(httpClient, apiBaseUrl, defaultHeaders);\n this.eventEmitter = new EventEmitter();\n\n if (config.enableTelemetry) {\n this.telemetrySender =\n config.telemetrySender ??\n createDefaultTelemetrySender(config.telemetryEndpoint ?? DEFAULT_TELEMETRY_ENDPOINT);\n }\n\n this.authService = new AuthService(\n this.apiClient,\n this.eventEmitter,\n this.sandbox,\n this.sandboxToken,\n this.telemetrySender\n );\n this.recoveryService = new RecoveryService(this.apiClient, this.eventEmitter);\n this.onboarding = new OnboardingManager(this.apiClient);\n this.crossDeviceManager = new CrossDeviceManager(this.apiClient);\n }\n\n static isSupported(): boolean {\n return isWebAuthnSupported();\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n return this.authService.register(options);\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n return this.authService.authenticate(options);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n if (this.sandbox && sessionToken === this.sandboxToken) {\n return Promise.resolve(\n ok({\n valid: true,\n user_id: 'sandbox-user',\n external_user_id: 'sandbox',\n tenant_id: 'sandbox-tenant',\n app_id: 'sandbox-app',\n })\n );\n }\n return this.apiClient.validateSession(sessionToken);\n }\n\n async getStatus(): Promise<ClientStatus> {\n return getClientStatus();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n return this.eventEmitter.on(event, handler);\n }\n\n version(): string {\n return typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0';\n }\n\n fallback = {\n email: {\n start: async (options: EmailFallbackStartOptions): Promise<Result<void, TryMellonError>> => {\n return this.apiClient.startEmailFallback(options);\n },\n verify: async (\n options: EmailFallbackVerifyOptions\n ): Promise<Result<EmailFallbackVerifyResult, TryMellonError>> => {\n const result = await this.apiClient.verifyEmailCode({\n userId: options.userId,\n code: options.code,\n ...(options.successUrl && { successUrl: options.successUrl }),\n });\n if (!result.ok) return result;\n return ok({\n sessionToken: result.value.sessionToken,\n ...(result.value.redirectUrl && { redirectUrl: result.value.redirectUrl }),\n });\n },\n },\n };\n\n auth = {\n crossDevice: {\n init: () => this.crossDeviceManager.init(),\n initRegistration: (options?: { externalUserId?: string }) =>\n this.crossDeviceManager.initRegistration(options ?? {}),\n waitForSession: (sessionId: string, signal?: AbortSignal, pollingToken?: string | null) =>\n this.crossDeviceManager.waitForSession(sessionId, signal, pollingToken),\n getContext: (sessionId: string) => this.apiClient.getCrossDeviceContext(sessionId),\n approve: (sessionId: string) => this.crossDeviceManager.approve(sessionId),\n },\n recoverAccount: (options: RecoverAccountOptions) => this.recoveryService.recover(options),\n };\n}\n","/**\n * Adapter/factory to create and validate core instances for UI. Infrastructure: may import real TryMellon.\n */\nimport { TryMellon } from '../../../core/trymellon';\nimport type { CoreAuthPort, CoreAuthOptions } from '../../ports';\n\nexport interface CoreConfig {\n appId: string;\n publishableKey: string;\n}\n\n/** Creates core instance for UI using minimal CoreAuthPort. Returns null on failure; Presentation decides. */\nexport function createCoreForUI(config: CoreConfig): CoreAuthPort | null {\n const result = TryMellon.create({\n appId: config.appId,\n publishableKey: config.publishableKey,\n });\n\n if (!result.ok || result.value == null) {\n return null;\n }\n\n return result.value as CoreAuthPort;\n}\n\n/** Runtime guard: injected instance satisfies CoreAuthPort. Keeps WCs decoupled from concrete TryMellon. */\nexport function isCoreAuthPort(candidate: unknown): candidate is CoreAuthPort {\n if (candidate == null || typeof candidate !== 'object') return false;\n\n const maybe = candidate as Record<string, unknown>;\n\n const hasAuthenticate = typeof maybe.authenticate === 'function';\n const hasRegister = typeof maybe.register === 'function';\n const hasOn = typeof maybe.on === 'function';\n\n return hasAuthenticate && hasRegister && hasOn;\n}\n\n/** Normalizes Presentation options to CoreAuthOptions. Forwards externalUserId when present. */\nexport function toCoreAuthOptions(externalUserId: string | null): CoreAuthOptions {\n return externalUserId ? { externalUserId } : {};\n}\n","/**\n * Centralized constants for the infra layer (event bridge).\n * CustomEvent names for core → host communication.\n */\n\n/** Event name when modal opens (WC lifecycle). */\nexport const MELLON_OPEN = 'mellon:open';\n\n/** Event name when button/host requests modal open. bubbles: true, composed: true; detail empty or minimal. */\nexport const MELLON_OPEN_REQUEST = 'mellon:open-request';\n\n/** Event name when modal closes (WC lifecycle). */\nexport const MELLON_CLOSE = 'mellon:close';\n\n/** Event name when auth completes (core → host). bubbles: false, composed: true; listener on WC element. */\nexport const MELLON_SUCCESS = 'mellon:success';\n\n/** Event name when auth fails (core → host). bubbles: true, composed: true. */\nexport const MELLON_ERROR = 'mellon:error';\n\n/** Event name when ceremony starts (core → host). */\nexport const MELLON_START = 'mellon:start';\n\n/** Event name when ceremony is cancelled (host close or reset from AUTHENTICATING). bubbles: true, composed: true. */\nexport const MELLON_CANCELLED = 'mellon:cancelled';\n\n/** Fired on fallback UI click inside WC (no external navigation). */\nexport const MELLON_FALLBACK = 'mellon:fallback';\n\n/** Event name when tab changes (register ↔ login) in the modal. */\nexport const MELLON_TAB_CHANGE = 'mellon:tab-change';\n","/**\n * Event bridge: Core EventEmitter → DOM CustomEvents on the WC host element.\n * Token only in mellon:success; bubbles:false, composed:true. At most once success per ceremony; no error after success.\n * Payload as unknown; narrow with type guards to port types. P1-B: nonce in detail when present; no public API to dispatch success with arbitrary detail.\n * Constants: infra/constants.ts.\n */\nimport type {\n AuthOperation,\n CoreCancelledPayload,\n CoreErrorPayload,\n CoreEventsPort,\n CoreStartPayload,\n CoreSuccessPayload,\n CoreWithEvents,\n MellonErrorDetail,\n MellonOperationDetail,\n MellonSuccessDetail,\n MellonSuccessUserInfo,\n} from '../../ports/core-events.port';\nimport {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n} from './constants';\n\nexport {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n};\n\nexport type {\n AuthOperation,\n CoreWithEvents,\n MellonErrorDetail,\n MellonOperationDetail,\n MellonSuccessDetail,\n} from '../../ports/core-events.port';\n\nfunction dispatchCustomEvent<T>(\n host: HTMLElement,\n name: string,\n detail: T,\n options: { bubbles: boolean; composed: boolean }\n): void {\n host.dispatchEvent(\n new CustomEvent(name, {\n detail,\n bubbles: options.bubbles,\n composed: options.composed,\n })\n );\n}\n\n/** Map core operation to public contract ('login' | 'register'). */\nfunction toPublicOperation(op: 'register' | 'authenticate'): AuthOperation {\n return op === 'authenticate' ? 'login' : 'register';\n}\n\n/**\n * Maps raw core success payload user to MellonSuccessUserInfo. Returns undefined if payload\n * does not expose user or does not have at least a non-empty userId (no inventar forma).\n */\nfunction mapSuccessUser(raw: unknown): MellonSuccessUserInfo | undefined {\n if (raw == null || typeof raw !== 'object') return undefined;\n const o = raw as Record<string, unknown>;\n const userId = o.userId;\n if (typeof userId !== 'string' || userId.length === 0) return undefined;\n const result: MellonSuccessUserInfo = { userId };\n if (typeof o.externalUserId === 'string') result.externalUserId = o.externalUserId;\n if (typeof o.email === 'string') result.email = o.email;\n if (o.metadata != null && typeof o.metadata === 'object' && !Array.isArray(o.metadata)) {\n result.metadata = o.metadata as Record<string, unknown>;\n }\n return result;\n}\n\nfunction isCoreStartPayload(raw: unknown): raw is CoreStartPayload {\n return (\n raw != null &&\n typeof raw === 'object' &&\n (raw as CoreStartPayload).type === 'start' &&\n ((raw as CoreStartPayload).operation === 'register' ||\n (raw as CoreStartPayload).operation === 'authenticate')\n );\n}\n\nfunction isCoreSuccessPayload(raw: unknown): raw is CoreSuccessPayload {\n const o = raw as Record<string, unknown>;\n return (\n raw != null &&\n typeof raw === 'object' &&\n o.type === 'success' &&\n typeof o.token === 'string' &&\n (o.operation === 'register' || o.operation === 'authenticate')\n );\n}\n\nfunction isCoreErrorPayload(raw: unknown): raw is CoreErrorPayload {\n return raw != null && typeof raw === 'object' && (raw as CoreErrorPayload).type === 'error';\n}\n\nfunction isCoreCancelledPayload(raw: unknown): raw is CoreCancelledPayload {\n return (\n raw != null &&\n typeof raw === 'object' &&\n (raw as CoreCancelledPayload).type === 'cancelled' &&\n ((raw as CoreCancelledPayload).operation === 'register' ||\n (raw as CoreCancelledPayload).operation === 'authenticate')\n );\n}\n\n/** Event-bridge adapter: CoreEventsPort (core → CustomEvents on host). */\nconst eventBridgeAdapter: CoreEventsPort = {\n subscribe(core: CoreWithEvents, host: HTMLElement): () => void {\n if (core == null || host == null) {\n throw new TypeError('eventBridgeAdapter.subscribe: core and host are required');\n }\n const unsubscribes: Array<() => void> = [];\n let lastOperation: 'register' | 'authenticate' = 'authenticate';\n let successEmittedThisCeremony = false;\n\n const offStart = core.on('start', (payload: unknown) => {\n if (!isCoreStartPayload(payload)) return;\n lastOperation = payload.operation;\n successEmittedThisCeremony = false;\n const detail: MellonOperationDetail = {\n operation: toPublicOperation(payload.operation),\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n };\n dispatchCustomEvent<MellonOperationDetail>(host, MELLON_START, detail, {\n bubbles: true,\n composed: true,\n });\n });\n unsubscribes.push(offStart);\n\n const offSuccess = core.on('success', (payload: unknown) => {\n if (!isCoreSuccessPayload(payload)) return;\n if (successEmittedThisCeremony) return;\n if (payload.token.length === 0) return;\n successEmittedThisCeremony = true;\n const mappedUser = mapSuccessUser(payload.user);\n const detail: MellonSuccessDetail = {\n operation: toPublicOperation(payload.operation),\n token: payload.token,\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n ...(mappedUser !== undefined && { user: mappedUser }),\n ...(typeof payload.redirectUrl === 'string' && { redirectUrl: payload.redirectUrl }),\n };\n // Token not exposed to document/window (bubbles: false).\n dispatchCustomEvent<MellonSuccessDetail>(host, MELLON_SUCCESS, detail, {\n bubbles: false,\n composed: true,\n });\n });\n unsubscribes.push(offSuccess);\n\n const offError = core.on('error', (payload: unknown) => {\n if (!isCoreErrorPayload(payload)) return;\n if (successEmittedThisCeremony) return;\n const code = payload.error?.code ?? 'UNKNOWN_ERROR';\n const detail: MellonErrorDetail = {\n operation: toPublicOperation(payload.operation ?? lastOperation),\n code,\n message:\n typeof payload.error?.message === 'string' ? payload.error.message : 'Unknown error',\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n };\n dispatchCustomEvent<MellonErrorDetail>(host, MELLON_ERROR, detail, {\n bubbles: true,\n composed: true,\n });\n });\n unsubscribes.push(offError);\n\n const offCancelled = core.on('cancelled', (payload: unknown) => {\n if (!isCoreCancelledPayload(payload)) return;\n const detail: MellonOperationDetail = {\n operation: toPublicOperation(payload.operation),\n ...(typeof payload.nonce === 'string' && { nonce: payload.nonce }),\n };\n dispatchCustomEvent<MellonOperationDetail>(host, MELLON_CANCELLED, detail, {\n bubbles: true,\n composed: true,\n });\n });\n unsubscribes.push(offCancelled);\n\n return function unsubscribe(): void {\n for (const off of unsubscribes) {\n off();\n }\n };\n },\n};\n\nexport { eventBridgeAdapter };\n","/**\n * Adapter: EnvStatusPort implementado delegando en getClientStatus.\n * Maps ClientStatus (core) → UIClientStatus (domain); coupling to core only here.\n */\nimport type { ClientStatus } from '../../../types';\nimport type { UIClientStatus } from '../../domain/types';\nimport type { EnvStatusPort } from '../../ports/env-evaluator.port';\nimport { getClientStatus } from '../../../utils/support';\n\nfunction mapClientStatusToUI(status: ClientStatus): UIClientStatus {\n return {\n isPasskeySupported: status.isPasskeySupported,\n platformAuthenticatorAvailable: status.platformAuthenticatorAvailable,\n recommendedFlow: status.recommendedFlow,\n };\n}\n\n/**\n * Creates adapter implementing EnvStatusPort using getClientStatus from utils/support. Used in tests or paths without core.\n */\nexport function createEnvStatusAdapter(): EnvStatusPort {\n return {\n getClientStatus: async (): Promise<UIClientStatus> => {\n const status = await getClientStatus();\n return mapClientStatusToUI(status);\n },\n };\n}\n\n/**\n * Creates adapter implementing EnvStatusPort using core TryMellon getStatus. Caller MUST validate getClientStatus result with isClientStatus.\n */\nexport function createEnvStatusPortFromCore(core: unknown): EnvStatusPort {\n const candidate = core as { getStatus?: () => Promise<ClientStatus> };\n if (typeof candidate.getStatus !== 'function') {\n return createEnvStatusAdapter();\n }\n\n const getStatus = candidate.getStatus;\n\n return {\n getClientStatus: async (): Promise<UIClientStatus> => {\n const status = await getStatus();\n return mapClientStatusToUI(status);\n },\n };\n}\n","import {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n} from '../adapters/infra/event-bridge.adapter';\nimport type {\n MellonErrorDetail,\n MellonFallbackDetail,\n MellonOperationDetail,\n MellonSuccessDetail,\n} from '../ports/core-events.port';\nimport type { MellonCloseDetail, MellonOpenDetail } from '../ports';\n\nexport {\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n};\n\nexport function createMellonOpenEvent(detail: MellonOpenDetail): CustomEvent<MellonOpenDetail> {\n return new CustomEvent<MellonOpenDetail>(MELLON_OPEN, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonCloseEvent(detail: MellonCloseDetail): CustomEvent<MellonCloseDetail> {\n return new CustomEvent<MellonCloseDetail>(MELLON_CLOSE, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonCancelledEvent(\n detail: MellonOperationDetail\n): CustomEvent<MellonOperationDetail> {\n return new CustomEvent<MellonOperationDetail>(MELLON_CANCELLED, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonFallbackEvent(\n detail: MellonFallbackDetail\n): CustomEvent<MellonFallbackDetail> {\n return new CustomEvent<MellonFallbackDetail>(MELLON_FALLBACK, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonTabChangeEvent(detail: { tab: string }): CustomEvent<{ tab: string }> {\n return new CustomEvent<{ tab: string }>(MELLON_TAB_CHANGE, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonStartEvent(\n detail: MellonOperationDetail\n): CustomEvent<MellonOperationDetail> {\n return new CustomEvent<MellonOperationDetail>(MELLON_START, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n\nexport function createMellonSuccessEvent(\n detail: MellonSuccessDetail\n): CustomEvent<MellonSuccessDetail> {\n return new CustomEvent<MellonSuccessDetail>(MELLON_SUCCESS, {\n detail,\n bubbles: false,\n composed: true,\n });\n}\n\nexport function createMellonErrorEvent(detail: MellonErrorDetail): CustomEvent<MellonErrorDetail> {\n return new CustomEvent<MellonErrorDetail>(MELLON_ERROR, {\n detail,\n bubbles: true,\n composed: true,\n });\n}\n","import type { UIState, TabKind } from '../domain/types';\nimport { INITIAL_UI_STATE, tabToUIMode } from '../domain/types';\nimport { authUiApplicationService, canStartAuth } from '../application/auth-ui.application-service';\nimport type {\n CoreAuthPort,\n CoreAuthOptions,\n MellonOperationDetail,\n} from '../ports/core-events.port';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\n\nexport type PendingAuthOperation = 'register' | 'authenticate';\n\nexport class AuthController {\n private _currentState: UIState = INITIAL_UI_STATE;\n private _lastRenderedState: UIState | null = null;\n private _renderDirty = true;\n private _pendingOperation: PendingAuthOperation = 'authenticate';\n private _currentNonce: string | undefined = undefined;\n private _envEvalRequestId = 0;\n\n get currentState(): UIState {\n return this._currentState;\n }\n\n setState(next: UIState): void {\n this._currentState = next;\n this._renderDirty = true;\n }\n\n invalidateRender(): void {\n this._renderDirty = true;\n }\n\n /**\n * Decides if a render is needed based on state/dirty flag.\n * Returns true when the caller should render and marks state as clean.\n */\n consumeRenderDecision(): boolean {\n if (!this._renderDirty && this._currentState === this._lastRenderedState) {\n return false;\n }\n this._lastRenderedState = this._currentState;\n this._renderDirty = false;\n return true;\n }\n\n setPendingOperationFromTab(tab: TabKind): void {\n this._pendingOperation = tab === 'login' ? 'authenticate' : 'register';\n }\n\n get pendingOperation(): PendingAuthOperation {\n return this._pendingOperation;\n }\n\n setNonce(nonce: string | undefined): void {\n this._currentNonce = nonce;\n }\n\n consumeCancelledDetailIfAuthenticating(): MellonOperationDetail | null {\n if (this._currentState !== 'AUTHENTICATING') return null;\n const detail: MellonOperationDetail = {\n operation: this._pendingOperation === 'authenticate' ? 'login' : this._pendingOperation,\n ...(this._currentNonce !== undefined && { nonce: this._currentNonce }),\n };\n this._currentNonce = undefined;\n return detail;\n }\n\n handleAuthSuccess(): void {\n const next = authUiApplicationService.tryHandleAuthSuccess(this._currentState);\n if (next === null) return;\n this.setState(next);\n }\n\n handleAuthError(): void {\n const next = authUiApplicationService.tryHandleAuthError(this._currentState);\n if (next === null) return;\n this.setState(next);\n }\n\n onStartEvent(detail: MellonOperationDetail | undefined): void {\n if (detail?.nonce !== undefined) {\n this._currentNonce = detail.nonce;\n }\n }\n\n startAuthFromClick(core: CoreAuthPort | null, tab: TabKind, options?: CoreAuthOptions): void {\n if (!core) return;\n if (!canStartAuth(this._currentState)) return;\n this.setPendingOperationFromTab(tab);\n const next = authUiApplicationService.startAuth(\n this._currentState,\n tabToUIMode(tab),\n core,\n options\n );\n this.setState(next);\n }\n\n async runEnvEval(params: Omit<RunEnvEvalParams, 'currentState'>): Promise<UIState | null> {\n const requestId = ++this._envEvalRequestId;\n this.setState(authUiApplicationService.envEvalStart(this._currentState));\n const nextState = await authUiApplicationService.evaluateEnv({\n ...params,\n currentState: this._currentState,\n });\n if (requestId !== this._envEvalRequestId) {\n return null;\n }\n return nextState;\n }\n\n reset(): void {\n this._currentState = authUiApplicationService.reset(this._currentState);\n this._lastRenderedState = null;\n this._renderDirty = true;\n this._currentNonce = undefined;\n }\n\n setStateForRender(state: UIState): void {\n this._currentState = state;\n this._renderDirty = true;\n }\n}\n","/**\n * Abstract base for <trymellon-auth> and <trymellon-auth-modal>. Shared lifecycle: teardown, host/fallback listeners, Mellon handlers, env eval.\n * AuthController encapsulates FSM/env-eval; this base wires it to HTMLElement and DOM events.\n */\nimport type { UIState, TabKind } from '../domain/types';\nimport { createEnvStatusPortFromCore } from '../adapters/infra/env-status.adapter';\nimport { eventBridgeAdapter } from '../adapters/infra/event-bridge.adapter';\nimport type {\n CoreAuthPort,\n MellonFallbackDetail,\n MellonOperationDetail,\n} from '../ports/core-events.port';\nimport { createCoreForUI, isCoreAuthPort } from '../adapters/infra/core-factory.adapter';\nimport type { CoreConfig } from '../adapters/infra/core-factory.adapter';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\nimport { createMellonCancelledEvent, createMellonFallbackEvent } from './ui-events';\nimport { AuthController } from './auth-controller';\n\n/**\n * Abstract base: FSM, core, event bridge, env eval, fallback/shadow click.\n * Subclasses define observedAttributes, parsing, _render() and (modal only) open/tab.\n * Render flow: setState / invalidateRender → scheduleRenderIfNeeded → _render (single path).\n */\nexport abstract class AuthElementBase extends HTMLElement {\n protected _controller = new AuthController();\n protected _unsubscribeBridge: (() => void) | null = null;\n protected _core: CoreAuthPort | null = null;\n protected _lastCoreConfig: CoreConfig | null = null;\n\n /** Encapsulates state assignment and schedules render. Single canonical way to change _currentState and trigger _render. */\n protected setState(next: UIState): void {\n this._controller.setState(next);\n this.scheduleRenderIfNeeded();\n }\n\n /** Marks that a re-render is needed even if FSM state did not change (e.g. theme or props). */\n protected invalidateRender(): void {\n this._controller.invalidateRender();\n this.scheduleRenderIfNeeded();\n }\n\n /** Compares current state with last render; if changed or dirty, calls _render and updates cache. */\n protected scheduleRenderIfNeeded(): void {\n if (!this.shadowRoot) return;\n if (!this._controller.consumeRenderDecision()) return;\n this._render();\n }\n\n /** If state was AUTHENTICATING: build detail, dispatch mellon:cancelled, clear nonce; return true. Else false. */\n protected _emitCancelledIfAuthenticating(): boolean {\n const detail = this._controller.consumeCancelledDetailIfAuthenticating();\n if (!detail) return false;\n this.dispatchEvent(createMellonCancelledEvent(detail));\n return true;\n }\n\n /**\n * Injects auth core and starts env eval. Pass null to detach and transition to IDLE.\n * Multi-write safe: teardown existing core before attaching new one. Host must call reset() before re-open if WC stays in DOM.\n * @param core - CoreAuthPort-compatible instance, or null to detach.\n */\n attachCore(core: unknown): void {\n if (this._core !== null) {\n this._teardownCore();\n }\n if (core == null) {\n this._core = null;\n this._controller.reset();\n this.scheduleRenderIfNeeded();\n return;\n }\n if (!isCoreAuthPort(core)) {\n throw new Error('[trymellon-auth] attachCore requires a CoreAuthPort-compatible instance.');\n }\n this._core = core;\n this._unsubscribeBridge = eventBridgeAdapter.subscribe(this._core, this);\n this._attachHostListeners();\n this._runEnvEval();\n }\n\n protected _teardownCore(): void {\n this._unsubscribeBridge?.();\n this._unsubscribeBridge = null;\n this.removeEventListener('mellon:start', this._onMellonStart);\n this.removeEventListener('mellon:success', this._onMellonSuccess);\n this.removeEventListener('mellon:error', this._onMellonError);\n this._core = null;\n }\n\n protected _attachHostListeners(): void {\n this.removeEventListener('mellon:start', this._onMellonStart);\n this.removeEventListener('mellon:success', this._onMellonSuccess);\n this.removeEventListener('mellon:error', this._onMellonError);\n this.addEventListener('mellon:start', this._onMellonStart);\n this.addEventListener('mellon:success', this._onMellonSuccess);\n this.addEventListener('mellon:error', this._onMellonError);\n }\n\n protected _onMellonSuccess = (): void => {\n this._controller.handleAuthSuccess();\n this.scheduleRenderIfNeeded();\n };\n\n protected _onMellonError = (): void => {\n this._controller.handleAuthError();\n this.scheduleRenderIfNeeded();\n };\n\n protected _onMellonStart = (e: Event): void => {\n const detail = (e as CustomEvent<MellonOperationDetail>).detail;\n this._controller.onStartEvent(detail);\n };\n\n /**\n * Semantic logic for \"click on primary auth button\". Subclasses register DOM delegation\n * (e.g. adapters/interactions/dom.adapter) and call this method from the callback.\n */\n protected startAuthFromClick(): void {\n if (!this._core) return;\n if (!this.canStartAuth()) return;\n this._controller.startAuthFromClick(this._core, this.getTabKind(), this.getCoreAuthOptions());\n this.scheduleRenderIfNeeded();\n }\n\n /**\n * Emits mellon:fallback. With type = email|qr sets detail.fallbackType; without type (generic \"Continue\") does not set fallbackType.\n */\n protected dispatchFallback(type?: 'email' | 'qr'): void {\n const detail: MellonFallbackDetail =\n type !== undefined\n ? { ...this.getFallbackDetail(), fallbackType: type }\n : this.getFallbackDetail();\n this.dispatchEvent(createMellonFallbackEvent(detail));\n }\n\n protected async _runEnvEval(): Promise<void> {\n if (!this._core) return;\n const params: RunEnvEvalParams = {\n ...this.getEnvEvalParams(),\n envStatusPort: createEnvStatusPortFromCore(this._core),\n // currentState is injected by AuthController\n } as RunEnvEvalParams;\n const nextState = await this._controller.runEnvEval(params);\n if (nextState === null) return;\n if (!this._core || !this.isConnected) return;\n this.setState(nextState);\n }\n\n protected _maybeAutoCreateCoreAndRunEnvEval(): void {\n if (this._core !== null) return;\n const config = this.getCoreConfig();\n if (!config) return;\n const core = createCoreForUI(config);\n if (!core) {\n this.attachCore(null);\n return;\n }\n this.attachCore(core);\n }\n\n /** Single path: compare config with last, attach or detach core. No per-call special cases. */\n protected _reconcileCoreFromConfig(): void {\n const nextConfig = this.getCoreConfig();\n const sameConfig =\n (this._lastCoreConfig === null && nextConfig === null) ||\n (this._lastCoreConfig !== null &&\n nextConfig !== null &&\n this._lastCoreConfig.appId === nextConfig.appId &&\n this._lastCoreConfig.publishableKey === nextConfig.publishableKey);\n\n if (sameConfig) return;\n\n this._lastCoreConfig = nextConfig;\n\n if (nextConfig === null) {\n this.attachCore(null);\n return;\n }\n\n const core = createCoreForUI(nextConfig);\n this.attachCore(core ?? null);\n }\n\n disconnectedCallback(): void {\n this._teardownCore();\n }\n\n /** Current FSM state (read-only). */\n get currentState(): UIState {\n return this._controller.currentState;\n }\n\n /**\n * Transitions FSM to IDLE, clears in-flight ceremony, re-renders. If state was AUTHENTICATING, emits mellon:cancelled first.\n * Host must call reset() before re-open if WC remains in DOM after close.\n */\n reset(): void {\n this._emitCancelledIfAuthenticating();\n this._controller.reset();\n this.scheduleRenderIfNeeded();\n }\n\n /** Tests only: set state and re-render without FSM transition. */\n setStateForRender(state: UIState): void {\n this._controller.setStateForRender(state);\n this.scheduleRenderIfNeeded();\n }\n\n protected abstract getTabKind(): TabKind;\n protected abstract getCoreAuthOptions(): { externalUserId?: string | null };\n protected abstract canStartAuth(): boolean;\n protected abstract getEnvEvalParams(): Omit<RunEnvEvalParams, 'envStatusPort' | 'currentState'>;\n protected abstract getCoreConfig(): { appId: string; publishableKey: string } | null;\n protected abstract getFallbackDetail(): MellonFallbackDetail;\n protected abstract _render(): void;\n}\n","/**\n * Parses trymellon-auth-modal WC attributes.\n * Uses parseEnum + enum arrays and domain-centralized defaults.\n */\nimport type { ParsedModalAttributes, TabLabels } from '../../domain/contracts/types';\nimport {\n DEFAULT_MODAL_DISPLAY_MODE,\n DEFAULT_MODAL_VARIANT,\n DEFAULT_TAB,\n DEFAULT_TAB_LABELS,\n DEFAULT_THEME,\n} from '../../domain/contracts/constants';\nimport {\n MODAL_DISPLAY_MODES,\n MODAL_VARIANTS,\n TAB_KINDS,\n THEME_KINDS,\n FALLBACK_TYPES,\n} from '../../domain/validators/validators-state';\nimport { ensureParsedModalAttributes } from '../../domain/validators';\nimport {\n parseString,\n parseOptionalString,\n parseBoolean,\n parseOptionalBoolean,\n parseEnum,\n parseOptionalEnum,\n} from './parse.utils';\n\nexport type {\n FallbackTypeKind,\n ModalDisplayMode,\n ModalTabKind,\n ParsedModalAttributes,\n ThemeKind,\n} from '../../domain/contracts/types';\n\n/**\n * Parses tab-labels. Format: \"registerLabel,loginLabel\" (CSV). Missing or empty → domain defaults.\n */\nfunction parseTabLabels(value: string | null): TabLabels {\n if (value == null || value.trim() === '') return DEFAULT_TAB_LABELS;\n const parts = value.split(',').map((p) => p.trim());\n const register = parts[0] ?? DEFAULT_TAB_LABELS.register;\n const login = parts[1] ?? DEFAULT_TAB_LABELS.login;\n return { register, login };\n}\n\n/**\n * Parses all modal attributes from element. Validates at boundary before return (adapter validates domain type).\n */\nexport function parseModalAttributesFromElement(element: HTMLElement): ParsedModalAttributes {\n const raw = {\n open: parseBoolean(element.getAttribute('open')),\n mode: parseEnum(element.getAttribute('mode'), MODAL_DISPLAY_MODES, DEFAULT_MODAL_DISPLAY_MODE),\n tab: parseEnum(element.getAttribute('tab'), TAB_KINDS, DEFAULT_TAB),\n tabLabels: parseTabLabels(element.getAttribute('tab-labels')),\n theme: parseEnum(element.getAttribute('theme'), THEME_KINDS, DEFAULT_THEME),\n sessionId: parseOptionalString(element.getAttribute('session-id')),\n onboardingUrl: parseOptionalString(element.getAttribute('onboarding-url')),\n isMobileOverride: parseOptionalBoolean(element.getAttribute('is-mobile-override')),\n fallbackType: parseOptionalEnum(element.getAttribute('fallback-type'), FALLBACK_TYPES),\n appId: parseString(element.getAttribute('app-id')),\n publishableKey: parseString(element.getAttribute('publishable-key')),\n appName: parseOptionalString(element.getAttribute('app-name')),\n dialogTitle: parseOptionalString(element.getAttribute('dialog-title')),\n dialogDescription: parseOptionalString(element.getAttribute('dialog-description')),\n externalUserId: parseOptionalString(element.getAttribute('external-user-id')),\n modalVariant: parseEnum(\n element.getAttribute('modal-variant'),\n MODAL_VARIANTS,\n DEFAULT_MODAL_VARIANT\n ),\n };\n return ensureParsedModalAttributes(raw);\n}\n","/**\n * Modal DOM structure: overlay (when mode=modal), panel, tabs, content wrapper (slot cross-device + default slot with #mellon-root), fallback-cta slot.\n * createElement/setAttribute/appendChild only. FSM content from shadow.adapter render(). ARIA: dialog on panel, tablist on tabs.\n * Constants: render/constants.ts.\n */\nimport type { ParsedModalAttributes } from '../../domain/contracts/types';\nimport {\n MELLON_ROOT_ID,\n WRAPPER_CLASS,\n OVERLAY_CLASS,\n PANEL_CLASS,\n TABS_CLASS,\n CONTENT_WRAPPER_CLASS,\n SLOT_CROSS_DEVICE,\n SLOT_FALLBACK_CTA,\n MELLON_DIALOG_TITLE_ID,\n MELLON_DIALOG_DESC_ID,\n DIALOG_TITLE_TEXT,\n DIALOG_TITLE_WITH_APP,\n DIALOG_DESC_TEXT,\n MODAL_SEPARATOR_TEXT,\n CROSS_DEVICE_WRAP_CLASS,\n MODAL_SEPARATOR_CLASS,\n CROSS_DEVICE_CTA_TEXT,\n CROSS_DEVICE_CTA_CLASS,\n CROSS_DEVICE_QR_BUTTON_ARIA_LABEL,\n MELLON_ACTION_FALLBACK_QR,\n MELLON_QR_SKELETON_CLASS,\n MELLON_QR_ERROR_CLASS,\n MELLON_QR_SLOT_WRAP_CLASS,\n QR_SKELETON_TEXT,\n QR_TIMEOUT_ERROR_TEXT,\n SVG_NS,\n MODAL_CLOSE_BUTTON_CLASS,\n MODAL_CLOSE_BUTTON_ARIA_LABEL,\n} from './constants';\n\nexport { SLOT_CROSS_DEVICE, MELLON_DIALOG_TITLE_ID, MELLON_DIALOG_DESC_ID };\n\nfunction ensureWrapper(shadowRoot: ShadowRoot): HTMLElement {\n let wrapper = shadowRoot.querySelector<HTMLElement>(`.${WRAPPER_CLASS}`);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.className = WRAPPER_CLASS;\n shadowRoot.appendChild(wrapper);\n }\n return wrapper;\n}\n\nfunction ensureOverlay(wrapper: HTMLElement): HTMLElement {\n let overlay = wrapper.querySelector<HTMLElement>(`.${OVERLAY_CLASS}`);\n if (!overlay) {\n overlay = document.createElement('div');\n overlay.className = OVERLAY_CLASS;\n overlay.setAttribute('aria-hidden', 'true');\n wrapper.appendChild(overlay);\n }\n return overlay;\n}\n\nfunction ensurePanel(wrapper: HTMLElement): HTMLElement {\n let panel = wrapper.querySelector<HTMLElement>(`.${PANEL_CLASS}`);\n if (!panel) {\n panel = document.createElement('div');\n panel.className = PANEL_CLASS;\n wrapper.appendChild(panel);\n }\n return panel;\n}\n\n/** Panel as dialog: role, aria-modal, labelledby/describedby. */\nfunction setPanelDialogAria(panel: HTMLElement, mode: 'modal' | 'inline'): void {\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', mode === 'modal' ? 'true' : 'false');\n panel.setAttribute('aria-labelledby', MELLON_DIALOG_TITLE_ID);\n panel.setAttribute('aria-describedby', MELLON_DIALOG_DESC_ID);\n}\n\n/** Creates or reuses dialog title and description; inserts at panel start. Uses dialog-title/dialog-description when set, else app-name + defaults. */\nfunction ensureDialogTitleAndDescription(panel: HTMLElement, parsed: ParsedModalAttributes): void {\n let titleEl = panel.querySelector<HTMLElement>(`#${MELLON_DIALOG_TITLE_ID}`);\n if (!titleEl) {\n titleEl = document.createElement('h2');\n titleEl.id = MELLON_DIALOG_TITLE_ID;\n titleEl.className = 'mellon-dialog-title';\n panel.insertBefore(titleEl, panel.firstChild);\n }\n const titleText =\n parsed.dialogTitle?.trim() ??\n (parsed.appName?.trim() ? DIALOG_TITLE_WITH_APP(parsed.appName.trim()) : DIALOG_TITLE_TEXT);\n titleEl.textContent = titleText;\n\n let descEl = panel.querySelector<HTMLElement>(`#${MELLON_DIALOG_DESC_ID}`);\n if (!descEl) {\n descEl = document.createElement('p');\n descEl.id = MELLON_DIALOG_DESC_ID;\n descEl.className = 'mellon-dialog-desc';\n panel.insertBefore(descEl, titleEl.nextSibling);\n }\n descEl.textContent = parsed.dialogDescription?.trim() ?? DIALOG_DESC_TEXT;\n}\n\n/** Close button (visual 'X') in top-right corner of the modal panel. */\nfunction ensureCloseButton(panel: HTMLElement): void {\n let btn = panel.querySelector<HTMLButtonElement>(`.${MODAL_CLOSE_BUTTON_CLASS}`);\n if (btn) return;\n btn = document.createElement('button');\n btn.type = 'button';\n btn.className = MODAL_CLOSE_BUTTON_CLASS;\n btn.setAttribute('aria-label', MODAL_CLOSE_BUTTON_ARIA_LABEL);\n btn.setAttribute('data-mellon-modal-close', 'true');\n btn.textContent = '×';\n panel.appendChild(btn);\n}\n\nfunction ensureTabs(\n panel: HTMLElement,\n tabLabels: { register: string; login: string }\n): HTMLElement {\n let tabs = panel.querySelector<HTMLElement>(`.${TABS_CLASS}`);\n if (!tabs) {\n tabs = document.createElement('div');\n tabs.className = TABS_CLASS;\n tabs.setAttribute('role', 'tablist');\n const btnRegister = document.createElement('button');\n btnRegister.type = 'button';\n btnRegister.setAttribute('data-tab', 'register');\n btnRegister.setAttribute('role', 'tab');\n const btnLogin = document.createElement('button');\n btnLogin.type = 'button';\n btnLogin.setAttribute('data-tab', 'login');\n btnLogin.setAttribute('role', 'tab');\n tabs.appendChild(btnRegister);\n tabs.appendChild(btnLogin);\n const afterDesc = panel.querySelector<HTMLElement>(`#${MELLON_DIALOG_DESC_ID}`);\n panel.insertBefore(tabs, afterDesc ? afterDesc.nextSibling : panel.firstChild);\n }\n const [btnRegister, btnLogin] = tabs.querySelectorAll('button');\n if (btnRegister) btnRegister.textContent = tabLabels.register;\n if (btnLogin) btnLogin.textContent = tabLabels.login;\n return tabs;\n}\n\n/** Content wrapper: cross-device slot (QR) + default slot (mellon-root). Same structure as landing: QR above, Try Passkey below. */\nfunction ensureModalContentWrapper(panel: HTMLElement): HTMLElement {\n let wrapper = panel.querySelector<HTMLElement>(`.${CONTENT_WRAPPER_CLASS}`);\n if (!wrapper) {\n wrapper = document.createElement('div');\n wrapper.className = CONTENT_WRAPPER_CLASS;\n const afterTabs = panel.querySelector(`.${TABS_CLASS}`);\n panel.insertBefore(wrapper, afterTabs ? afterTabs.nextSibling : panel.firstChild);\n }\n return wrapper;\n}\n\n/** QR code icon as inline SVG (icon-only button). */\nfunction createQrIconSVG(): SVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('class', 'mellon-qr-icon');\n svg.setAttribute('fill', 'currentColor');\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute(\n 'd',\n 'M3 3h6v6H3V3zm2 2v2h2V5H5zm8-2h6v6h-6V3zm2 2v2h2V5h-2zM3 15h6v6H3v-6zm2 2v2h2v-2H5zm8-2h6v6h-6v-6zm2 2v2h2v-2h-2zm4-12h2v2h-2V5zm0 8h2v2h-2v-2zm-4 4h2v2h-2v-2zm0-8h2v2h-2V9zm0 4h2v2h-2v-2z'\n );\n svg.appendChild(path);\n return svg;\n}\n\n/** Default content for cross-device slot: CTA text + icon-only QR button. Shown when host does not inject QR; click dispatches fallback qr. */\nfunction createCrossDeviceDefaultContent(): DocumentFragment {\n const frag = document.createDocumentFragment();\n const wrap = document.createElement('div');\n wrap.className = CROSS_DEVICE_CTA_CLASS;\n const p = document.createElement('p');\n p.className = 'mellon-cross-device-cta-text';\n p.textContent = CROSS_DEVICE_CTA_TEXT;\n wrap.appendChild(p);\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'mellon-btn mellon-btn-qr-icon';\n btn.setAttribute('data-mellon-action', MELLON_ACTION_FALLBACK_QR);\n btn.setAttribute('aria-label', CROSS_DEVICE_QR_BUTTON_ARIA_LABEL);\n btn.appendChild(createQrIconSVG());\n wrap.appendChild(btn);\n frag.appendChild(wrap);\n return frag;\n}\n\n/** Skeleton node (modal-owned): shown when waiting for host-injected QR. */\nfunction createQrSkeletonNode(): HTMLElement {\n const el = document.createElement('div');\n el.className = MELLON_QR_SKELETON_CLASS;\n el.setAttribute('aria-live', 'polite');\n const label = document.createElement('span');\n label.textContent = QR_SKELETON_TEXT;\n const dots = document.createElement('span');\n dots.className = 'mellon-qr-dots';\n dots.setAttribute('aria-hidden', 'true');\n el.appendChild(label);\n el.appendChild(dots);\n return el;\n}\n\n/** Error node (modal-owned): shown when QR load times out. */\nfunction createQrErrorNode(): HTMLElement {\n const el = document.createElement('div');\n el.className = MELLON_QR_ERROR_CLASS;\n el.setAttribute('aria-live', 'polite');\n el.textContent = QR_TIMEOUT_ERROR_TEXT;\n return el;\n}\n\n/** Wrapper + slot for cross-device UI. Includes skeleton (waiting) and error (timeout); slot shows default CTA or host-injected QR. */\nfunction ensureCrossDeviceSlot(panel: HTMLElement): HTMLSlotElement {\n const wrapper = ensureModalContentWrapper(panel);\n let wrap = wrapper.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (!wrap) {\n wrap = document.createElement('div');\n wrap.className = CROSS_DEVICE_WRAP_CLASS;\n wrap.setAttribute('data-qr-area-state', 'default');\n\n wrap.appendChild(createQrSkeletonNode());\n wrap.appendChild(createQrErrorNode());\n\n const slotWrap = document.createElement('div');\n slotWrap.className = MELLON_QR_SLOT_WRAP_CLASS;\n const slot = document.createElement('slot');\n slot.name = SLOT_CROSS_DEVICE;\n slot.appendChild(createCrossDeviceDefaultContent());\n slotWrap.appendChild(slot);\n wrap.appendChild(slotWrap);\n\n wrapper.appendChild(wrap);\n }\n const slot = wrap.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_CROSS_DEVICE}\"]`);\n if (!slot) {\n const created = document.createElement('slot');\n created.name = SLOT_CROSS_DEVICE;\n created.appendChild(createCrossDeviceDefaultContent());\n wrap.appendChild(created);\n return created;\n }\n return slot;\n}\n\n/** Separator: continuous lines with \"or\" centered between them. */\nfunction ensureSeparator(panel: HTMLElement): void {\n const wrapper = ensureModalContentWrapper(panel);\n if (wrapper.querySelector(`.${MODAL_SEPARATOR_CLASS}`)) return;\n const sep = document.createElement('div');\n sep.className = MODAL_SEPARATOR_CLASS;\n sep.setAttribute('aria-hidden', 'true');\n const span = document.createElement('span');\n span.className = 'mellon-separator-text';\n span.textContent = MODAL_SEPARATOR_TEXT;\n sep.appendChild(span);\n const wrap = wrapper.querySelector(`.${CROSS_DEVICE_WRAP_CLASS}`);\n wrapper.insertBefore(sep, wrap ? wrap.nextSibling : wrapper.firstChild);\n}\n\n/** Default slot: main content; fallback #mellon-root when host does not inject. Lives inside content wrapper. */\nfunction ensureDefaultSlotWithRoot(panel: HTMLElement): HTMLElement {\n const wrapper = ensureModalContentWrapper(panel);\n let slot = wrapper.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) {\n slot = document.createElement('slot');\n const root = document.createElement('div');\n root.id = MELLON_ROOT_ID;\n root.className = 'mellon-root';\n slot.appendChild(root);\n wrapper.appendChild(slot);\n }\n let root = panel.querySelector<HTMLElement>(`#${MELLON_ROOT_ID}`);\n if (!root) {\n root = document.createElement('div');\n root.id = MELLON_ROOT_ID;\n root.className = 'mellon-root';\n slot.appendChild(root);\n }\n return root;\n}\n\nfunction ensureFallbackSlot(panel: HTMLElement): HTMLSlotElement {\n let slot = panel.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_FALLBACK_CTA}\"]`);\n if (!slot) {\n slot = document.createElement('slot');\n slot.name = SLOT_FALLBACK_CTA;\n panel.appendChild(slot);\n }\n return slot;\n}\n\n/** Syncs active tab on buttons (aria-selected). Does not control wrapper/overlay visibility (WC responsibility via open/mode). */\nfunction syncTabAriaSelected(panel: HTMLElement, activeTab: 'register' | 'login'): void {\n const tabs = panel.querySelector<HTMLElement>(`.${TABS_CLASS}`);\n if (!tabs) return;\n const reg = tabs.querySelector<HTMLButtonElement>('[data-tab=\"register\"]');\n const log = tabs.querySelector<HTMLButtonElement>('[data-tab=\"login\"]');\n if (reg) reg.setAttribute('aria-selected', String(activeTab === 'register'));\n if (log) log.setAttribute('aria-selected', String(activeTab === 'login'));\n}\n\n/** Ensures modal structure: wrapper, overlay when mode=modal, panel, tabs, #mellon-root, fallback-cta slot, tab aria-selected. Visibility (open/mode) is WC responsibility. */\nfunction ensureModalStructure(shadowRoot: ShadowRoot, parsed: ParsedModalAttributes): void {\n if (shadowRoot == null || parsed == null) return;\n const wrapper = ensureWrapper(shadowRoot);\n wrapper.setAttribute('data-mellon-modal-variant', parsed.modalVariant);\n if (parsed.mode === 'modal') {\n ensureOverlay(wrapper);\n }\n const panel = ensurePanel(wrapper);\n setPanelDialogAria(panel, parsed.mode);\n ensureDialogTitleAndDescription(panel, parsed);\n ensureCloseButton(panel);\n ensureTabs(panel, parsed.tabLabels);\n ensureCrossDeviceSlot(panel);\n ensureSeparator(panel);\n ensureDefaultSlotWithRoot(panel);\n ensureFallbackSlot(panel);\n syncTabAriaSelected(panel, parsed.tab);\n}\n\nexport { ensureModalStructure };\n","/**\n * Focus trap: keeps focus inside a container. Tab/Shift+Tab cycle within; deactivate restores focus to previous element or body.\n * Used by adapters; WC in presentation only calls activate/deactivate.\n * Constants: interactions/constants.ts.\n */\nimport { FOCUSABLE_SELECTOR } from './constants';\n\n/** Excludes hidden elements; avoids offsetParent (often null in jsdom shadow). */\nfunction isFocusableCandidate(el: HTMLElement): boolean {\n if ((el as unknown as { hidden?: boolean }).hidden === true) return false;\n if (el.getAttribute('aria-hidden') === 'true') return false;\n return true;\n}\n\n/** Returns focusable elements inside container in document order (visible only). */\nexport function getFocusables(container: HTMLElement): HTMLElement[] {\n const candidates = Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n return candidates.filter((el) => isFocusableCandidate(el));\n}\n\nexport interface FocusTrapHandle {\n activate(): void;\n deactivate(): void;\n}\n\n/**\n * Creates a focus trap on container. activate(): store activeElement, focus first focusable, add Tab keydown.\n * deactivate(): remove listener, restore focus to stored element if still in document, else body.\n */\nexport function createFocusTrap(container: HTMLElement): FocusTrapHandle {\n let previousActiveElement: Element | null = null;\n let keydownBound: ((e: KeyboardEvent) => void) | null = null;\n let isActive = false;\n\n function handleKeydown(e: KeyboardEvent): void {\n if (e.key !== 'Tab') return;\n const focusables = getFocusables(container);\n if (focusables.length === 0) return;\n const current = e.target instanceof Node ? (e.target as HTMLElement) : null;\n const currentIndex = current ? focusables.indexOf(current) : -1;\n const lastIndex = focusables.length - 1;\n let nextIndex: number;\n if (e.shiftKey) {\n nextIndex = currentIndex <= 0 ? lastIndex : currentIndex - 1;\n } else {\n nextIndex = currentIndex >= lastIndex ? 0 : currentIndex + 1;\n }\n const next = focusables[nextIndex];\n if (next) {\n e.preventDefault();\n next.focus();\n }\n }\n\n function activate(): void {\n if (isActive) return;\n previousActiveElement = document.activeElement;\n const focusables = getFocusables(container);\n const first = focusables[0];\n if (first) {\n first.focus();\n }\n keydownBound = handleKeydown;\n container.addEventListener('keydown', keydownBound, true);\n isActive = true;\n }\n\n function deactivate(): void {\n if (!isActive) return;\n if (keydownBound) {\n container.removeEventListener('keydown', keydownBound, true);\n keydownBound = null;\n }\n isActive = false;\n const doc = (container.getRootNode() as Document | ShadowRoot)?.ownerDocument ?? document;\n const toRestore =\n previousActiveElement instanceof HTMLElement && doc.body.contains(previousActiveElement)\n ? previousActiveElement\n : null;\n if (toRestore) {\n toRestore.focus();\n } else {\n const body = doc.body as HTMLElement;\n const prevTabindex = body.getAttribute('tabindex');\n body.setAttribute('tabindex', '-1');\n body.focus();\n if (prevTabindex === null) body.removeAttribute('tabindex');\n else body.setAttribute('tabindex', prevTabindex);\n }\n previousActiveElement = null;\n }\n\n return { activate, deactivate };\n}\n","/**\n * Centralized constants for the presentation layer (WC elements).\n * Attribute names, modal DOM selectors, close reasons. Single source — no magic strings.\n * Selector class names must match render layer (styles.adapter, modal-structure.adapter).\n */\n\n// --- Modal DOM selectors (class names aligned with render/constants WRAPPER_CLASS, etc.) ---\nconst MODAL_WRAPPER_CLASS = 'mellon-modal-wrapper';\nconst MODAL_OVERLAY_CLASS = 'mellon-modal-overlay';\nconst MODAL_PANEL_CLASS = 'mellon-modal-panel';\n\n// --- Observed attribute names (public API) ---\n\nexport const OBSERVED_ATTRIBUTES_AUTH = [\n 'app-id',\n 'publishable-key',\n 'mode',\n 'external-user-id',\n 'theme',\n 'action',\n 'trigger-only',\n 'button-variant',\n 'button-label',\n 'button-aria-label',\n] as const;\n\nexport const OBSERVED_ATTRIBUTES_MODAL = [\n 'open',\n 'mode',\n 'tab',\n 'tab-labels',\n 'theme',\n 'session-id',\n 'onboarding-url',\n 'is-mobile-override',\n 'fallback-type',\n 'app-id',\n 'publishable-key',\n 'app-name',\n 'dialog-title',\n 'dialog-description',\n 'external-user-id',\n 'modal-variant',\n 'qr-load-timeout-ms',\n] as const;\n\n// --- Modal DOM selectors ---\n\nexport const MODAL_SELECTORS = {\n wrapper: `.${MODAL_WRAPPER_CLASS}`,\n overlay: `.${MODAL_OVERLAY_CLASS}`,\n panel: `.${MODAL_PANEL_CLASS}`,\n} as const;\n\n// --- Close / event reasons ---\n\nexport const MELLON_CLOSE_REASON_DEFAULT = 'user' as const;\n","/**\n * Web Component <trymellon-auth-modal>. Public API per 01-limites-api-publica.md.\n * Extends AuthElementBase; attributes, parsing, modal structure, open/tab and _render only.\n */\nimport type { UIState, TabKind } from '../domain/types';\nimport { tabToUIMode } from '../domain/types';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\nimport { authUiApplicationService } from '../application/auth-ui.application-service';\nimport type { ParsedModalAttributes } from '../adapters/attributes/modal.adapter';\nimport { parseModalAttributesFromElement } from '../adapters/attributes/modal.adapter';\nimport { ensureModalStructure } from '../adapters/render/modal-structure.adapter';\nimport { createFocusTrap, type FocusTrapHandle } from '../adapters/interactions/focus-trap.adapter';\nimport { buildAuthModalViewModel } from '../domain/auth-viewmodels';\nimport { renderAuthModal } from '../adapters/render/auth.adapter';\nimport { registerAuthModalInteractions } from '../adapters/interactions/dom.adapter';\nimport { MODAL_PASSKEY_ARIA_LABEL, MODAL_PASSKEY_BUTTON_LABEL } from '../adapters/render/constants';\nimport {\n createModalConstructableStylesheet,\n getModalStylesFallback,\n} from '../adapters/render/styles.adapter';\nimport type { IRenderSurface } from '../ports/render.port';\nimport type { MellonCloseDetail, MellonFallbackDetail, MellonOpenDetail } from '../ports';\nimport {\n createMellonCloseEvent,\n createMellonOpenEvent,\n createMellonTabChangeEvent,\n} from './ui-events';\nimport { AuthElementBase } from './auth-element-base';\nimport {\n OBSERVED_ATTRIBUTES_MODAL,\n MODAL_SELECTORS,\n MELLON_CLOSE_REASON_DEFAULT,\n} from './constants';\nimport {\n CROSS_DEVICE_WRAP_CLASS,\n SLOT_CROSS_DEVICE,\n QR_LOAD_TIMEOUT_MS_DEFAULT,\n} from '../adapters/render/constants';\n\n/** State → close reason. Lookup only; default handles all unmapped states (good taste: no special-case ifs). */\nconst CLOSE_REASON_BY_STATE: Partial<Record<UIState, MellonCloseDetail>> = {\n SUCCESS: { reason: 'success' },\n AUTHENTICATING: { reason: 'cancel' },\n ERROR: { reason: 'error' },\n};\n\nfunction closeDetailFromState(state: UIState): MellonCloseDetail {\n const mapped = CLOSE_REASON_BY_STATE[state];\n return mapped ?? { reason: MELLON_CLOSE_REASON_DEFAULT };\n}\n\nexport class TryMellonAuthModalElement extends AuthElementBase {\n static get observedAttributes(): string[] {\n return [...OBSERVED_ATTRIBUTES_MODAL];\n }\n\n protected _parsed: ParsedModalAttributes = parseModalAttributesFromElement(this as HTMLElement);\n private _focusTrap: FocusTrapHandle | null = null;\n private _unregisterInteractions: (() => void) | null = null;\n /** When external-user-id is not set, register uses this UUID so backend can notify client without external UI. */\n private _generatedExternalUserId: string | null = null;\n private _qrLoadTimeoutId: number | null = null;\n private _qrSlotChangeBound: (() => void) | null = null;\n\n /** Escape closes modal via same path as open=false → _transitionToIdle. */\n private _boundEscapeKeydown = (e: KeyboardEvent): void => {\n if (e.key !== 'Escape') return;\n if (!this._parsed.open) return;\n e.preventDefault();\n this.open = false;\n };\n\n connectedCallback(): void {\n this.addEventListener('keydown', this._boundEscapeKeydown, true);\n if (this.shadowRoot) {\n this._registerInteractions();\n if (this._core !== null && this._unsubscribeBridge === null) {\n this.attachCore(this._core);\n }\n return;\n }\n\n const shadow = this.attachShadow({ mode: 'open' });\n\n const sheet = createModalConstructableStylesheet();\n if (sheet) {\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const styleEl = document.createElement('style');\n styleEl.textContent = getModalStylesFallback();\n shadow.appendChild(styleEl);\n }\n\n this._parsed = parseModalAttributesFromElement(this);\n ensureModalStructure(shadow, this._parsed);\n this._registerInteractions();\n this._render();\n this._applyModalVisibility();\n this._maybeAutoCreateCoreAndRunEnvEval();\n }\n\n private _registerInteractions(): void {\n if (!this.shadowRoot) return;\n this._unregisterInteractions?.();\n this._unregisterInteractions = registerAuthModalInteractions(this.shadowRoot, {\n onTabChange: (tab) => {\n this.dispatchEvent(createMellonTabChangeEvent({ tab }));\n this.setAttribute('tab', tab);\n },\n onPrimaryClick: () => this.startAuthFromClick(),\n onFallbackClick: (type) => this.dispatchFallback(type),\n onOverlayClick: () => {\n this.open = false;\n },\n onCloseClick: () => {\n this.open = false;\n },\n });\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, _newValue: string | null): void {\n if (!this.shadowRoot) return;\n this._parsed = parseModalAttributesFromElement(this);\n if (name === 'open') {\n if (this._parsed.open && oldValue !== 'true') {\n const detail: MellonOpenDetail = { timestamp: Date.now() };\n this.dispatchEvent(createMellonOpenEvent(detail));\n this._startQrLoadWait();\n }\n if (!this._parsed.open) {\n this._clearQrLoadWait();\n this._transitionToIdle();\n return;\n }\n }\n if (name === 'tab') {\n this._emitCancelledIfAuthenticating();\n this.setState(authUiApplicationService.tabChange(this.currentState, this._parsed.tab));\n }\n if (name === 'app-id' || name === 'publishable-key') {\n this._reconcileCoreFromConfig();\n }\n ensureModalStructure(this.shadowRoot, this._parsed);\n this._render();\n this._applyModalVisibility();\n }\n\n private _startQrLoadWait(): void {\n const root = this.shadowRoot;\n if (!root) return;\n const wrap = root.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n const slot = root.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_CROSS_DEVICE}\"]`);\n if (!wrap || !slot) return;\n wrap.setAttribute('data-qr-area-state', 'waiting');\n const ms = Math.max(\n 1000,\n parseInt(this.getAttribute('qr-load-timeout-ms') ?? String(QR_LOAD_TIMEOUT_MS_DEFAULT), 10) ||\n QR_LOAD_TIMEOUT_MS_DEFAULT\n );\n this._qrLoadTimeoutId = window.setTimeout(() => {\n this._qrLoadTimeoutId = null;\n if (!this.shadowRoot) return;\n const wrapElement = this.shadowRoot.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (wrapElement?.getAttribute('data-qr-area-state') === 'waiting') {\n wrapElement.setAttribute('data-qr-area-state', 'timeout');\n }\n }, ms);\n const onSlotChange = (): void => {\n if (slot.assignedNodes().length > 0) {\n this._clearQrLoadWait();\n const w = this.shadowRoot?.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (w) w.setAttribute('data-qr-area-state', 'loaded');\n }\n };\n this._qrSlotChangeBound = onSlotChange;\n slot.addEventListener('slotchange', onSlotChange);\n if (slot.assignedNodes().length > 0) onSlotChange();\n }\n\n private _clearQrLoadWait(): void {\n if (this._qrLoadTimeoutId != null) {\n clearTimeout(this._qrLoadTimeoutId);\n this._qrLoadTimeoutId = null;\n }\n const root = this.shadowRoot;\n if (!root) return;\n const slot = root.querySelector<HTMLSlotElement>(`slot[name=\"${SLOT_CROSS_DEVICE}\"]`);\n if (slot && this._qrSlotChangeBound) {\n slot.removeEventListener('slotchange', this._qrSlotChangeBound);\n this._qrSlotChangeBound = null;\n }\n const wrap = root.querySelector<HTMLElement>(`.${CROSS_DEVICE_WRAP_CLASS}`);\n if (wrap) wrap.setAttribute('data-qr-area-state', 'default');\n }\n\n /** Single path to IDLE: close event, cancelled if needed, reset FSM, structure, render, visibility. Called from open→false and reset(). */\n private _transitionToIdle(): void {\n this._generatedExternalUserId = null;\n const closeDetail = closeDetailFromState(this.currentState);\n const detail: MellonCloseDetail = { reason: closeDetail.reason, timestamp: Date.now() };\n this.dispatchEvent(createMellonCloseEvent(detail));\n this._emitCancelledIfAuthenticating();\n this.setState(authUiApplicationService.reset(this.currentState));\n if (!this.shadowRoot) return;\n ensureModalStructure(this.shadowRoot, this._parsed);\n this.scheduleRenderIfNeeded();\n this._applyModalVisibility();\n }\n\n get open(): boolean {\n return this._parsed.open;\n }\n set open(value: boolean) {\n this.setAttribute('open', value ? 'true' : 'false');\n }\n\n get mode(): 'modal' | 'inline' {\n return this._parsed.mode;\n }\n set mode(value: 'modal' | 'inline') {\n this.setAttribute('mode', value);\n }\n\n get tab(): 'register' | 'login' {\n return this._parsed.tab;\n }\n set tab(value: 'register' | 'login') {\n this.setAttribute('tab', value);\n }\n\n get tabLabels(): string {\n return `${this._parsed.tabLabels.register},${this._parsed.tabLabels.login}`;\n }\n set tabLabels(value: string | undefined) {\n if (value == null || value === '') this.removeAttribute('tab-labels');\n else this.setAttribute('tab-labels', value);\n }\n\n get theme(): 'light' | 'dark' {\n return this._parsed.theme;\n }\n set theme(value: 'light' | 'dark') {\n this.setAttribute('theme', value);\n }\n\n get sessionId(): string | null {\n return this._parsed.sessionId;\n }\n set sessionId(value: string | null) {\n if (value == null) this.removeAttribute('session-id');\n else this.setAttribute('session-id', value);\n }\n\n get onboardingUrl(): string | null {\n return this._parsed.onboardingUrl;\n }\n set onboardingUrl(value: string | null) {\n if (value == null) this.removeAttribute('onboarding-url');\n else this.setAttribute('onboarding-url', value);\n }\n\n get isMobileOverride(): boolean | null {\n return this._parsed.isMobileOverride;\n }\n set isMobileOverride(value: boolean | null) {\n if (value == null) this.removeAttribute('is-mobile-override');\n else this.setAttribute('is-mobile-override', value ? 'true' : 'false');\n }\n\n get fallbackType(): 'email' | 'qr' | undefined {\n return this._parsed.fallbackType;\n }\n set fallbackType(value: 'email' | 'qr' | undefined) {\n if (value == null) this.removeAttribute('fallback-type');\n else this.setAttribute('fallback-type', value);\n }\n\n get appId(): string {\n return this._parsed.appId;\n }\n set appId(value: string) {\n this.setAttribute('app-id', value ?? '');\n }\n\n get publishableKey(): string {\n return this._parsed.publishableKey;\n }\n set publishableKey(value: string) {\n this.setAttribute('publishable-key', value ?? '');\n }\n\n get appName(): string | null {\n return this._parsed.appName;\n }\n set appName(value: string | null) {\n if (value == null) this.removeAttribute('app-name');\n else this.setAttribute('app-name', value);\n }\n\n get dialogTitle(): string | null {\n return this._parsed.dialogTitle;\n }\n set dialogTitle(value: string | null) {\n if (value == null) this.removeAttribute('dialog-title');\n else this.setAttribute('dialog-title', value);\n }\n\n get dialogDescription(): string | null {\n return this._parsed.dialogDescription;\n }\n set dialogDescription(value: string | null) {\n if (value == null) this.removeAttribute('dialog-description');\n else this.setAttribute('dialog-description', value);\n }\n\n get externalUserId(): string | null {\n return this._parsed.externalUserId;\n }\n set externalUserId(value: string | null) {\n if (value == null) this.removeAttribute('external-user-id');\n else this.setAttribute('external-user-id', value);\n }\n\n /**\n * Reset override: transitions to IDLE, clears ceremony and emits `mellon:cancelled` if was AUTHENTICATING.\n * Also emits `mellon:close` with the reason for the current state (success | cancel | error | user).\n * Host must call `reset()` before reopening if the WC stays in the DOM for a clean state.\n */\n override disconnectedCallback(): void {\n this._unregisterInteractions?.();\n this._unregisterInteractions = null;\n this.removeEventListener('keydown', this._boundEscapeKeydown, true);\n super.disconnectedCallback();\n }\n\n override reset(): void {\n this._transitionToIdle();\n }\n\n protected getTabKind(): TabKind {\n return this._parsed.tab;\n }\n\n protected getCoreAuthOptions(): { externalUserId?: string | null } {\n const externalUserId = this._resolveExternalUserId();\n return externalUserId ? { externalUserId } : {};\n }\n\n /** Single path: explicit attr > generated UUID for register > none. No special-case branches in getCoreAuthOptions. */\n private _resolveExternalUserId(): string | null {\n const explicit = this._parsed.externalUserId?.trim();\n if (explicit) return explicit;\n if (this.getTabKind() !== 'register') return null;\n this._generatedExternalUserId ??=\n typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : null;\n return this._generatedExternalUserId;\n }\n\n /** Passkey register is always allowed (external user id optional; SDK uses UUID when not set). */\n protected canStartAuth(): boolean {\n return true;\n }\n\n protected getEnvEvalParams(): Omit<RunEnvEvalParams, 'envStatusPort' | 'currentState'> {\n return {\n mode: tabToUIMode(this._parsed.tab),\n isMobileOverride: this._parsed.isMobileOverride ?? undefined,\n fallbackType: this._parsed.fallbackType,\n };\n }\n\n protected getCoreConfig(): { appId: string; publishableKey: string } | null {\n if (!this._parsed.appId || !this._parsed.publishableKey) return null;\n return { appId: this._parsed.appId, publishableKey: this._parsed.publishableKey };\n }\n\n protected getFallbackDetail(): MellonFallbackDetail {\n return { operation: this._parsed.tab };\n }\n\n /** Reflects open/mode in DOM (wrapper/overlay hidden). Syncs focus trap: activate when open, deactivate restores focus on close. */\n private _applyModalVisibility(): void {\n if (!this.shadowRoot) return;\n const wrapper = this.shadowRoot.querySelector<HTMLElement>(MODAL_SELECTORS.wrapper);\n if (wrapper) wrapper.hidden = !this._parsed.open;\n const overlay = this.shadowRoot.querySelector<HTMLElement>(MODAL_SELECTORS.overlay);\n if (overlay) overlay.hidden = this._parsed.mode !== 'modal';\n const panel = this.shadowRoot.querySelector<HTMLElement>(MODAL_SELECTORS.panel);\n if (panel) panel.setAttribute('aria-hidden', String(!this._parsed.open));\n\n if (this._parsed.open && wrapper) {\n if (!this._focusTrap) this._focusTrap = createFocusTrap(wrapper);\n this._focusTrap.activate();\n } else {\n this._focusTrap?.deactivate();\n }\n }\n\n protected _render(): void {\n if (!this.shadowRoot) return;\n ensureModalStructure(this.shadowRoot, this._parsed);\n this._applyModalVisibility();\n const vm = buildAuthModalViewModel(this.currentState, this._parsed, {\n registerSessionReady: this._parsed.tab === 'register' ? this.canStartAuth() : undefined,\n primaryButtonLabel: MODAL_PASSKEY_BUTTON_LABEL,\n primaryButtonAriaLabel: MODAL_PASSKEY_ARIA_LABEL,\n });\n const surface: IRenderSurface = { shadowRoot: this.shadowRoot };\n renderAuthModal(surface, vm);\n }\n}\n","/**\n * Web Component <trymellon-auth>. Shadow DOM open + attributes + render by state.\n * Option A (default): action=open-modal without trigger-only → emits mellon:open-request and shows internal modal.\n * Option B (escape hatch): trigger-only=\"true\" → only emits mellon:open-request; host mounts <trymellon-auth-modal> separately.\n */\nimport type { TabKind } from '../domain/types';\nimport type { RunEnvEvalParams } from '../application/evaluate-env.use-case';\nimport { authUiApplicationService } from '../application/auth-ui.application-service';\nimport { parseAttributesFromElement } from '../adapters/attributes/inline.adapter';\nimport type { ParsedAttributes } from '../adapters/attributes/inline.adapter';\nimport { DEFAULT_PARSED_ATTRIBUTES } from '../domain/contracts/constants';\nimport { buildAuthButtonViewModel } from '../domain/auth-viewmodels';\nimport { renderAuthButton } from '../adapters/render/auth.adapter';\nimport { registerAuthButtonInteractions } from '../adapters/interactions/dom.adapter';\nimport type { IRenderSurface } from '../ports/render.port';\nimport {\n createConstructableStylesheet,\n getStylesFallback,\n} from '../adapters/render/styles.adapter';\nimport type { MellonFallbackDetail } from '../ports';\nimport { toCoreAuthOptions } from '../adapters/infra/core-factory.adapter';\nimport { MELLON_CLOSE, MELLON_SUCCESS } from '../adapters/infra/event-bridge.adapter';\nimport { AuthElementBase } from './auth-element-base';\nimport { TryMellonAuthModalElement } from './trymellon-auth-modal.element';\nimport { OBSERVED_ATTRIBUTES_AUTH } from './constants';\nimport { MELLON_OPEN_REQUEST } from './ui-events';\n\nexport class TryMellonAuthElement extends AuthElementBase {\n static get observedAttributes(): string[] {\n return [...OBSERVED_ATTRIBUTES_AUTH];\n }\n\n protected _parsed: ParsedAttributes = { ...DEFAULT_PARSED_ATTRIBUTES };\n private _internalModal: TryMellonAuthModalElement | null = null;\n /** Element that opened the modal; single source for focus restore on close. */\n private _focusRestoreTarget: Element | null = null;\n private _unregisterInteractions: (() => void) | null = null;\n\n private _onInternalModalClose = (): void => {\n if (this._internalModal) this._internalModal.open = false;\n this._restoreFocusToTrigger();\n };\n\n /** Re-dispatch modal success on this element so host can listen on <trymellon-auth> (modal is in body, events don't bubble here). */\n private _onInternalModalSuccess = (e: Event): void => {\n const ev = e as CustomEvent;\n this.dispatchEvent(\n new CustomEvent(MELLON_SUCCESS, {\n detail: ev.detail,\n bubbles: false,\n composed: true,\n })\n );\n };\n\n private _restoreFocusToTrigger(): void {\n const el = this._focusRestoreTarget;\n this._focusRestoreTarget = null;\n if (!el?.isConnected || typeof (el as HTMLElement).focus !== 'function') return;\n (el as HTMLElement).focus();\n }\n\n connectedCallback(): void {\n if (this.shadowRoot) {\n this._registerInteractions();\n if (this._core !== null && this._unsubscribeBridge === null) {\n this.attachCore(this._core);\n }\n this._syncInternalModalAttributes();\n this._ensureInternalModal();\n return;\n }\n const shadow = this.attachShadow({ mode: 'open' });\n\n const sheet = createConstructableStylesheet();\n if (sheet) {\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const styleEl = document.createElement('style');\n styleEl.textContent = getStylesFallback();\n shadow.appendChild(styleEl);\n }\n\n this._parsed = parseAttributesFromElement(this);\n this._syncThemeAttribute();\n this._registerInteractions();\n this._render();\n this._reconcileCoreFromConfig();\n this._ensureInternalModal();\n }\n\n private _registerInteractions(): void {\n if (!this.shadowRoot) return;\n this._unregisterInteractions?.();\n this._unregisterInteractions = registerAuthButtonInteractions(this.shadowRoot, {\n onPrimaryClick: () => this._onPrimaryClick(),\n onFallbackClick: (type?: 'email' | 'qr') => this.dispatchFallback(type),\n });\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, _newValue: string | null): void {\n if (!this.shadowRoot) return;\n const prevMode = this._parsed.mode;\n this._parsed = parseAttributesFromElement(this);\n if (name === 'button-variant' || name === 'theme') {\n this.invalidateRender();\n }\n if (name === 'app-id' || name === 'publishable-key') {\n this._reconcileCoreFromConfig();\n }\n if (name === 'mode' && (this._parsed.mode === 'register' || this._parsed.mode === 'login')) {\n const tab = this._parsed.mode;\n if (prevMode !== tab) {\n this._emitCancelledIfAuthenticating();\n this.setState(authUiApplicationService.tabChange(this.currentState, tab));\n }\n }\n this._syncThemeAttribute();\n this.scheduleRenderIfNeeded();\n this._syncInternalModalAttributes();\n this._ensureInternalModal();\n }\n\n private _onPrimaryClick(): void {\n if (this._parsed.action === 'open-modal') {\n this._focusRestoreTarget =\n document.activeElement instanceof Element ? document.activeElement : null;\n this.dispatchEvent(\n new CustomEvent(MELLON_OPEN_REQUEST, { detail: {}, bubbles: true, composed: true })\n );\n if (!this._parsed.triggerOnly && this._internalModal) this._internalModal.open = true;\n return;\n }\n this.startAuthFromClick();\n }\n\n protected getTabKind(): TabKind {\n return this._parsed.mode === 'auto' ? 'login' : this._parsed.mode;\n }\n\n protected getCoreAuthOptions(): { externalUserId?: string | null } {\n return toCoreAuthOptions(this._parsed.externalUserId);\n }\n\n protected canStartAuth(): boolean {\n return true;\n }\n\n protected getEnvEvalParams(): Omit<RunEnvEvalParams, 'envStatusPort' | 'currentState'> {\n return { mode: this._parsed.mode };\n }\n\n protected getCoreConfig(): { appId: string; publishableKey: string } | null {\n if (!this._parsed.appId || !this._parsed.publishableKey) return null;\n return { appId: this._parsed.appId, publishableKey: this._parsed.publishableKey };\n }\n\n protected getFallbackDetail(): MellonFallbackDetail {\n const operation =\n this._parsed.mode === 'login' || this._parsed.mode === 'register'\n ? this._parsed.mode\n : undefined;\n return operation !== undefined ? { operation } : {};\n }\n\n protected _render(): void {\n if (!this.shadowRoot) return;\n const vm = buildAuthButtonViewModel(this.currentState, this._parsed, {\n registerSessionReady: this._parsed.mode === 'register' ? this.canStartAuth() : undefined,\n primaryButtonLabel: this._parsed.buttonLabel ?? undefined,\n primaryButtonAriaLabel: this._parsed.buttonAriaLabel ?? undefined,\n });\n const surface: IRenderSurface = { shadowRoot: this.shadowRoot };\n renderAuthButton(surface, vm);\n }\n\n private _syncThemeAttribute(): void {\n if (this.getAttribute('theme') !== this._parsed.theme) {\n this.setAttribute('theme', this._parsed.theme);\n }\n }\n\n private _syncInternalModalAttributes(): void {\n if (!this._internalModal) return;\n this._internalModal.setAttribute('app-id', this._parsed.appId ?? '');\n this._internalModal.setAttribute('publishable-key', this._parsed.publishableKey ?? '');\n this._internalModal.setAttribute('theme', this._parsed.theme);\n const tab = this._parsed.mode === 'auto' ? 'login' : this._parsed.mode;\n this._internalModal.setAttribute('tab', tab);\n /** Opaque panel (avoids transparent look when host CSS vars don't reach body-portaled modal). */\n this._internalModal.setAttribute('modal-variant', 'minimal');\n }\n\n private _ensureInternalModal(): void {\n if (this._parsed.action !== 'open-modal' || !this.shadowRoot) return;\n if (this._parsed.triggerOnly) {\n if (this._internalModal?.isConnected) {\n this._internalModal.removeEventListener(MELLON_CLOSE, this._onInternalModalClose);\n this._internalModal.remove();\n this._internalModal = null;\n }\n return;\n }\n if (this._internalModal?.isConnected) {\n this._syncInternalModalAttributes();\n return;\n }\n const modal = document.createElement('trymellon-auth-modal') as TryMellonAuthModalElement;\n this._internalModal = modal;\n this._syncInternalModalAttributes();\n modal.addEventListener(MELLON_CLOSE, this._onInternalModalClose);\n modal.addEventListener(MELLON_SUCCESS, this._onInternalModalSuccess);\n // Portal to body so overlay covers viewport; ancestors with transform/filter/backdrop-filter\n // would otherwise create a containing block and trap position:fixed (modal off to the side).\n if (typeof document !== 'undefined' && document.body) {\n document.body.appendChild(modal);\n } else {\n this.shadowRoot.appendChild(modal);\n }\n }\n\n override disconnectedCallback(): void {\n this._unregisterInteractions?.();\n this._unregisterInteractions = null;\n if (this._internalModal?.isConnected) {\n this._internalModal.removeEventListener(MELLON_CLOSE, this._onInternalModalClose);\n this._internalModal.removeEventListener(MELLON_SUCCESS, this._onInternalModalSuccess);\n this._internalModal.remove();\n this._internalModal = null;\n }\n super.disconnectedCallback();\n }\n}\n","/** @trymellon/js/ui — Web Component entry. */\nimport { TryMellonAuthElement } from './presentation/trymellon-auth.element';\nimport { TryMellonAuthModalElement } from './presentation/trymellon-auth-modal.element';\n\nexport const UI_VERSION = '0.1.0';\n/** Canonical tag: button + internal modal (Option A) or trigger only (Option B with trigger-only). */\nexport const TRYMELLON_AUTH_TAG = 'trymellon-auth';\n/** Modal tag; used internally by <trymellon-auth> (Option A) or by host (Option B). */\nexport const TRYMELLON_AUTH_MODAL_TAG = 'trymellon-auth-modal';\n\nif (typeof customElements !== 'undefined' && !customElements.get(TRYMELLON_AUTH_TAG)) {\n customElements.define(TRYMELLON_AUTH_TAG, TryMellonAuthElement);\n}\nif (typeof customElements !== 'undefined' && !customElements.get(TRYMELLON_AUTH_MODAL_TAG)) {\n customElements.define(TRYMELLON_AUTH_MODAL_TAG, TryMellonAuthModalElement);\n}\n\nexport { TryMellonAuthElement, TryMellonAuthModalElement };\nexport { getNextState, INITIAL_UI_STATE } from './domain';\nexport {\n BASE_STYLES,\n createConstructableStylesheet,\n getStylesFallback,\n} from './adapters/render/styles.adapter';\nexport type { UIState, FSMEvent, EnvResolvedPayload, UIMode, TabKind } from './domain';\nexport type { ParsedAttributes, ThemeKind } from './adapters/attributes/inline.adapter';\nexport type { RenderOptions } from './ports';\nexport {\n eventBridgeAdapter,\n MELLON_START,\n MELLON_CANCELLED,\n MELLON_FALLBACK,\n MELLON_TAB_CHANGE,\n MELLON_OPEN,\n MELLON_OPEN_REQUEST,\n MELLON_CLOSE,\n MELLON_SUCCESS,\n MELLON_ERROR,\n} from './adapters/infra/event-bridge.adapter';\nexport type {\n CoreWithEvents,\n CoreEventsPort,\n MellonSuccessDetail,\n MellonErrorDetail,\n MellonOperationDetail,\n MellonFallbackDetail,\n MellonOpenDetail,\n MellonCloseDetail,\n} from './ports';\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqXhC,KAAK,EAGA,SAASC,IAAiC,CAC/C,OAAON,GAAc;AAAA,EAAOK,EAC9B,CAGO,SAASE,IAA2D,CACzE,GAAI,CAACN,GAA8B,OAAO,KAC1C,GAAI,CACF,IAAME,EAAQ,IAAI,cAClB,OAAAA,EAAM,YAAYH,GAAc;AAAA,EAAOK,EAAkB,EAClDF,CACT,MAAQ,CACN,OAAO,IACT,CACF,CC7hBO,IAAMK,EAASC,IAAgC,CAAE,GAAI,GAAM,MAAAA,CAAM,GAC3DC,EAAUC,IAAgC,CAAE,GAAI,GAAO,MAAAA,CAAM,GCUnE,IAAMC,GAAN,MAAMC,UAAuB,KAAM,CAC/B,KACA,QACA,iBAAmB,GAE5B,YAAYC,EAA0BC,EAAiBC,EAAmB,CACxE,MAAMD,CAAO,EACb,KAAK,KAAO,iBACZ,KAAK,KAAOD,EACZ,KAAK,QAAUE,EAEX,MAAM,mBACR,MAAM,kBAAkB,KAAMH,CAAc,CAEhD,CACF,EAEMI,GAAuD,CAC3D,cAAe,gDACf,eAAgB,+BAChB,kBAAmB,oBACnB,gBAAiB,sBACjB,gBAAiB,yBACjB,iBAAkB,4BAClB,QAAS,sBACT,QAAS,wBACT,YAAa,uCACb,mBAAoB,8EACpB,cAAe,2BACjB,EAEO,SAASC,EACdJ,EACAC,EACAC,EACgB,CAChB,OAAO,IAAIJ,GAAeE,EAAMC,GAAWE,GAAiBH,CAAI,EAAGE,CAAO,CAC5E,CAEO,SAASG,GAAiBC,EAAyC,CACxE,OACEA,aAAiBR,IAChB,OAAOQ,GAAU,UAChBA,IAAU,MACV,qBAAsBA,GACrBA,EAAyB,mBAAqB,EAErD,CAEO,SAASC,IAA0C,CACxD,OAAOH,EAAY,eAAe,CACpC,CAiBO,SAASI,EAA2BC,EAAeC,EAAgC,CACxF,OAAOC,EAAY,mBAAoB,qBAAqBF,CAAK,MAAMC,CAAM,GAAI,CAC/E,MAAAD,EACA,OAAAC,CACF,CAAC,CACH,CAEO,SAASE,GAAsBC,EAA6C,CACjF,OAAOF,EAAY,gBAAiB,aAAaE,CAAS,cAAe,CAAE,UAAAA,CAAU,CAAC,CACxF,CAEO,SAASC,GAAoBC,EAA2C,CAC7E,OAAOJ,EACL,gBACA,aAAaI,IAAS,SAAW,WAAa,UAAU,aACxD,CAAE,KAAAA,CAAK,CACT,CACF,CAQO,SAASC,GAAYC,EAAaC,EAAyB,CAChE,GAAI,CACF,IAAMC,EAAS,IAAI,IAAIF,CAAG,EAC1B,GAAIE,EAAO,WAAa,UAAYA,EAAO,WAAa,QACtD,MAAMC,EAA2BF,EAAW,iCAAiC,CAEjF,OAASG,EAAO,CACd,MAAIC,GAAiBD,CAAK,EAClBA,EAEFD,EAA2BF,EAAW,qBAAqB,CACnE,CACF,CAEO,SAASK,EAAcC,EAAeN,EAAmBO,EAAaC,EAAmB,CAC9F,GAAI,CAAC,OAAO,SAASF,CAAK,EACxB,MAAMJ,EAA2BF,EAAW,yBAAyB,EAEvE,GAAIM,EAAQC,GAAOD,EAAQE,EACzB,MAAMN,EAA2BF,EAAW,mBAAmBO,CAAG,QAAQC,CAAG,EAAE,CAEnF,CAEO,SAASC,GAAkBC,EAAWV,EAAyB,CACpE,GAAI,OAAOU,GAAM,UAAYA,EAAE,SAAW,EACxC,MAAMR,EAA2BF,EAAW,4BAA4B,EAE1E,GAAI,CAAC,mBAAmB,KAAKU,CAAC,EAC5B,MAAMR,EAA2BF,EAAW,kCAAkC,CAElF,CAEA,IAAMW,GAA8D,CAClE,gBAAiB,iBACjB,WAAY,UACZ,kBAAmB,gBACnB,cAAe,gBACf,kBAAmB,gBACnB,aAAc,eAChB,EAOO,SAASC,GAA+BC,EAAyC,CACtF,GAAI,OAAOA,GAAgB,SAAU,MAAO,gBAC5C,IAAMC,EAAaD,EAAY,YAAY,EAAE,KAAK,EAUlD,MATgD,CAC9C,mBAAoB,qBACpB,gBAAiB,kBACjB,aAAc,kBACd,iBAAkB,mBAClB,iBAAkB,mBAClB,eAAgB,kBAChB,kBAAmB,mBACrB,EACWC,CAAU,GAAK,eAC5B,CAEO,SAASC,EAAiBZ,EAAgC,CAC/D,GAAIA,aAAiB,aAAc,CACjC,IAAMa,EAAOb,EAAM,KACbc,EAAUd,EAAM,SAAW,4BAC3Be,EAAYP,GAAwBK,CAAI,GAAK,gBACnD,OAAOG,EAAYD,EAAWD,EAAS,CAAE,cAAed,CAAM,CAAC,CACjE,CAEA,OAAIA,aAAiB,MACZgB,EAAY,gBAAiBhB,EAAM,QAAS,CAAE,cAAeA,CAAM,CAAC,EAGtEgB,EAAY,gBAAiB,4BAA6B,CAC/D,cAAehB,CACjB,CAAC,CACH,CCnLO,SAASiB,EAASC,EAAkD,CACzE,OAAO,OAAOA,GAAU,UAAYA,IAAU,MAAQ,CAAC,MAAM,QAAQA,CAAK,CAC5E,CAEO,SAASC,EAASD,EAAiC,CACxD,OAAO,OAAOA,GAAU,QAC1B,CAEO,SAASE,EAASF,EAAiC,CACxD,OAAO,OAAOA,GAAU,UAAY,OAAO,SAASA,CAAK,CAC3D,CAEO,SAASG,GAAUH,EAAkC,CAC1D,OAAO,OAAOA,GAAU,SAC1B,CAEO,SAASI,EAAQJ,EAAoC,CAC1D,OAAO,MAAM,QAAQA,CAAK,CAC5B,CAEO,SAASK,EACdC,EACAC,EAC+B,CAC/B,OAAOC,EACLC,EAAY,gBAAiBH,EAAS,CACpC,GAAGC,EACH,aAAcA,GAAS,YACzB,CAAC,CACH,CACF,CAEO,SAASG,EAASC,EAA8BC,EAAsB,CAC3E,OAAOD,EAAIC,CAAG,CAChB,CASO,SAASC,GAAoBC,EAAaC,EAA6C,CAC5F,MAAI,CAACC,EAASF,CAAE,GAAK,CAACG,EAASH,EAAG,IAAI,GAAK,CAACG,EAASH,EAAG,EAAE,EACjDI,EAAgB,mEAAoE,CACzF,aAAcH,CAChB,CAAC,EAEII,EAAG,EAAI,CAChB,CAEO,SAASC,GAAsBC,EAAeN,EAA6C,CAChG,MACE,CAACC,EAASK,CAAI,GACd,CAACJ,EAASI,EAAK,EAAE,GACjB,CAACJ,EAASI,EAAK,IAAI,GACnB,CAACJ,EAASI,EAAK,WAAW,EAEnBH,EACL,+EACA,CAAE,aAAcH,CAAK,CACvB,EAEKI,EAAG,EAAI,CAChB,CAEO,SAASG,GACdC,EACAR,EAC8B,CAC9B,GAAI,CAACS,EAAQD,CAAM,EACjB,OAAOL,EAAgB,iEAAkE,CACvF,aAAcH,CAChB,CAAC,EAEH,QAAWU,KAAQF,EACjB,GAAI,CAACP,EAASS,CAAI,GAAKA,EAAK,OAAS,cAAgB,CAACC,EAASD,EAAK,GAAG,EACrE,OAAOP,EACL,sEACA,CAAE,aAAcH,CAAK,CACvB,EAGJ,OAAOI,EAAG,EAAI,CAChB,CAEO,SAASQ,GACdN,EACAN,EAIA,CACA,GAAI,CAACC,EAASK,CAAI,EAChB,OAAOH,EAAgB,4CAA6C,CAClE,MAAO,OACP,aAAcH,CAChB,CAAC,EAGH,IAAMa,EAASC,EAASR,EAAM,SAAS,EACjCS,EAAiBD,EAASR,EAAM,kBAAkB,EACxD,GAAI,CAACJ,EAASW,CAAM,GAAK,CAACX,EAASa,CAAc,EAC/C,OAAOZ,EACL,4EACA,CAAE,aAAcH,CAAK,CACvB,EAGF,IAAMgB,EAAQV,EAAK,MACbW,EAAWX,EAAK,SACtB,OAAIU,IAAU,QAAa,CAACd,EAASc,CAAK,EACjCb,EAAgB,kDAAmD,CACxE,aAAcH,CAChB,CAAC,EAECiB,IAAa,SAAc,OAAOA,GAAa,UAAYA,IAAa,MACnEd,EAAgB,qDAAsD,CAC3E,aAAcH,CAChB,CAAC,EAGII,EAAG,CACR,QAASS,EACT,iBAAkBE,EAClB,GAAIC,IAAU,QAAa,CAAE,MAAAA,CAAM,EACnC,GAAIC,IAAa,QAAa,CAAE,SAAUA,CAAoC,CAChF,CAAC,CACH,CC7GO,SAASC,GACdC,EAC+C,CAC/C,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAaC,EAASJ,EAAM,YAAY,EAC9C,GAAI,CAACK,EAASF,CAAU,EACtB,OAAOD,EAAgB,kDAAmD,CACxE,MAAO,aACP,aAAcF,CAChB,CAAC,EAGH,IAAMM,EAAYF,EAASJ,EAAM,WAAW,EAC5C,GAAI,CAACC,EAASK,CAAS,EACrB,OAAOJ,EAAgB,iDAAkD,CACvE,MAAO,YACP,aAAcF,CAChB,CAAC,EAGH,IAAMO,EAAWC,GAAoBJ,EAASE,EAAW,IAAI,EAAGN,CAAI,EACpE,GAAI,CAACO,EAAS,GAAI,OAAOA,EAEzB,IAAME,EAAaC,GAAsBN,EAASE,EAAW,MAAM,EAAGN,CAAI,EAC1E,GAAI,CAACS,EAAW,GAAI,OAAOA,EAE3B,IAAME,EAAeP,EAASE,EAAW,WAAW,EACpD,GAAI,CAACD,EAASM,CAAY,EACxB,OAAOT,EAAgB,2DAA4D,CACjF,aAAcF,CAChB,CAAC,EAGH,IAAMY,EAAyBC,GAC7BT,EAASE,EAAW,kBAAkB,EACtCN,CACF,EACA,GAAI,CAACY,EAAuB,GAAI,OAAOA,EAEvC,IAAME,EAAUR,EAAU,QAC1B,GAAIQ,IAAY,QAAa,CAACC,EAASD,CAAO,EAC5C,OAAOZ,EAAgB,yDAA0D,CAC/E,aAAcF,CAChB,CAAC,EAGH,IAAMgB,EAAqBV,EAAU,mBACrC,GAAIU,IAAuB,OAAW,CACpC,GAAI,CAACC,EAAQD,CAAkB,EAC7B,OAAOd,EAAgB,yDAA0D,CAC/E,aAAcF,CAChB,CAAC,EAEH,QAAWkB,KAAKF,EACd,GACE,CAACf,EAASiB,CAAC,GACVA,EAA8B,OAAS,cACxC,CAACb,EAAUa,EAA8B,EAAE,EAE3C,OAAOhB,EACL,uEACA,CACE,aAAcF,CAChB,CACF,CAGN,CAEA,IAAMmB,EAAyBb,EAAU,uBACzC,OAAIa,IAA2B,QAAa,CAAClB,EAASkB,CAAsB,EACnEjB,EAAgB,8DAA+D,CACpF,aAAcF,CAChB,CAAC,EAGIoB,EAAG,CACR,WAAAjB,EACA,UAAW,CACT,GAAIG,EAAU,GACd,KAAMA,EAAU,KAChB,UAAWK,EACX,iBACEL,EAAU,iBACZ,GAAIQ,IAAY,QAAa,CAAE,QAAAA,CAAQ,EACvC,GAAIE,IAAuB,QAAa,CACtC,mBACEA,CACJ,EACA,GAAIG,IAA2B,QAAa,CAC1C,uBACEA,CACJ,CACF,CACF,CAAC,CACH,CAEO,SAASE,GACdrB,EAC2C,CAC3C,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAaC,EAASJ,EAAM,YAAY,EAC9C,GAAI,CAACK,EAASF,CAAU,EACtB,OAAOD,EAAgB,kDAAmD,CACxE,MAAO,aACP,aAAcF,CAChB,CAAC,EAGH,IAAMM,EAAYF,EAASJ,EAAM,WAAW,EAC5C,GAAI,CAACC,EAASK,CAAS,EACrB,OAAOJ,EAAgB,iDAAkD,CACvE,MAAO,YACP,aAAcF,CAChB,CAAC,EAGH,IAAMsB,EAAKlB,EAASE,EAAW,WAAW,EACpCiB,EAAOnB,EAASE,EAAW,MAAM,EACjCkB,EAAmBlB,EAAU,iBACnC,GAAI,CAACD,EAASiB,CAAE,EACd,OAAOpB,EAAgB,2DAA4D,CACjF,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACK,EAASkB,CAAI,EAChB,OAAOrB,EAAgB,sDAAuD,CAC5E,aAAcF,CAChB,CAAC,EAEH,GAAIwB,IAAqB,QAAa,CAACP,EAAQO,CAAgB,EAC7D,OAAOtB,EAAgB,uDAAwD,CAC7E,aAAcF,CAChB,CAAC,EAEH,GAAIwB,GACF,QAAWN,KAAKM,EACd,GACE,CAACvB,EAASiB,CAAC,GACVA,EAA8B,OAAS,cACxC,CAACb,EAAUa,EAA8B,EAAE,EAE3C,OAAOhB,EACL,qEACA,CACE,aAAcF,CAChB,CACF,EAKN,IAAMc,EAAUR,EAAU,QAC1B,GAAIQ,IAAY,QAAa,CAACC,EAASD,CAAO,EAC5C,OAAOZ,EAAgB,yDAA0D,CAC/E,aAAcF,CAChB,CAAC,EAGH,IAAMyB,EAAmBnB,EAAU,iBACnC,OACEmB,IAAqB,QACrB,CAAC,CAAC,WAAY,YAAa,aAAa,EAAE,SAAS,OAAOA,CAAgB,CAAC,EAEpEvB,EACL,gFACA,CACE,aAAcF,CAChB,CACF,EAGKoB,EAAG,CACR,WAAAjB,EACA,UAAW,CACT,UAAWmB,EACX,KAAAC,EACA,iBACGC,GAA2E,CAAC,EAC/E,GAAIV,IAAY,QAAa,CAAE,QAAAA,CAAQ,EACvC,GAAIW,IAAqB,QAAa,CACpC,iBAAkBA,CACpB,CACF,CACF,CAAC,CACH,CAEO,SAASC,GACd1B,EACgD,CAChD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAM2B,EAAgBvB,EAASJ,EAAM,eAAe,EAC9C4B,EAASxB,EAASJ,EAAM,QAAQ,EAChC6B,EAAgBzB,EAASJ,EAAM,eAAe,EAC9C8B,EAAO1B,EAASJ,EAAM,MAAM,EAElC,GAAI,CAACK,EAASsB,CAAa,EACzB,OAAOzB,EAAgB,qDAAsD,CAC3E,MAAO,gBACP,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACK,EAASuB,CAAM,EAClB,OAAO1B,EAAgB,8CAA+C,CACpE,MAAO,SACP,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACK,EAASwB,CAAa,EACzB,OAAO3B,EAAgB,qDAAsD,CAC3E,MAAO,gBACP,aAAcF,CAChB,CAAC,EAEH,IAAMS,EAAasB,GAAmBD,EAAM9B,CAAI,EAChD,GAAI,CAACS,EAAW,GAAI,OAAOP,EAAgBO,EAAW,MAAM,QAAS,CAAE,aAAcT,CAAK,CAAC,EAE3F,IAAMgC,EAAehC,EAAK,aAC1B,OAAIgC,IAAiB,QAAa,CAAC3B,EAAS2B,CAAY,EAC/C9B,EAAgB,oDAAqD,CAC1E,aAAcF,CAChB,CAAC,EAGIoB,EAAG,CACR,cAAAO,EACA,OAAAC,EACA,cAAAC,EACA,KAAMpB,EAAW,MACjB,GAAIuB,IAAiB,QAAa,CAAE,aAAAA,CAAa,CACnD,CAAC,CACH,CAEO,SAASC,GACdjC,EAC4C,CAC5C,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMkC,EAAgB9B,EAASJ,EAAM,eAAe,EAC9C6B,EAAgBzB,EAASJ,EAAM,eAAe,EAC9C8B,EAAO1B,EAASJ,EAAM,MAAM,EAC5BmC,EAAU/B,EAASJ,EAAM,SAAS,EAExC,GAAI,CAACoC,GAAUF,CAAa,EAC1B,OAAOhC,EAAgB,sDAAuD,CAC5E,MAAO,gBACP,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACK,EAASwB,CAAa,EACzB,OAAO3B,EAAgB,qDAAsD,CAC3E,MAAO,gBACP,aAAcF,CAChB,CAAC,EAEH,IAAMS,EAAasB,GAAmBD,EAAM9B,CAAI,EAChD,GAAI,CAACS,EAAW,GAAI,OAAOP,EAAgBO,EAAW,MAAM,QAAS,CAAE,aAAcT,CAAK,CAAC,EAE3F,GAAImC,IAAY,QAAa,CAAClC,EAASkC,CAAO,EAC5C,OAAOjC,EAAgB,+CAAgD,CACrE,aAAcF,CAChB,CAAC,EAGH,IAAMgC,EAAehC,EAAK,aAC1B,OAAIgC,IAAiB,QAAa,CAAC3B,EAAS2B,CAAY,EAC/C9B,EAAgB,oDAAqD,CAC1E,aAAcF,CAChB,CAAC,EAGIoB,EAAG,CACR,cAAAc,EACA,cAAAL,EACA,KAAMpB,EAAW,MACjB,QAAS0B,EACT,GAAIH,IAAiB,QAAa,CAAE,aAAAA,CAAa,CACnD,CAAC,CACH,CClTO,SAASK,GACdC,EACiD,CACjD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAQC,EAASJ,EAAM,OAAO,EAC9BK,EAAUD,EAASJ,EAAM,SAAS,EAClCM,EAAmBF,EAASJ,EAAM,kBAAkB,EACpDO,EAAYH,EAASJ,EAAM,WAAW,EACtCQ,EAASJ,EAASJ,EAAM,QAAQ,EAEtC,OAAKS,GAAUN,CAAK,EAMfO,EAASL,CAAO,EAMhBK,EAASJ,CAAgB,EAMzBI,EAASH,CAAS,EAMlBG,EAASF,CAAM,EAObG,EAAG,CACR,MAAAR,EACA,QAAAE,EACA,iBAAAC,EACA,UAAAC,EACA,OAAAC,CACF,CAAC,EAZQN,EAAgB,8CAA+C,CACpE,MAAO,SACP,aAAcF,CAChB,CAAC,EATME,EAAgB,iDAAkD,CACvE,MAAO,YACP,aAAcF,CAChB,CAAC,EATME,EAAgB,wDAAyD,CAC9E,MAAO,mBACP,aAAcF,CAChB,CAAC,EATME,EAAgB,+CAAgD,CACrE,MAAO,UACP,aAAcF,CAChB,CAAC,EATME,EAAgB,8CAA+C,CACpE,MAAO,QACP,aAAcF,CAChB,CAAC,CAkCL,CCpDO,SAASY,GACdC,EACwE,CACxE,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EACHH,EAAiC,eACjCA,EAAiC,aACpC,GAAI,CAACI,EAASD,CAAG,EACf,OAAOD,EAAgB,kEAAmE,CACxF,MAAO,gBACP,aAAcF,CAChB,CAAC,EAGH,IAAMK,EAAgBL,EAAiC,aACvD,OAAIK,IAAiB,QAAa,CAACD,EAASC,CAAY,EAC/CH,EAAgB,oDAAqD,CAC1E,aAAcF,CAChB,CAAC,EAGIM,EAAG,CACR,aAAcH,EACd,GAAIE,IAAiB,QAAa,CAAE,YAAaA,CAAa,CAChE,CAAC,CACH,CCpBA,IAAME,GAAsB,CAAC,kBAAmB,eAAgB,WAAW,EACrEC,GAA4B,CAAC,eAAgB,WAAW,EAEvD,SAASC,GACdC,EACiD,CACjD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAaC,EAASJ,EAAM,YAAY,EACxCK,EAAiBD,EAASJ,EAAM,gBAAgB,EAChDM,EAAaF,EAASJ,EAAM,YAAY,EAE9C,OAAKO,EAASJ,CAAU,EAMnBI,EAASF,CAAc,EAMvBG,EAASF,CAAU,EAOjBG,EAAG,CAAE,WAAAN,EAAY,eAAAE,EAAgB,WAAAC,CAAW,CAAC,EAN3CJ,EAAgB,kDAAmD,CACxE,MAAO,aACP,aAAcF,CAChB,CAAC,EATME,EAAgB,sDAAuD,CAC5E,MAAO,iBACP,aAAcF,CAChB,CAAC,EATME,EAAgB,kDAAmD,CACxE,MAAO,aACP,aAAcF,CAChB,CAAC,CAgBL,CAEO,SAASU,GACdV,EACkD,CAClD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMW,EAASP,EAASJ,EAAM,QAAQ,EAChCK,EAAiBD,EAASJ,EAAM,gBAAgB,EAChDM,EAAaF,EAASJ,EAAM,YAAY,EAE9C,MACE,CAACO,EAASI,CAAM,GAChB,CAACd,GAAoB,SAASc,CAA8C,EAErET,EACL,8EACA,CACE,MAAO,SACP,aAAcF,CAChB,CACF,EAEGO,EAASF,CAAc,EAKvBG,EAASF,CAAU,EAMjBG,EAAG,CACR,OAAQE,EACR,eAAAN,EACA,WAAAC,CACF,CAAC,EATQJ,EAAgB,kDAAmD,CACxE,aAAcF,CAChB,CAAC,EAPME,EAAgB,sDAAuD,CAC5E,aAAcF,CAChB,CAAC,CAaL,CAOO,SAASY,GACdZ,EACiE,CACjE,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAaC,EAASJ,EAAM,YAAY,EACxCW,EAASP,EAASJ,EAAM,QAAQ,EAChCK,EAAiBD,EAASJ,EAAM,gBAAgB,EAEtD,GAAI,CAACO,EAASJ,CAAU,EACtB,OAAOD,EAAgB,kDAAmD,CACxE,MAAO,aACP,aAAcF,CAChB,CAAC,EAEH,GAAIW,IAAW,kBACb,OAAOT,EAAgB,uDAAwD,CAC7E,MAAO,SACP,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACO,EAASF,CAAc,EAC1B,OAAOH,EAAgB,sDAAuD,CAC5E,aAAcF,CAChB,CAAC,EAGH,IAAMa,EAAYb,EAAK,UACnBc,EACJ,GAAID,IAAc,OAAW,CAC3B,IAAME,EAAWC,GAA4BH,CAAS,EACtD,GAAI,CAACE,EAAS,GAAI,OAAOA,EACzBD,EAAkBC,EAAS,KAC7B,CAEA,OAAON,EAAG,CACR,WAAAN,EACA,OAAQ,kBACR,eAAAE,EACA,GAAIS,IAAoB,QAAa,CAAE,UAAWA,CAAgB,CACpE,CAAC,CACH,CAEA,SAASE,GACPhB,EAC4D,CAC5D,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,iDAAkD,CACvE,aAAcF,CAChB,CAAC,EAGH,IAAMiB,EAAKb,EAASJ,EAAM,IAAI,EACxBkB,EAAOd,EAASJ,EAAM,MAAM,EAC5BmB,EAAef,EAASJ,EAAM,WAAW,EACzCoB,EAAmBhB,EAASJ,EAAM,kBAAkB,EAE1D,GACE,CAACC,EAASgB,CAAE,GACZ,CAACV,EAAUU,EAA+B,IAAI,GAC9C,CAACV,EAAUU,EAA+B,EAAE,EAE5C,OAAOf,EAAgB,2DAA4D,CACjF,aAAcF,CAChB,CAAC,EAEH,GACE,CAACC,EAASiB,CAAI,GACd,CAACX,EAAUW,EAAiC,EAAE,GAC9C,CAACX,EAAUW,EAAiC,IAAI,GAChD,CAACX,EAAUW,EAAiC,WAAW,EAEvD,OAAOhB,EAAgB,uEAAwE,CAC7F,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACO,EAASY,CAAY,EACxB,OAAOjB,EAAgB,2DAA4D,CACjF,aAAcF,CAChB,CAAC,EAEH,GAAI,CAACqB,EAAQD,CAAgB,EAC3B,OAAOlB,EAAgB,iEAAkE,CACvF,aAAcF,CAChB,CAAC,EAEH,QAAWsB,KAAQF,EACjB,GACE,CAACnB,EAASqB,CAAI,GACbA,EAAiC,OAAS,cAC3C,CAACd,EAAUc,EAAiC,GAAG,EAE/C,OAAOpB,EACL,sEACA,CACE,aAAcF,CAChB,CACF,EAIJ,OAAOS,EAAG,CACR,GAAIQ,EACJ,KAAMC,EACN,UAAWC,EACX,iBAAkBC,CACpB,CAAC,CACH,CAEO,SAASG,GACdvB,EAC2D,CAC3D,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAaC,EAASJ,EAAM,YAAY,EACxCW,EAASP,EAASJ,EAAM,QAAQ,EAChCwB,EAAUpB,EAASJ,EAAM,SAAS,EAClCyB,EAAYrB,EAASJ,EAAM,WAAW,EAE5C,OAAKO,EAASJ,CAAU,EAMtB,CAACI,EAASI,CAAM,GAChB,CAACb,GAA0B,SAASa,CAAoD,EAEjFT,EAAgB,8DAA+D,CACpF,aAAcF,CAChB,CAAC,EAEEO,EAASiB,CAAO,EAKhBjB,EAASkB,CAAS,EAMhBhB,EAAG,CACR,WAAAN,EACA,OAAQQ,EACR,QAAAa,EACA,UAAAC,CACF,CAAC,EAVQvB,EAAgB,iDAAkD,CACvE,aAAcF,CAChB,CAAC,EAPME,EAAgB,+CAAgD,CACrE,aAAcF,CAChB,CAAC,EAfME,EAAgB,kDAAmD,CACxE,aAAcF,CAChB,CAAC,CA2BL,CAEO,SAAS0B,GACd1B,EACoD,CACpD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAaC,EAASJ,EAAM,YAAY,EACxCW,EAASP,EAASJ,EAAM,QAAQ,EAChCwB,EAAUpB,EAASJ,EAAM,SAAS,EAClCyB,EAAYrB,EAASJ,EAAM,WAAW,EACtC2B,EAAgBvB,EAASJ,EAAM,eAAe,EAEpD,OAAKO,EAASJ,CAAU,EAKpBQ,IAAW,YACNT,EAAgB,iDAAkD,CACvE,aAAcF,CAChB,CAAC,EAEC,CAACO,EAASiB,CAAO,GAAK,CAACjB,EAASkB,CAAS,GAAK,CAAClB,EAASoB,CAAa,EAChEzB,EACL,0EACA,CAAE,aAAcF,CAAK,CACvB,EAGKS,EAAG,CACR,WAAAN,EACA,OAAQ,YACR,QAAAqB,EACA,UAAAC,EACA,cAAAE,CACF,CAAC,EAtBQzB,EAAgB,kDAAmD,CACxE,aAAcF,CAChB,CAAC,CAqBL,CChRO,SAAS4B,GAAkCC,EAA6C,CAC7F,OAA0BA,GAAS,KAC1BC,EAAG,MAAS,EAEjBC,EAASF,CAAI,GAAK,OAAO,KAAKA,CAAI,EAAE,SAAW,EAC1CC,EAAG,MAAS,EAEdE,EAAgB,kDAAmD,CACxE,aAAcH,CAChB,CAAC,CACH,CAEA,SAASI,GAAuBC,EAAgD,CAC9E,GAAI,CAACA,GAAQ,OAAOA,GAAS,SAAU,MAAO,GAC9C,IAAMC,EAAID,EACV,OACE,OAAOC,EAAE,WAAc,UACvBA,EAAE,IAAM,MACR,OAAOA,EAAE,IAAO,UAChBA,EAAE,MAAQ,MACV,OAAOA,EAAE,MAAS,UAClB,MAAM,QAASA,EAAqC,gBAAgB,CAExE,CAEA,SAASC,GAAsBF,EAAgD,CAC7E,GAAI,CAACA,GAAQ,OAAOA,GAAS,SAAU,MAAO,GAC9C,IAAMC,EAAID,EACV,OAAO,OAAOC,EAAE,WAAc,UAAY,OAAOA,EAAE,MAAS,QAC9D,CAOO,SAASE,GACdR,EAC+C,CAC/C,GAAI,CAACE,EAASF,CAAI,EAChB,OAAOG,EAAgB,wCAAyC,CAAE,aAAcH,CAAK,CAAC,EAGxF,IAAMS,EACJ,cAAeT,GAAQE,EAAUF,EAAgC,SAAS,EACrEA,EAAgD,UACjDA,EAEAU,EAAaD,EAAQ,WACrBE,EAASF,EAAQ,OACjBG,EAAaH,EAAQ,WACrBI,EAAgBJ,EAAQ,cAE9B,GACE,CAACK,EAASJ,CAAU,GACpB,CAACI,EAASH,CAAM,GAChB,CAACG,EAASF,CAAU,GACpB,CAACE,EAASD,CAAa,EAEvB,OAAOV,EAAgB,gDAAiD,CAAE,aAAcH,CAAK,CAAC,EAGhG,IAAMe,EAAgC,CACpC,WAAAL,EACA,OAAAC,EACA,WAAAC,EACA,cAAAC,CACF,EACA,OAAIJ,EAAQ,mBAAqB,QAAaK,EAASL,EAAQ,gBAAgB,IAC7EM,EAAO,iBAAmBN,EAAQ,kBAE7BR,EAAGc,CAAM,CAClB,CAMO,SAASC,GACdhB,EACiD,CACjD,GAAI,CAACE,EAASF,CAAI,EAChB,OAAOG,EAAgB,wCAAyC,CAAE,aAAcH,CAAK,CAAC,EAGxF,IAAMS,EACJ,cAAeT,GAAQE,EAAUF,EAAgC,SAAS,EACrEA,EAAgD,UACjDA,EAEAiB,EAASR,EAAQ,OACvB,GAAI,CAACK,EAASG,CAAM,GAAK,CAAC,CAAC,UAAW,gBAAiB,WAAW,EAAE,SAASA,CAAM,EACjF,OAAOd,EAAgB,uCAAwC,CAAE,aAAcH,CAAK,CAAC,EAGvF,IAAMkB,EAAUT,EAAQ,QAClBU,EAAgBV,EAAQ,cACxBW,EAAeX,EAAQ,aAE7B,OAAIS,IAAY,QAAa,CAACJ,EAASI,CAAO,EACrCf,EAAgB,8DAA+D,CACpF,aAAcH,CAChB,CAAC,EAECmB,IAAkB,QAAa,CAACL,EAASK,CAAa,EACjDhB,EAAgB,oEAAqE,CAC1F,aAAcH,CAChB,CAAC,EAECoB,IAAiB,QAAa,CAACN,EAASM,CAAY,EAC/CjB,EAAgB,mEAAoE,CACzF,aAAcH,CAChB,CAAC,EAGIC,EAAG,CACR,OAAQgB,EACR,QAASC,EACT,cAAeC,EACf,aAAcC,CAChB,CAAC,CACH,CAEO,SAASC,GACdrB,EACkD,CAClD,GAAI,CAACE,EAASF,CAAI,EAChB,OAAOG,EAAgB,wCAAyC,CAAE,aAAcH,CAAK,CAAC,EAGxF,IAAMsB,EAAUtB,EAAK,KACfuB,EACJD,IAAY,eAAiB,eAAsC,OAE/DE,EAAUxB,EAAK,QACrB,GAAI,CAACE,EAASsB,CAAO,EACnB,OAAOrB,EAAgB,6CAA8C,CAAE,aAAcH,CAAK,CAAC,EAG7F,IAAMyB,EAAqB,IACrBC,EAAmBC,GAAsB3B,EAAK,iBAAkByB,CAAkB,EAClFG,EAAmBD,GAAsB3B,EAAK,iBAAkByB,CAAkB,EACxF,GAAIC,IAAqB,IAASE,IAAqB,GACrD,OAAOzB,EACL,uFACA,CACE,aAAcH,CAChB,CACF,EAGF,IAAM6B,EAAkE,CAAC,EAIzE,OAHI,OAAOH,GAAqB,WAAUG,EAAM,iBAAmBH,GAC/D,OAAOE,GAAqB,WAAUC,EAAM,iBAAmBD,GAE/DL,IAAS,eACNnB,GAAuBoB,CAAO,EAM5BvB,EAAG,CACR,KAAM,eACN,QAAAuB,EACA,GAAGK,CACL,CAA6B,EATpB1B,EACL,6FACA,CAAE,aAAcH,CAAK,CACvB,EASCO,GAAsBiB,CAAO,EAK3BvB,EAAG,CAAE,KAAM,OAAQ,QAAAuB,EAAS,GAAGK,CAAM,CAA6B,EAJhE1B,EAAgB,kEAAmE,CACxF,aAAcH,CAChB,CAAC,CAGL,CAGA,SAAS2B,GAAsBG,EAAgBC,EAA+C,CAC5F,GAA2BD,GAAU,KAErC,OADI,OAAOA,GAAU,UACjBA,EAAM,OAASC,EAAkB,GAC9BD,CACT,CChMO,SAASE,GACdC,EACgD,CAChD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMG,EAAYC,EAASJ,EAAM,WAAW,EACtCK,EAAsBD,EAASJ,EAAM,qBAAqB,EAEhE,OAAKC,EAASE,CAAS,EAOlBG,EAASD,CAAmB,EAO1BE,EAAG,CACR,UAAWJ,EACX,oBAAAE,CACF,CAAC,EATQH,EAAgB,2DAA4D,CACjF,MAAO,sBACP,aAAcF,CAChB,CAAC,EAVME,EAAgB,iDAAkD,CACvE,MAAO,YACP,aAAcF,CAChB,CAAC,CAcL,CAEO,SAASQ,GACdR,EACkD,CAClD,GAAI,CAACC,EAASD,CAAI,EAChB,OAAOE,EAAgB,wCAAyC,CAAE,aAAcF,CAAK,CAAC,EAGxF,IAAMS,EAASL,EAASJ,EAAM,QAAQ,EAChCU,EAAgBN,EAASJ,EAAM,eAAe,EAC9CW,EAAOP,EAASJ,EAAM,MAAM,EAC5BY,EAAgBR,EAASJ,EAAM,eAAe,EAEpD,GAAI,CAACM,EAASG,CAAM,EAClB,OAAOP,EAAgB,8CAA+C,CACpE,MAAO,SACP,aAAcF,CAChB,CAAC,EAGH,GAAI,CAACM,EAASI,CAAa,EACzB,OAAOR,EAAgB,qDAAsD,CAC3E,MAAO,gBACP,aAAcF,CAChB,CAAC,EAGH,GAAI,CAACM,EAASM,CAAa,EACzB,OAAOV,EAAgB,qDAAsD,CAC3E,MAAO,gBACP,aAAcF,CAChB,CAAC,EAGH,GAAI,CAACC,EAASU,CAAI,EAChB,OAAOT,EAAgB,4CAA6C,CAClE,MAAO,OACP,aAAcF,CAChB,CAAC,EAGH,IAAMa,EAAUT,EAASO,EAAM,SAAS,EACxC,GAAI,CAACL,EAASO,CAAO,EACnB,OAAOX,EAAgB,oDAAqD,CAC1E,MAAO,eACP,aAAcF,CAChB,CAAC,EAIH,IAAMc,EADUd,EACa,aAC7B,GAAIc,IAAiB,QAAa,CAACR,EAASQ,CAAY,EACtD,OAAOZ,EAAgB,oDAAqD,CAC1E,MAAO,eACP,aAAcF,CAChB,CAAC,EAGH,IAAMe,EAAUJ,EAChB,OAAOJ,EAAG,CACR,OAAAE,EACA,cAAAC,EACA,cAAAE,EACA,KAAM,CACJ,QAAAC,EACA,iBAAkBP,EAASS,EAAQ,gBAAgB,EAAIA,EAAQ,iBAAmB,OAClF,MAAOT,EAASS,EAAQ,KAAK,EAAIA,EAAQ,MAAQ,OACjD,SAAUd,EAASc,EAAQ,QAAQ,EAC9BA,EAAQ,SACT,MACN,EACA,GAAID,IAAiB,QAAa,CAAE,aAAAA,CAAa,CACnD,CAAC,CACH,CC1DO,IAAME,GAAN,KAAgB,CACrB,YACmBC,EACAC,EACAC,EAAyC,CAAC,EAC3D,CAHiB,gBAAAF,EACA,aAAAC,EACA,oBAAAC,CAChB,CAEK,aAAaC,EAAwD,CAC3E,MAAO,CAAE,GAAG,KAAK,eAAgB,GAAGA,CAAM,CAC5C,CAEA,MAAc,KACZC,EACAC,EACAC,EACsC,CACtC,IAAMC,EAAM,GAAG,KAAK,OAAO,GAAGH,CAAI,GAC5BI,EAAS,MAAM,KAAK,WAAW,KAAcD,EAAKF,EAAM,KAAK,aAAa,CAAC,EAEjF,OAAKG,EAAO,GAILF,EAASE,EAAO,KAAK,EAHnBC,EAAID,EAAO,KAAK,CAI3B,CAEA,MAAc,IACZJ,EACAE,EACAI,EACsC,CACtC,IAAMH,EAAM,GAAG,KAAK,OAAO,GAAGH,CAAI,GAC5BI,EAAS,MAAM,KAAK,WAAW,IAAaD,EAAK,KAAK,aAAaG,CAAO,CAAC,EAEjF,OAAKF,EAAO,GAILF,EAASE,EAAO,KAAK,EAHnBC,EAAID,EAAO,KAAK,CAI3B,CAEA,MAAM,cACJG,EACwD,CACxD,OAAO,KAAK,KAAK,8BAA+BA,EAASC,EAA6B,CACxF,CAEA,MAAM,UAAUD,EAA+E,CAC7F,OAAO,KAAK,KAAK,0BAA2BA,EAASE,EAAyB,CAChF,CAEA,MAAM,eACJF,EACyD,CACzD,OAAO,KAAK,KAAK,+BAAgCA,EAASG,EAA8B,CAC1F,CAEA,MAAM,qBACJH,EACqD,CACrD,OAAO,KAAK,KAAK,2BAA4BA,EAASI,EAA0B,CAClF,CAEA,MAAM,gBACJC,EAC0D,CAC1D,OAAO,KAAK,IAAI,wBAAyBC,GAAiC,CACxE,cAAe,UAAUD,CAAY,EACvC,CAAC,CACH,CAEA,MAAM,mBAAmBE,EAGiB,CACxC,IAAMX,EAAM,GAAG,KAAK,OAAO,2BACrBC,EAAS,MAAM,KAAK,WAAW,KACnCD,EACA,CAAE,OAAQW,EAAQ,OAAQ,MAAOA,EAAQ,KAAM,EAC/C,KAAK,aAAa,CACpB,EACA,OAAKV,EAAO,GACLW,EAAG,MAAS,EADIV,EAAID,EAAO,KAAK,CAEzC,CAEA,MAAM,gBAAgBU,EAI8D,CAClF,IAAMb,EAAgC,CAAE,OAAQa,EAAQ,OAAQ,KAAMA,EAAQ,IAAK,EACnF,OAAIA,EAAQ,aAAYb,EAAK,YAAca,EAAQ,YAC5C,KAAK,KAAK,4BAA6Bb,EAAMe,EAA2B,CACjF,CAEA,MAAM,gBACJT,EAC0D,CAC1D,OAAO,KAAK,KAAK,uBAAwBA,EAASU,EAA+B,CACnF,CAEA,MAAM,oBACJC,EAC2D,CAC3D,OAAO,KAAK,IAAI,kBAAkBA,CAAS,UAAWC,EAAgC,CACxF,CAEA,MAAM,sBACJD,EAC0E,CAC1E,OAAO,KAAK,IAAI,kBAAkBA,CAAS,YAAaE,EAAkC,CAC5F,CAEA,MAAM,0BACJF,EACAX,EACoE,CACpE,OAAO,KAAK,KACV,kBAAkBW,CAAS,oBAC3BX,EACAc,EACF,CACF,CAEA,MAAM,mBACJH,EACAX,EAC6D,CAC7D,OAAO,KAAK,KACV,kBAAkBW,CAAS,YAC3BX,EACAe,EACF,CACF,CAEA,MAAM,qBAA8E,CAClF,OAAO,KAAK,KAAK,6BAA8B,CAAC,EAAGC,EAA+B,CACpF,CAEA,MAAM,4BAA4BT,EAEyB,CACzD,IAAMU,EACJ,OAAOV,GAAS,gBAAmB,SAAWA,EAAQ,eAAe,KAAK,EAAI,GAC1Eb,EAAOuB,EAAQ,OAAS,EAAI,CAAE,iBAAkBA,CAAQ,EAAI,CAAC,EACnE,OAAO,KAAK,KACV,0CACAvB,EACAsB,EACF,CACF,CAEA,MAAM,qBACJL,EACAO,EAC0D,CAC1D,IAAMnB,EAAkC,CAAC,EACzC,OAAI,OAAOmB,GAAiB,UAAYA,EAAa,OAAS,IAC5DnB,EAAQ,iBAAiB,EAAImB,GAExB,KAAK,IACV,gCAAgCP,CAAS,GACzCQ,GACA,OAAO,KAAKpB,CAAO,EAAE,OAAS,EAAIA,EAAU,MAC9C,CACF,CAQA,MAAM,sBACJY,EAC2D,CAC3D,OAAO,KAAK,IACV,iCAAiCA,CAAS,GAC1CS,EACF,CACF,CAEA,MAAM,sBACJpB,EACuC,CACvC,OAAO,KAAK,KAAK,+BAAgCA,EAASqB,EAAiC,CAC7F,CAEA,MAAM,8BACJrB,EACuC,CACvC,OAAO,KAAK,KACV,4CACAA,EACAqB,EACF,CACF,CAEA,MAAM,yBACJC,EACAC,EACyD,CACzD,OAAO,KAAK,KACV,4BACA,CAAE,YAAaD,EAAgB,IAAAC,CAAI,EACnCC,EACF,CACF,CAEA,MAAM,wBACJC,EACAC,EAC2D,CAC3D,OAAO,KAAK,KACV,8BACA,CAAE,oBAAqBD,EAAmB,WAAAC,CAAW,EACrDC,EACF,CACF,CACF,ECjQA,SAASC,GAAkBC,EAAyD,CAClF,OACE,OAAOA,GAAS,UAChBA,IAAS,MACRA,EAAiC,KAAO,IACzC,cAAgBA,CAEpB,CAGA,SAASC,GACPD,EACoF,CACpF,GAAI,OAAOA,GAAS,UAAYA,IAAS,KAAM,MAAO,GACtD,IAAME,EAAIF,EACV,GAAIE,EAAE,KAAO,IAAS,CAACA,EAAE,OAAS,OAAOA,EAAE,OAAU,SAAU,MAAO,GACtE,IAAMC,EAAMD,EAAE,MACd,OAAO,OAAOC,EAAI,MAAS,UAAY,OAAOA,EAAI,SAAY,QAChE,CAMO,SAASC,GACdC,EACAC,EAC+C,CAC/C,GAAIL,GAAgBI,CAAS,EAC3B,MAAO,CACL,QAASA,EAAU,MAAM,QACzB,KAAME,GAA+BF,EAAU,MAAM,IAAI,CAC3D,EAEF,IAAMG,EAAOH,EAGPI,EAASD,GAAM,MACrB,GACE,OAAOC,GAAW,UAClBA,IAAW,MACX,SAAUA,GACV,OAAQA,EAA4B,MAAS,SAE7C,MAAO,CACL,QAAUA,EAAgC,SAAWD,GAAM,SAAWF,EACtE,KAAMC,GAAgCE,EAA4B,IAAI,CACxE,EAEF,IAAMC,EAAUF,GAAM,SAAWF,EAC3BK,EAAUH,GAAM,MAChBI,EACJ,OAAOD,GAAY,SACfJ,GAA+BI,CAAO,EACtCA,IAAY,OACV,kBACAJ,GAA+B,OAAOI,CAAO,CAAC,EACtD,MAAO,CAAE,QAAAD,EAAS,KAAAE,CAAK,CACzB,CAEA,IAAMC,GAAqB,IAM3B,SAASC,IAA4B,CACnC,GACE,OAAO,WAAW,OAAW,KAC7B,OAAO,WAAW,OAAO,YAAe,WAExC,OAAO,WAAW,OAAO,WAAW,EAEtC,MAAM,IAAI,MAAM,+CAA+C,CACjE,CAMO,SAASC,GAAgBC,EAAiBC,EAAwB,CACvE,IAAMC,EAAQD,EAAS,KAAK,IAAI,EAAGD,CAAO,EAC1C,OAAO,KAAK,IAAIE,EAAOL,EAAkB,CAC3C,CAEA,SAASM,GAAoBC,EAAgBC,EAAyB,CACpE,OAAID,IAAW,MAAc,GACtBC,GAAU,KAAOA,IAAW,GACrC,CAEO,IAAMC,GAAN,KAA4C,CACjD,YACmBC,EACAC,EAAqB,EACrBC,EAAuB,IACvBC,EACjB,CAJiB,eAAAH,EACA,gBAAAC,EACA,kBAAAC,EACA,YAAAC,CAChB,CAEH,MAAM,IAAOC,EAAaC,EAAsE,CAC9F,OAAO,KAAK,QAAWD,EAAK,CAAE,OAAQ,MAAO,QAAAC,CAAQ,CAAC,CACxD,CAEA,MAAM,KACJD,EACAnB,EACAoB,EACoC,CACpC,OAAO,KAAK,QAAWD,EAAK,CAC1B,OAAQ,OACR,KAAM,KAAK,UAAUnB,CAAI,EACzB,QAAS,CAAE,eAAgB,mBAAoB,GAAGoB,CAAQ,CAC5D,CAAC,CACH,CAEA,MAAc,QAAWD,EAAaE,EAAyD,CAC7F,IAAMT,GAAUS,EAAO,QAAU,OAAO,YAAY,EAC9CC,EAAYhB,GAAkB,EAC9Bc,EAAU,IAAI,QAAQC,EAAO,OAAsB,EACzDD,EAAQ,IAAI,eAAgBE,CAAS,EAEjC,KAAK,QACP,KAAK,OAAO,MAAM,UAAW,CAAE,UAAAA,EAAW,IAAAH,EAAK,OAAAP,CAAO,CAAC,EAGzD,IAAIW,EAEJ,QAASf,EAAU,EAAGA,GAAW,KAAK,WAAYA,IAChD,GAAI,CACF,IAAMgB,EAAa,IAAI,gBACjBC,EAAY,WAAW,IAAMD,EAAW,MAAM,EAAG,KAAK,SAAS,EAErE,GAAI,CACF,IAAME,EAAW,MAAM,MAAMP,EAAK,CAChC,GAAGE,EACH,QAAAD,EACA,OAAQI,EAAW,MACrB,CAAC,EAED,GAAI,CAACE,EAAS,GAAI,CAChB,IAAI7B,EACJ,GAAI,CACFA,EAAY,MAAM6B,EAAS,KAAK,CAClC,MAAQ,CAER,CAEA,GAAM,CAAE,QAAAxB,EAAS,KAAAE,EAAK,EAAIR,GAAmBC,EAAW6B,EAAS,UAAU,EACrEC,EAAYC,EAAYxB,GAAMF,EAAS,CAC3C,UAAAoB,EACA,OAAQI,EAAS,OACjB,WAAYA,EAAS,WACrB,KAAM7B,CACR,CAAC,EAED,GAAIc,GAAoBC,EAAQc,EAAS,MAAM,GAAKlB,EAAU,KAAK,WAAY,CAC7Ee,EAAYI,EACZ,aAAaF,CAAS,EACtB,MAAM,IAAI,QAASI,IACjB,WAAWA,GAAStB,GAAgBC,EAAS,KAAK,YAAY,CAAC,CACjE,EACA,QACF,CAEA,OAAOb,EAAIgC,CAAS,CACtB,CAEA,GAAID,EAAS,SAAW,IACtB,OAAOI,EAAG,MAAc,EAG1B,GADsBJ,EAAS,QAAQ,IAAI,gBAAgB,IACrC,IACpB,OAAOI,EAAG,MAAc,EAE1B,IAAMC,EAAO,MAAML,EAAS,KAAK,EACjC,GAAInC,GAAkBwC,CAAG,EACvB,OAAOD,EAAIC,EAAmC,SAAS,EAEzD,IAAMrC,EAAIqC,EACV,GAAI,OAAOA,GAAQ,UAAYA,IAAQ,MAAQrC,EAAE,KAAO,IAAQ,EAAE,cAAeA,GAC/E,OAAOoC,EAAG,MAAc,EAE1B,GAAIrC,GAAgBsC,CAAG,EAAG,CACxB,GAAM,CAAE,QAAA7B,EAAS,KAAAE,CAAK,EAAIR,GAAmBmC,EAAKL,EAAS,UAAU,EACrE,OAAO/B,EACLiC,EAAYxB,EAAMF,EAAS,CACzB,UAAAoB,EACA,OAAQI,EAAS,OACjB,WAAYA,EAAS,WACrB,KAAMK,CACR,CAAC,CACH,CACF,CACA,OAAOD,EAAGC,CAAQ,CACpB,QAAE,CACA,aAAaN,CAAS,CACxB,CACF,OAASO,EAAO,CAGd,GAFAT,EAAYS,EACEpB,IAAW,OACZJ,EAAU,KAAK,WAC1B,MAAM,IAAI,QAASqB,GACjB,WAAWA,EAAStB,GAAgBC,EAAS,KAAK,YAAY,CAAC,CACjE,MAEA,MAEJ,CAGF,OAAIe,aAAqB,OAASA,EAAU,OAAS,aAC5C5B,EAAIiC,EAAY,UAAW,oBAAqB,CAAE,UAAAN,CAAU,CAAC,CAAC,EAGhE3B,EACLiC,EACE,kBACAL,aAAqB,MAAQA,EAAU,QAAU,iBACjD,CAAE,UAAAD,EAAW,MAAOC,CAAU,CAChC,CACF,CACF,CACF,ECnOO,SAASU,EAAgBC,EAA0B,CACxD,IAAMC,EAAQ,IAAI,WAAWD,CAAG,EAC1BE,EAAS,MAAM,KAAKD,EAAQE,GAAM,OAAO,aAAaA,CAAC,CAAC,EAAE,KAAK,EAAE,EAEvE,GAAI,OAAO,WAAW,KAAS,IAC7B,MAAMC,GAAoB,QAAQ,EAGpC,OADe,WAAW,KAAKF,CAAM,EACvB,QAAQ,MAAO,GAAG,EAAE,QAAQ,MAAO,GAAG,EAAE,QAAQ,KAAM,EAAE,CACxE,CAMO,SAASG,GAAgBC,EAAuB,CACrD,GAAI,OAAO,WAAW,KAAS,IAC7B,MAAMF,GAAoB,QAAQ,EAGpC,IAAMG,EAASD,EAAE,QAAQ,KAAM,GAAG,EAAE,QAAQ,KAAM,GAAG,EAC/CE,EAAUD,EAAO,OAAS,EAC1BE,EAASD,IAAY,EAAID,EAASA,EAAS,IAAI,OAAO,EAAIC,CAAO,EACjEN,EAAS,WAAW,KAAKO,CAAM,EAErC,OAAO,WAAW,KAAKP,EAASQ,GAAMA,EAAE,WAAW,CAAC,CAAC,CACvD,CAGO,SAASC,EAA6BL,EAAwB,CACnE,IAAML,EAAQI,GAAgBC,CAAC,EACzBM,EAAS,IAAI,YAAYX,EAAM,MAAM,EAC3C,WAAI,WAAWW,CAAM,EAAE,IAAIX,CAAK,EACzBW,CACT,CC9BA,SAASC,GACPC,EAC+E,CAC/E,OACEA,IAAa,MACb,OAAOA,GAAa,UACpB,mBAAoBA,GACpBA,EAAS,0BAA0B,WAEvC,CAUO,SAASC,EACdC,EACiC,CACjC,GAAI,CAACA,EAAW,SACd,MAAMC,EAAY,gBAAiB,iCAAkC,CAAE,WAAAD,CAAW,CAAC,EAGrF,IAAMF,EAAWE,EAAW,SAE5B,GAAI,CAACH,GAA0BC,CAAQ,EACrC,MAAMG,EAAY,gBAAiB,wCAAyC,CAAE,SAAAH,CAAS,CAAC,EAG1F,GAAI,EAAE,sBAAuBA,GAC3B,MAAMG,EACJ,gBACA,mFACA,CAAE,SAAAH,CAAS,CACb,EAGF,IAAMI,EAAiBJ,EAAS,eAC1BK,EAAqBL,EAA8C,kBAEzE,MAAO,CACL,GAAIE,EAAW,GACf,MAAOI,EAAgBJ,EAAW,KAAK,EACvC,SAAU,CACR,eAAgBI,EAAgBF,CAAc,EAC9C,kBAAmBE,EAAgBD,CAAiB,CACtD,EACA,KAAM,YACR,CACF,CAUO,SAASE,GACdL,EAC6B,CAC7B,GAAI,CAACA,EAAW,SACd,MAAMC,EAAY,gBAAiB,iCAAkC,CAAE,WAAAD,CAAW,CAAC,EAGrF,IAAMF,EAAWE,EAAW,SAE5B,GAAI,CAACH,GAA0BC,CAAQ,EACrC,MAAMG,EAAY,gBAAiB,wCAAyC,CAAE,SAAAH,CAAS,CAAC,EAG1F,GAAI,EAAE,sBAAuBA,IAAa,EAAE,cAAeA,GACzD,MAAMG,EACJ,gBACA,4FACA,CAAE,SAAAH,CAAS,CACb,EAGF,IAAMI,EAAiBJ,EAAS,eAC1BQ,EAAqBR,EAA4C,kBACjES,EAAaT,EAA4C,UACzDU,EAAcV,EAA4C,WAEhE,MAAO,CACL,GAAIE,EAAW,GACf,MAAOI,EAAgBJ,EAAW,KAAK,EACvC,SAAU,CACR,kBAAmBI,EAAgBE,CAAiB,EACpD,eAAgBF,EAAgBF,CAAc,EAC9C,UAAWE,EAAgBG,CAAS,EACpC,GAAIC,GAAc,CAAE,WAAYJ,EAAgBI,CAAU,CAAE,CAC9D,EACA,KAAM,YACR,CACF,CC3GO,SAASC,IAA+B,CAC7C,GAAI,CAKF,MAJI,SAAO,UAAc,KAAe,CAAC,UAAU,aAI/C,OAAO,oBAAwB,IAKrC,MAAQ,CACN,MAAO,EACT,CACF,CAEA,eAAsBC,IAAqD,CACzE,GAAI,CAKF,MAJI,CAACD,GAAoB,GAIrB,OAAO,oBAAoB,+CAAkD,WACxE,GAGF,MAAM,oBAAoB,8CAA8C,CACjF,MAAQ,CACN,MAAO,EACT,CACF,CAEA,eAAsBE,IAAyC,CAC7D,IAAMC,EAAqBH,GAAoB,EACzCI,EAAiC,MAAMH,GAAiC,EAE9E,MAAO,CACL,mBAAAE,EACA,+BAAAC,EACA,gBAAiBD,EAAqB,UAAY,UACpD,CACF,CCzCO,SAASE,EACdC,EACAC,EAA8B,SACa,CAC3C,GACE,CAACD,GACD,OAAOA,GAAe,UACtB,EAAE,OAAQA,IACV,EAAE,UAAWA,IACb,EAAE,aAAcA,GAEhB,MAAME,GAAsBD,CAAS,CAEzC,CCgBA,eAAsBE,GAKpBC,EACgD,CAChD,GAAM,CAAE,UAAAC,EAAW,aAAAC,EAAc,MAAAC,EAAO,cAAAC,EAAe,OAAAC,EAAQ,OAAAC,CAAO,EAAIN,EAE1E,GAAI,CAGF,GAFAE,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,UAAAD,CAAU,CAAC,EAEnD,CAACM,GAAoB,EAAG,CAC1B,IAAMC,EAAQC,GAAwB,EACtC,OAAAP,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAAM,CAAM,CAAC,EAC5CE,EAAIF,CAAK,CAClB,CAGA,IAAMG,EAAc,MAAMR,EAAM,EAChC,GAAI,CAACQ,EAAY,GACf,OAAAT,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAOS,EAAY,KAAM,CAAC,EAC/DD,EAAIC,EAAY,KAAK,EAI9B,IAAMC,EAAgBR,EAAcO,EAAY,KAAK,EACrD,GAAI,CAACC,EAAc,GACjB,OAAAV,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAOU,EAAc,KAAM,CAAC,EACjEF,EAAIE,EAAc,KAAK,EAIhC,IAAMC,EAAc,MAAMR,EAAOO,EAAc,KAAK,EACpD,GAAI,CAACC,EAAY,CACf,IAAML,EAAQM,EACZ,aACA,GAAGb,IAAc,WAAa,WAAa,WAAW,SACxD,EACA,OAAAC,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAAM,CAAM,CAAC,EAC5CE,EAAIF,CAAK,CAClB,CAEA,GAAI,CACFO,EAA4BF,CAAU,CACxC,OAASG,EAAG,CACV,IAAMR,EAAQS,EAAiBD,CAAC,EAChC,OAAAd,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAAM,CAAM,CAAC,EAC5CE,EAAIF,CAAK,CAClB,CAGA,IAAMU,EAAe,MAAMZ,EAAOK,EAAY,MAAOE,CAAU,EAC/D,OAAKK,EAAa,GAKXC,EAAGD,EAAa,KAAK,GAJ1BhB,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAOgB,EAAa,KAAM,CAAC,EAChER,EAAIQ,EAAa,KAAK,EAIjC,OAASV,EAAO,CACd,IAAMY,EAAiBH,EAAiBT,CAAK,EAC7C,OAAAN,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAOkB,CAAe,CAAC,EAC5DV,EAAIU,CAAc,CAC3B,CACF,CCpEO,SAASC,EACdC,EACAC,EACmD,CACnD,GAAI,CACFC,GAAkBF,EAAuB,UAAW,WAAW,EAC/DE,GAAkBF,EAAuB,KAAK,GAAI,SAAS,EAE3D,IAAMG,EAAkBC,EAA6BJ,EAAuB,SAAS,EAC/EK,EAAeD,EAA6BJ,EAAuB,KAAK,EAAE,EAG5EM,EAAyD,CAC3D,iBAAkB,WACpB,EAEIN,EAAuB,yBAEzBM,EAAyB,CACvB,GAAGN,EAAuB,sBAC5B,GAIEC,IACFK,EAAyB,CACvB,GAAGA,EACH,wBAAyBL,CAC3B,GAGF,IAAMM,EAAgD,CACpD,GAAI,CACF,GAAIP,EAAuB,GAAG,GAC9B,KAAMA,EAAuB,GAAG,IAClC,EACA,KAAM,CACJ,GAAIK,EACJ,KAAML,EAAuB,KAAK,KAClC,YAAaA,EAAuB,KAAK,WAC3C,EACA,UAAWG,EACX,iBAAkBH,EAAuB,iBACzC,GAAIA,EAAuB,UAAY,QAAa,CAClD,QAASA,EAAuB,OAClC,EACA,YAAa,OACb,uBAAAM,EACA,GAAIN,EAAuB,oBAAsB,CAC/C,mBAAoBA,EAAuB,mBAAmB,IAAKQ,IAAU,CAC3E,GAAIJ,EAA6BI,EAAK,EAAE,EACxC,KAAMA,EAAK,KACX,GAAIA,EAAK,YAAc,CACrB,WAAYA,EAAK,UACnB,CACF,EAAE,CACJ,CACF,EAEA,OAAOC,EAAG,CAAE,UAAAF,CAAU,CAAC,CACzB,OAASG,EAAG,CACV,OAAOC,EAAIC,EAAiBF,CAAC,CAAC,CAChC,CACF,CAOO,SAASG,GACdC,EACAC,EACkD,CAClD,GAAI,CACFb,GAAkBY,EAAU,UAAW,WAAW,EAClD,IAAMX,EAAkBC,EAA6BU,EAAU,SAAS,EAExE,OAAOL,EAAG,CACR,UAAW,CACT,UAAWN,EACX,KAAMW,EAAU,KAChB,GAAIA,EAAU,UAAY,QAAa,CAAE,QAASA,EAAU,OAAQ,EACpE,iBAAkBA,EAAU,kBAAoB,YAChD,GAAIA,EAAU,kBAAoB,CAChC,iBAAkBA,EAAU,iBAAiB,IAAKN,IAAU,CAC1D,GAAIJ,EAA6BI,EAAK,EAAE,EACxC,KAAMA,EAAK,KACX,GAAIA,EAAK,YAAc,CACrB,WAAYA,EAAK,UACnB,CACF,EAAE,CACJ,CACF,EACA,GAAIO,IAAc,QAAa,CAAE,UAAAA,CAAU,CAC7C,CAAC,CACH,OAASL,EAAG,CACV,OAAOC,EAAIC,EAAiBF,CAAC,CAAC,CAChC,CACF,CAMA,eAAsBM,GACpBC,EACAC,EACAC,EACiD,CACjD,IAAMC,EAAQH,EAAQ,gBAAkBA,EAAQ,iBAChD,GAAI,CAACG,GAAS,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAAI,CAC9D,IAAMC,EAAQC,EAA2B,iBAAkB,4BAA4B,EACvF,OAAAH,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAAE,CAAM,CAAC,EAC5CV,EAAIU,CAAK,CAClB,CAEA,IAAME,EAAS,MAAMC,GAInB,CACA,UAAW,WACX,aAAAL,EACA,MAAO,IAAMD,EAAU,cAAc,CAAE,iBAAkBE,CAAM,CAAC,EAChE,cAAgBK,GACd1B,EAA0B0B,EAAY,UAAWR,EAAQ,iBAAiB,EAC5E,OAAQ,MAAOS,GAAoB,CACjC,IAAMC,EAAO,CAAE,GAAGD,EAAiB,GAAIT,EAAQ,QAAU,CAAE,OAAQA,EAAQ,MAAO,CAAG,EACrF,OAAO,UAAU,YAAY,OAAOU,CAAI,CAC1C,EACA,OAAQ,MAAOF,EAAaG,IAAe,CACzC,IAAMC,EAAe,MAAMX,EAAU,eAAe,CAClD,WAAYO,EAAY,WACxB,WAAYK,EAA+BF,CAAU,EACrD,GAAIX,EAAQ,YAAc,CAAE,YAAaA,EAAQ,UAAW,CAC9D,CAAC,EAED,OAAKY,EAAa,GAEXpB,EAAG,CACR,QAAS,GACT,aAAcoB,EAAa,MAAM,cACjC,cAAeA,EAAa,MAAM,cAClC,OAAQA,EAAa,MAAM,OAC3B,aAAcA,EAAa,MAAM,cACjC,KAAM,CACJ,OAAQA,EAAa,MAAM,KAAK,QAChC,eAAgBA,EAAa,MAAM,KAAK,iBACxC,MAAOA,EAAa,MAAM,KAAK,MAC/B,SAAUA,EAAa,MAAM,KAAK,QACpC,EACA,GAAIA,EAAa,MAAM,cAAgB,CAAE,YAAaA,EAAa,MAAM,YAAa,CACxF,CAAC,EAf4BlB,EAAIkB,EAAa,KAAK,CAgBrD,CACF,CAAC,EAED,OAAIN,EAAO,IACTJ,EAAa,KAAK,UAAW,CAC3B,KAAM,UACN,UAAW,WACX,MAAOI,EAAO,MAAM,aACpB,KAAMA,EAAO,MAAM,IACrB,CAAC,EAEIA,CACT,CAMA,eAAsBQ,GACpBd,EACAC,EACAC,EACqD,CACrD,IAAMC,EAAQH,EAAQ,gBAAkBA,EAAQ,iBAC1Ce,EAAYZ,IAAU,QAAa,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAEjFG,EAAS,MAAMC,GAInB,CACA,UAAW,eACX,aAAAL,EACA,MAAO,IACLD,EAAU,UAAUc,EAAY,CAAE,iBAAmBZ,EAAiB,KAAK,CAAE,EAAI,CAAC,CAAC,EACrF,cAAgBK,GACdZ,GAA4BY,EAAY,UAAWR,EAAQ,SAAS,EACtE,OAAQ,MAAOS,GAAoB,CACjC,IAAMC,EAAO,CAAE,GAAGD,EAAiB,GAAIT,EAAQ,QAAU,CAAE,OAAQA,EAAQ,MAAO,CAAG,EACrF,OAAO,UAAU,YAAY,IAAIU,CAAI,CACvC,EACA,OAAQ,MAAOF,EAAaG,IAAe,CACzC,IAAMC,EAAe,MAAMX,EAAU,qBAAqB,CACxD,WAAYO,EAAY,WACxB,WAAYQ,GAA2BL,CAAU,EACjD,GAAIX,EAAQ,YAAc,CAAE,YAAaA,EAAQ,UAAW,CAC9D,CAAC,EAED,OAAKY,EAAa,GAEXpB,EAAG,CACR,cAAeoB,EAAa,MAAM,cAClC,aAAcA,EAAa,MAAM,cACjC,KAAM,CACJ,OAAQA,EAAa,MAAM,KAAK,QAChC,eAAgBA,EAAa,MAAM,KAAK,iBACxC,MAAOA,EAAa,MAAM,KAAK,MAC/B,SAAUA,EAAa,MAAM,KAAK,QACpC,EACA,QAASA,EAAa,MAAM,QAC5B,GAAIA,EAAa,MAAM,cAAgB,CAAE,YAAaA,EAAa,MAAM,YAAa,CACxF,CAAC,EAb4BlB,EAAIkB,EAAa,KAAK,CAcrD,CACF,CAAC,EAED,OAAIN,EAAO,IACTJ,EAAa,KAAK,UAAW,CAC3B,KAAM,UACN,UAAW,eACX,MAAOI,EAAO,MAAM,aACpB,KAAMA,EAAO,MAAM,IACrB,CAAC,EAEIA,CACT,CC/PA,eAAsBW,GACpBC,EACAC,EACkC,CAElC,OAAKA,EAKDA,EAAO,QACF,UAGF,IAAI,QAAkCC,GAAY,CACvD,IAAMC,EAAU,IAAM,CACpBC,EAAQ,EACRF,EAAQ,SAAS,CACnB,EAEME,EAAU,IAAM,CACpB,aAAaC,CAAO,EACpBJ,EAAO,oBAAoB,QAASE,CAAO,CAC7C,EAEME,EAAU,WAAW,IAAM,CAC/BD,EAAQ,EACRF,EAAQ,WAAW,CACrB,EAAGF,CAAU,EAEbC,EAAO,iBAAiB,QAASE,CAAO,CAC1C,CAAC,GAzBC,MAAM,IAAI,QAASD,GAAY,WAAWA,EAASF,CAAU,CAAC,EACvD,YAyBX,CCpBA,IAAMM,GAAmB,IACnBC,GAAoB,GAEbC,GAAN,KAAwB,CAC7B,YAA6BC,EAAsB,CAAtB,eAAAA,CAAuB,CASpD,MAAM,UACJC,EACAC,EAC2D,CAC3D,IAAMC,EAAc,MAAM,KAAK,UAAU,gBAAgB,CAAE,UAAWF,EAAQ,SAAU,CAAC,EACzF,GAAI,CAACE,EAAY,GAAI,OAAOC,EAAID,EAAY,KAAK,EAEjD,GAAM,CAAE,WAAAE,CAAW,EAAIF,EAAY,MAEnC,QAASG,EAAU,EAAGA,EAAUR,GAAmBQ,IAAW,CAC5D,GAAIJ,GAAQ,QACV,OAAOE,EAAIG,EAAY,cAAe,sCAAsC,CAAC,EAI/E,GADmB,MAAMC,GAAcX,GAAkBK,CAAM,IAC5C,UACjB,OAAOE,EAAIG,EAAY,cAAe,sCAAsC,CAAC,EAG/E,IAAME,EAAe,MAAM,KAAK,UAAU,oBAAoBJ,CAAU,EACxE,GAAI,CAACI,EAAa,GAAI,OAAOL,EAAIK,EAAa,KAAK,EAEnD,IAAMC,EAASD,EAAa,MAAM,OAC5BE,EAAiBF,EAAa,MAAM,eAE1C,GAAIC,IAAW,kBAAmB,CAChC,IAAME,EAAqB,MAAM,KAAK,UAAU,sBAAsBP,CAAU,EAChF,GAAI,CAACO,EAAmB,GAAI,OAAOR,EAAIQ,EAAmB,KAAK,EAE/D,IAAMC,EAAeD,EAAmB,MAExC,GAAI,CAACC,EAAa,UAChB,OAAOT,EACLG,EACE,gBACA,iGACA,CAAE,eAAAI,CAAe,CACnB,CACF,EAGF,IAAMG,EAAwBC,EAA0BF,EAAa,SAAS,EAC9E,GAAI,CAACC,EAAsB,GAAI,OAAOV,EAAIU,EAAsB,KAAK,EAErE,IAAIE,EACJ,GAAI,CACFA,EAAa,MAAM,UAAU,YAAY,OAAOF,EAAsB,KAAK,CAC7E,OAASG,EAAG,CACV,OAAOb,EAAIc,EAAiBD,CAAC,CAAC,CAChC,CAEA,GAAI,CACFE,EAA4BH,EAAY,QAAQ,CAClD,OAASC,EAAG,CACV,OAAOb,EAAIc,EAAiBD,CAAC,CAAC,CAChC,CAEA,IAAIG,EACJ,GAAI,CACFA,EAAuBC,EAA+BL,CAAiC,CACzF,OAASC,EAAG,CACV,OAAOb,EAAIc,EAAiBD,CAAC,CAAC,CAChC,CAEA,IAAMK,EAAwB,MAAM,KAAK,UAAU,0BAA0BjB,EAAY,CACvF,WAAYe,EACZ,UAAWP,EAAa,UAAU,SACpC,CAAC,EACD,OAAKS,EAAsB,GAEJ,MAAM,KAAK,UAAU,mBAAmBjB,EAAY,CACzE,aAAcJ,EAAQ,YACxB,CAAC,EAJqCG,EAAIkB,EAAsB,KAAK,CAMvE,CAEA,GAAIZ,IAAW,YAIb,OAHuB,MAAM,KAAK,UAAU,mBAAmBL,EAAY,CACzE,aAAcJ,EAAQ,YACxB,CAAC,CAGL,CAEA,OAAOG,EAAIG,EAAY,UAAW,sBAAsB,CAAC,CAC3D,CACF,EChGA,IAAMgB,GAAmB,IACnBC,GAAoB,GAEbC,GAAN,KAAyB,CAC9B,YAA6BC,EAAsB,CAAtB,eAAAA,CAAuB,CAMpD,MAAM,MAA+D,CACnE,OAAO,KAAK,UAAU,oBAAoB,CAC5C,CAOA,MAAM,iBAAiBC,EAEoC,CACzD,OAAO,KAAK,UAAU,4BAA4BA,CAAO,CAC3D,CAOA,MAAM,eACJC,EACAC,EACAC,EAGA,CACA,GAAID,GAAQ,QACV,OAAOE,EAAIC,EAAY,cAAe,sCAAsC,CAAC,EAG/E,QAASC,EAAU,EAAGA,EAAUT,GAAmBS,IAAW,CAC5D,IAAMC,EAAe,MAAM,KAAK,UAAU,qBAAqBN,EAAWE,CAAY,EACtF,GAAI,CAACI,EAAa,GAAI,OAAOH,EAAIG,EAAa,KAAK,EAEnD,GAAIA,EAAa,MAAM,SAAW,YAAa,CAC7C,GAAI,CAACA,EAAa,MAAM,eAAiB,CAACA,EAAa,MAAM,QAC3D,OAAOH,EAAIC,EAAY,gBAAiB,mCAAmC,CAAC,EAE9E,IAAMG,EACJD,EAAa,MAAM,cAAgB,MAAQA,EAAa,MAAM,eAAiB,GAC3EA,EAAa,MAAM,aACnB,OACN,OAAOE,EAAG,CACR,cAAeF,EAAa,MAAM,cAClC,QAASA,EAAa,MAAM,QAC5B,GAAIC,IAAgB,QAAa,CAAE,YAAAA,CAAY,CACjD,CAAC,CACH,CAGA,GADmB,MAAME,GAAcd,GAAkBM,CAAM,IAC5C,UACjB,OAAOE,EAAIC,EAAY,cAAe,sCAAsC,CAAC,CAEjF,CAEA,OAAOD,EAAIC,EAAY,UAAW,uCAAuC,CAAC,CAC5E,CAQA,MAAM,QAAQJ,EAA0D,CACtE,IAAMU,EAAgB,MAAM,KAAK,UAAU,sBAAsBV,CAAS,EAC1E,GAAI,CAACU,EAAc,GAAI,OAAOP,EAAIO,EAAc,KAAK,EAErD,IAAMC,EAAUD,EAAc,MAE9B,OAAIC,EAAQ,OAAS,eACZ,KAAK,4BAA4BX,EAAWW,CAAO,EAErD,KAAK,oBAAoBX,EAAWW,CAAO,CACpD,CAKA,MAAc,4BACZX,EACAW,EACuC,CACvC,IAAMC,EAAwBC,EAA0BF,EAAQ,OAAO,EACvE,GAAI,CAACC,EAAsB,GAAI,OAAOT,EAAIS,EAAsB,KAAK,EAErE,IAAIE,EACJ,GAAI,CACFA,EAAa,MAAM,UAAU,YAAY,OAAOF,EAAsB,KAAK,CAC7E,OAASG,EAAG,CACV,OAAOZ,EAAIa,EAAiBD,CAAC,CAAC,CAChC,CAEA,GAAI,CACFE,EAA4BH,EAAY,QAAQ,CAClD,OAASC,EAAG,CACV,OAAOZ,EAAIa,EAAiBD,CAAC,CAAC,CAChC,CAEA,IAAIG,EACJ,GAAI,CACFA,EAAuBC,EAA+BL,CAAiC,CACzF,OAASC,EAAG,CACV,OAAOZ,EAAIa,EAAiBD,CAAC,CAAC,CAChC,CAEA,OAAO,KAAK,UAAU,8BAA8B,CAClD,WAAYf,EACZ,WAAYkB,CACd,CAAC,CACH,CAKA,MAAc,oBACZlB,EACAW,EACuC,CACvC,IAAMS,EAAuBC,GAA4BV,EAAQ,OAAO,EACxE,GAAI,CAACS,EAAqB,GAAI,OAAOjB,EAAIiB,EAAqB,KAAK,EAEnE,IAAIN,EACJ,GAAI,CACFA,EAAa,MAAM,UAAU,YAAY,IAAIM,EAAqB,KAAK,CACzE,OAASL,EAAG,CACV,OAAOZ,EAAIa,EAAiBD,CAAC,CAAC,CAChC,CAEA,GAAI,CACFE,EAA4BH,EAAY,KAAK,CAC/C,OAASC,EAAG,CACV,OAAOZ,EAAIa,EAAiBD,CAAC,CAAC,CAChC,CAEA,IAAIG,EACJ,GAAI,CACFA,EAAuBI,GAA2BR,CAAiC,CACrF,OAASC,EAAG,CACV,OAAOZ,EAAIa,EAAiBD,CAAC,CAAC,CAChC,CAEA,OAAO,KAAK,UAAU,sBAAsB,CAC1C,WAAYf,EACZ,WAAYkB,CACd,CAAC,CACH,CACF,EC3KO,IAAMK,GAAN,KAAmB,CAChB,SAER,aAAc,CACZ,KAAK,SAAW,IAAI,GACtB,CAEA,GAAGC,EAAuBC,EAAmC,CAC3D,IAAIC,EAAc,KAAK,SAAS,IAAIF,CAAK,EACzC,OAAKE,IACHA,EAAc,IAAI,IAClB,KAAK,SAAS,IAAIF,EAAOE,CAAW,GAGtCA,EAAY,IAAID,CAAO,EAEhB,IAAM,CACX,KAAK,IAAID,EAAOC,CAAO,CACzB,CACF,CAEA,IAAID,EAAuBC,EAA6B,CACtD,IAAMC,EAAc,KAAK,SAAS,IAAIF,CAAK,EACtCE,IAGLA,EAAY,OAAOD,CAAO,EACtBC,EAAY,OAAS,GACvB,KAAK,SAAS,OAAOF,CAAK,EAE9B,CAEA,KAAKA,EAAuBG,EAA6B,CACvD,IAAMD,EAAc,KAAK,SAAS,IAAIF,CAAK,EAC3C,GAAIE,EACF,QAAWD,KAAWC,EACpB,GAAI,CACFD,EAAQE,CAAO,CACjB,MAAQ,CAGR,CAGN,CAEA,oBAA2B,CACzB,KAAK,SAAS,MAAM,CACtB,CACF,EChDO,IAAMC,GAAuB,gCACvBC,GAA6B,6CAgBnC,IAAMC,GAAwB,qCCd9B,SAASC,GAA6BC,EAAmC,CAC9E,MAAO,CACL,MAAM,KAAKC,EAA0C,CACnD,IAAMC,EAAO,KAAK,UAAUD,CAAO,EACnC,GAAI,OAAO,UAAc,KAAe,OAAO,UAAU,YAAe,WAAY,CAClF,UAAU,WAAWD,EAAUE,CAAI,EACnC,MACF,CACI,OAAO,MAAU,KACnB,MAAM,MAAMF,EAAU,CACpB,OAAQ,OACR,KAAAE,EACA,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,UAAW,EACb,CAAC,CAEL,CACF,CACF,CCTO,SAASC,GAAsBC,EAAuBC,EAAqC,CAChG,MAAO,CAAE,MAAAD,EAAO,UAAAC,EAAW,GAAI,EAAK,CACtC,CCCO,IAAMC,GAAN,KAAkB,CACvB,YACmBC,EACAC,EACAC,EACAC,EACAC,EACjB,CALiB,eAAAJ,EACA,kBAAAC,EACA,aAAAC,EACA,kBAAAC,EACA,qBAAAC,CAChB,CAEH,MAAc,kBACZC,EACAC,EACsE,CACtE,IAAMC,EACJ,mBAAoBD,EACfA,EAAQ,gBAAkBA,EAAQ,kBAAoB,UACtDA,EAAQ,kBAAoBA,EAAQ,gBAAkB,UACvDE,EAAa,OAAOD,GAAmB,SAAWA,EAAiB,UAEzE,OAAIF,IAAc,WACT,QAAQ,QACbI,EAAG,CACD,QAAS,GACT,aAAc,GACd,OAAQ,UACR,aAAc,KAAK,aACnB,KAAM,CAAE,OAAQ,eAAgB,eAAgBD,CAAW,CAC7D,CAAC,CACH,EAGK,QAAQ,QACbC,EAAG,CACD,cAAe,GACf,aAAc,KAAK,aACnB,KAAM,CAAE,OAAQ,eAAgB,eAAgBD,CAAW,CAC7D,CAAC,CACH,CACF,CAEA,MAAM,SAASF,EAA2E,CACxF,GAAI,KAAK,QAAS,CAChB,IAAMI,EAAS,MAAM,KAAK,kBAAkB,WAAYJ,CAAO,EAC/D,OAAII,EAAO,IACT,KAAK,aAAa,KAAK,UAAW,CAChC,KAAM,UACN,UAAW,WACX,MAAOA,EAAO,MAAM,aACpB,KAAMA,EAAO,MAAM,IACrB,CAAC,EAEIA,CACT,CAEA,IAAMC,EAAQ,KAAK,IAAI,EACjBD,EAAS,MAAME,GAAgBN,EAAS,KAAK,UAAW,KAAK,YAAY,EAC/E,OAAII,EAAO,IAAM,KAAK,iBACpB,KAAK,gBACF,KAAKG,GAAsB,WAAY,KAAK,IAAI,EAAIF,CAAK,CAAC,EAC1D,MAAM,IAAM,CAAC,CAAC,EAEZD,CACT,CAEA,MAAM,aACJJ,EACqD,CACrD,GAAI,KAAK,QAAS,CAChB,IAAMI,EAAS,MAAM,KAAK,kBAAkB,eAAgBJ,CAAO,EACnE,OAAII,EAAO,IACT,KAAK,aAAa,KAAK,UAAW,CAChC,KAAM,UACN,UAAW,eACX,MAAOA,EAAO,MAAM,aACpB,KAAMA,EAAO,MAAM,IACrB,CAAC,EAEIA,CACT,CAEA,IAAMC,EAAQ,KAAK,IAAI,EACjBD,EAAS,MAAMI,GAAoBR,EAAS,KAAK,UAAW,KAAK,YAAY,EACnF,OAAII,EAAO,IAAM,KAAK,iBACpB,KAAK,gBACF,KAAKG,GAAsB,eAAgB,KAAK,IAAI,EAAIF,CAAK,CAAC,EAC9D,MAAM,IAAM,CAAC,CAAC,EAEZD,CACT,CACF,ECvFA,eAAsBK,GACpBC,EACAC,EACAC,EACuD,CACvD,IAAMC,EAAQH,EAAQ,gBAAkBA,EAAQ,iBAChD,GAAI,CAACG,GAAS,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAAI,CAC9D,IAAMC,EAAQC,EAA2B,iBAAkB,4BAA4B,EACvF,OAAAH,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAAE,CAAM,CAAC,EAC5CE,EAAIF,CAAK,CAClB,CAEA,GAAI,CAACJ,EAAQ,KAAO,OAAOA,EAAQ,KAAQ,UAAYA,EAAQ,IAAI,KAAK,EAAE,SAAW,EAAG,CACtF,IAAMI,EAAQC,EAA2B,MAAO,0BAA0B,EAC1E,OAAAH,EAAa,KAAK,QAAS,CAAE,KAAM,QAAS,MAAAE,CAAM,CAAC,EAC5CE,EAAIF,CAAK,CAClB,CAEA,IAAMG,EAAS,MAAMC,GAInB,CACA,UAAW,WACX,aAAAN,EACA,MAAO,IAAMD,EAAU,yBAAyBE,EAAOH,EAAQ,GAAG,EAClE,cAAgBS,GACdC,EAA0BD,EAAY,SAA+C,EACvF,OAAQ,MAAOE,GAAoB,UAAU,YAAY,OAAOA,CAAe,EAC/E,OAAQ,MAAOF,EAAaG,IAAe,CACzC,IAAMC,EAAe,MAAMZ,EAAU,wBACnCQ,EAAY,oBACZK,EAA+BF,CAAU,CAC3C,EAEA,GAAI,CAACC,EAAa,GAAI,OAAOP,EAAIO,EAAa,KAAK,EAEnD,GAAM,CACJ,cAAAE,EACA,OAAAC,EACA,cAAAC,EACA,KAAMC,EACN,aAAAC,CACF,EAAIN,EAAa,MACjB,OAAOO,EAAG,CACR,QAAS,GACT,aAAcL,EACd,OAAAC,EACA,aAAcC,EACd,KAAM,CACJ,OAAQC,EAAY,QACpB,eAAgBA,EAAY,iBAC5B,MAAOA,EAAY,MACnB,SAAUA,EAAY,QACxB,EACA,GAAIC,IAAiB,QAAa,CAAE,YAAaA,CAAa,CAChE,CAAC,CACH,CACF,CAAC,EAED,OAAIZ,EAAO,IACTL,EAAa,KAAK,UAAW,CAC3B,KAAM,UACN,UAAW,WACX,MAAOK,EAAO,MAAM,aACpB,KAAMA,EAAO,MAAM,IACrB,CAAC,EAEIA,CACT,CClFO,IAAMc,GAAN,KAAsB,CAC3B,YACmBC,EACAC,EACjB,CAFiB,eAAAD,EACA,kBAAAC,CAChB,CAEH,QAAQC,EAAuF,CAC7F,OAAOC,GAAeD,EAAS,KAAK,UAAW,KAAK,YAAY,CAClE,CACF,EC6BO,IAAME,GAAN,MAAMC,CAAU,CACJ,QACA,aACT,UACA,aACA,gBACA,mBACA,YACA,gBACD,WAOP,OAAO,OAAOC,EAA4D,CACxE,GAAI,CACF,IAAMC,EAAQD,EAAO,MACfE,EAAiBF,EAAO,eAE9B,GAAI,CAACC,GAAS,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAC1D,OAAOE,EAAIC,EAA2B,QAAS,4BAA4B,CAAC,EAE9E,GAAI,CAACF,GAAkB,OAAOA,GAAmB,UAAYA,EAAe,KAAK,IAAM,GACrF,OAAOC,EAAIC,EAA2B,iBAAkB,4BAA4B,CAAC,EAGvF,IAAMC,EAAaL,EAAO,YAAcM,GACxCC,GAAYF,EAAY,YAAY,EAEpC,IAAMG,EAAYR,EAAO,WAAa,IACtC,OAAAS,EAAcD,EAAW,YAAa,IAAgB,GAAc,EAEhER,EAAO,aAAe,QACxBS,EAAcT,EAAO,WAAY,aAAc,EAAiB,EAAe,EAG7EA,EAAO,eAAiB,QAC1BS,EAAcT,EAAO,aAAc,eAAgB,IAAoB,GAAkB,EAIpFU,EAAG,IAAIX,EAAUC,CAAM,CAAC,CACjC,OAASW,EAAG,CACV,OAAIC,GAAiBD,CAAC,EACbR,EAAIQ,CAAC,EAEPR,EAAIC,EAA2B,SAAWO,EAAY,OAAO,CAAC,CACvE,CACF,CAMA,YAAYX,EAAyB,CACnC,KAAK,QAAUA,EAAO,UAAY,GAClC,KAAK,aACH,KAAK,SAAWA,EAAO,cAAgB,MAAQA,EAAO,eAAiB,GACnEA,EAAO,aACPa,GAEN,IAAMZ,EAAQD,EAAO,MACfE,EAAiBF,EAAO,eAI9B,GAAI,CAACC,GAAS,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAC1D,MAAMG,EAA2B,QAAS,4BAA4B,EAExE,GAAI,CAACF,GAAkB,OAAOA,GAAmB,UAAYA,EAAe,KAAK,IAAM,GACrF,MAAME,EAA2B,iBAAkB,4BAA4B,EAGjF,IAAMC,EAAaL,EAAO,YAAcM,GAExCC,GAAYF,EAAY,YAAY,EAEpC,IAAMG,EAAYR,EAAO,WAAa,IACtCS,EAAcD,EAAW,YAAa,IAAgB,GAAc,EAEhER,EAAO,aAAe,QACxBS,EAAcT,EAAO,WAAY,aAAc,EAAiB,EAAe,EAG7EA,EAAO,eAAiB,QAC1BS,EAAcT,EAAO,aAAc,eAAgB,IAAoB,GAAkB,EAG3F,IAAMc,EAAad,EAAO,YAAc,EAClCe,EAAef,EAAO,cAAgB,IACtCgB,EAAa,IAAIC,GAAgBT,EAAWM,EAAYC,EAAcf,EAAO,MAAM,EAEnFkB,EACJlB,EAAO,SACN,OAAO,OAAW,KAAe,QAAQ,UAAU,OAChD,OAAO,SAAS,OAChB,QAEAmB,EAAyC,CAC7C,WAAYlB,EAAM,KAAK,EACvB,cAAe,UAAUC,EAAe,KAAK,CAAC,GAC9C,GAAIgB,GAAgB,CAAE,OAAQA,CAAa,CAC7C,EAEA,KAAK,UAAY,IAAIE,GAAUJ,EAAYX,EAAYc,CAAc,EACrE,KAAK,aAAe,IAAIE,GAEpBrB,EAAO,kBACT,KAAK,gBACHA,EAAO,iBACPsB,GAA6BtB,EAAO,mBAAqBuB,EAA0B,GAGvF,KAAK,YAAc,IAAIC,GACrB,KAAK,UACL,KAAK,aACL,KAAK,QACL,KAAK,aACL,KAAK,eACP,EACA,KAAK,gBAAkB,IAAIC,GAAgB,KAAK,UAAW,KAAK,YAAY,EAC5E,KAAK,WAAa,IAAIC,GAAkB,KAAK,SAAS,EACtD,KAAK,mBAAqB,IAAIC,GAAmB,KAAK,SAAS,CACjE,CAEA,OAAO,aAAuB,CAC5B,OAAOC,GAAoB,CAC7B,CAEA,MAAM,SAASC,EAA2E,CACxF,OAAO,KAAK,YAAY,SAASA,CAAO,CAC1C,CAEA,MAAM,aACJA,EACqD,CACrD,OAAO,KAAK,YAAY,aAAaA,CAAO,CAC9C,CAEA,MAAM,gBACJC,EAC0D,CAC1D,OAAI,KAAK,SAAWA,IAAiB,KAAK,aACjC,QAAQ,QACbpB,EAAG,CACD,MAAO,GACP,QAAS,eACT,iBAAkB,UAClB,UAAW,iBACX,OAAQ,aACV,CAAC,CACH,EAEK,KAAK,UAAU,gBAAgBoB,CAAY,CACpD,CAEA,MAAM,WAAmC,CACvC,OAAOC,GAAgB,CACzB,CAEA,GAAGC,EAAuBC,EAAmC,CAC3D,OAAO,KAAK,aAAa,GAAGD,EAAOC,CAAO,CAC5C,CAEA,SAAkB,CAChB,MAA4C,OAC9C,CAEA,SAAW,CACT,MAAO,CACL,MAAO,MAAOJ,GACL,KAAK,UAAU,mBAAmBA,CAAO,EAElD,OAAQ,MACNA,GAC+D,CAC/D,IAAMK,EAAS,MAAM,KAAK,UAAU,gBAAgB,CAClD,OAAQL,EAAQ,OAChB,KAAMA,EAAQ,KACd,GAAIA,EAAQ,YAAc,CAAE,WAAYA,EAAQ,UAAW,CAC7D,CAAC,EACD,OAAKK,EAAO,GACLxB,EAAG,CACR,aAAcwB,EAAO,MAAM,aAC3B,GAAIA,EAAO,MAAM,aAAe,CAAE,YAAaA,EAAO,MAAM,WAAY,CAC1E,CAAC,EAJsBA,CAKzB,CACF,CACF,EAEA,KAAO,CACL,YAAa,CACX,KAAM,IAAM,KAAK,mBAAmB,KAAK,EACzC,iBAAmBL,GACjB,KAAK,mBAAmB,iBAAiBA,GAAW,CAAC,CAAC,EACxD,eAAgB,CAACM,EAAmBC,EAAsBC,IACxD,KAAK,mBAAmB,eAAeF,EAAWC,EAAQC,CAAY,EACxE,WAAaF,GAAsB,KAAK,UAAU,sBAAsBA,CAAS,EACjF,QAAUA,GAAsB,KAAK,mBAAmB,QAAQA,CAAS,CAC3E,EACA,eAAiBN,GAAmC,KAAK,gBAAgB,QAAQA,CAAO,CAC1F,CACF,EC7OO,SAASS,GAAgBC,EAAyC,CACvE,IAAMC,EAASC,GAAU,OAAO,CAC9B,MAAOF,EAAO,MACd,eAAgBA,EAAO,cACzB,CAAC,EAED,MAAI,CAACC,EAAO,IAAMA,EAAO,OAAS,KACzB,KAGFA,EAAO,KAChB,CAGO,SAASE,GAAeC,EAA+C,CAC5E,GAAIA,GAAa,MAAQ,OAAOA,GAAc,SAAU,MAAO,GAE/D,IAAMC,EAAQD,EAERE,EAAkB,OAAOD,EAAM,cAAiB,WAChDE,EAAc,OAAOF,EAAM,UAAa,WACxCG,EAAQ,OAAOH,EAAM,IAAO,WAElC,OAAOC,GAAmBC,GAAeC,CAC3C,CAGO,SAASC,GAAkBC,EAAgD,CAChF,OAAOA,EAAiB,CAAE,eAAAA,CAAe,EAAI,CAAC,CAChD,CCnCO,IAAMC,GAAc,cAGdC,GAAsB,sBAGtBC,EAAe,eAGfC,EAAiB,iBAGjBC,GAAe,eAGfC,GAAe,eAGfC,GAAmB,mBAGnBC,GAAkB,kBAGlBC,GAAoB,oBCqBjC,SAASC,GACPC,EACAC,EACAC,EACAC,EACM,CACNH,EAAK,cACH,IAAI,YAAYC,EAAM,CACpB,OAAAC,EACA,QAASC,EAAQ,QACjB,SAAUA,EAAQ,QACpB,CAAC,CACH,CACF,CAGA,SAASC,GAAkBC,EAAgD,CACzE,OAAOA,IAAO,eAAiB,QAAU,UAC3C,CAMA,SAASC,GAAeC,EAAiD,CACvE,GAAIA,GAAO,MAAQ,OAAOA,GAAQ,SAAU,OAC5C,IAAMC,EAAID,EACJE,EAASD,EAAE,OACjB,GAAI,OAAOC,GAAW,UAAYA,EAAO,SAAW,EAAG,OACvD,IAAMC,EAAgC,CAAE,OAAAD,CAAO,EAC/C,OAAI,OAAOD,EAAE,gBAAmB,WAAUE,EAAO,eAAiBF,EAAE,gBAChE,OAAOA,EAAE,OAAU,WAAUE,EAAO,MAAQF,EAAE,OAC9CA,EAAE,UAAY,MAAQ,OAAOA,EAAE,UAAa,UAAY,CAAC,MAAM,QAAQA,EAAE,QAAQ,IACnFE,EAAO,SAAWF,EAAE,UAEfE,CACT,CAEA,SAASC,GAAmBJ,EAAuC,CACjE,OACEA,GAAO,MACP,OAAOA,GAAQ,UACdA,EAAyB,OAAS,UACjCA,EAAyB,YAAc,YACtCA,EAAyB,YAAc,eAE9C,CAEA,SAASK,GAAqBL,EAAyC,CACrE,IAAMC,EAAID,EACV,OACEA,GAAO,MACP,OAAOA,GAAQ,UACfC,EAAE,OAAS,WACX,OAAOA,EAAE,OAAU,WAClBA,EAAE,YAAc,YAAcA,EAAE,YAAc,eAEnD,CAEA,SAASK,GAAmBN,EAAuC,CACjE,OAAOA,GAAO,MAAQ,OAAOA,GAAQ,UAAaA,EAAyB,OAAS,OACtF,CAEA,SAASO,GAAuBP,EAA2C,CACzE,OACEA,GAAO,MACP,OAAOA,GAAQ,UACdA,EAA6B,OAAS,cACrCA,EAA6B,YAAc,YAC1CA,EAA6B,YAAc,eAElD,CAGA,IAAMQ,GAAqC,CACzC,UAAUC,EAAsBhB,EAA+B,CAC7D,GAAIgB,GAAQ,MAAQhB,GAAQ,KAC1B,MAAM,IAAI,UAAU,0DAA0D,EAEhF,IAAMiB,EAAkC,CAAC,EACrCC,EAA6C,eAC7CC,EAA6B,GAE3BC,EAAWJ,EAAK,GAAG,QAAUK,GAAqB,CACtD,GAAI,CAACV,GAAmBU,CAAO,EAAG,OAClCH,EAAgBG,EAAQ,UACxBF,EAA6B,GAC7B,IAAMjB,EAAgC,CACpC,UAAWE,GAAkBiB,EAAQ,SAAS,EAC9C,GAAI,OAAOA,EAAQ,OAAU,UAAY,CAAE,MAAOA,EAAQ,KAAM,CAClE,EACAtB,GAA2CC,EAAMsB,GAAcpB,EAAQ,CACrE,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAAC,EACDe,EAAa,KAAKG,CAAQ,EAE1B,IAAMG,EAAaP,EAAK,GAAG,UAAYK,GAAqB,CAG1D,GAFI,CAACT,GAAqBS,CAAO,GAC7BF,GACAE,EAAQ,MAAM,SAAW,EAAG,OAChCF,EAA6B,GAC7B,IAAMK,EAAalB,GAAee,EAAQ,IAAI,EACxCnB,EAA8B,CAClC,UAAWE,GAAkBiB,EAAQ,SAAS,EAC9C,MAAOA,EAAQ,MACf,GAAI,OAAOA,EAAQ,OAAU,UAAY,CAAE,MAAOA,EAAQ,KAAM,EAChE,GAAIG,IAAe,QAAa,CAAE,KAAMA,CAAW,EACnD,GAAI,OAAOH,EAAQ,aAAgB,UAAY,CAAE,YAAaA,EAAQ,WAAY,CACpF,EAEAtB,GAAyCC,EAAMyB,EAAgBvB,EAAQ,CACrE,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAAC,EACDe,EAAa,KAAKM,CAAU,EAE5B,IAAMG,EAAWV,EAAK,GAAG,QAAUK,GAAqB,CAEtD,GADI,CAACR,GAAmBQ,CAAO,GAC3BF,EAA4B,OAChC,IAAMQ,EAAON,EAAQ,OAAO,MAAQ,gBAC9BnB,EAA4B,CAChC,UAAWE,GAAkBiB,EAAQ,WAAaH,CAAa,EAC/D,KAAAS,EACA,QACE,OAAON,EAAQ,OAAO,SAAY,SAAWA,EAAQ,MAAM,QAAU,gBACvE,GAAI,OAAOA,EAAQ,OAAU,UAAY,CAAE,MAAOA,EAAQ,KAAM,CAClE,EACAtB,GAAuCC,EAAM4B,GAAc1B,EAAQ,CACjE,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAAC,EACDe,EAAa,KAAKS,CAAQ,EAE1B,IAAMG,EAAeb,EAAK,GAAG,YAAcK,GAAqB,CAC9D,GAAI,CAACP,GAAuBO,CAAO,EAAG,OACtC,IAAMnB,EAAgC,CACpC,UAAWE,GAAkBiB,EAAQ,SAAS,EAC9C,GAAI,OAAOA,EAAQ,OAAU,UAAY,CAAE,MAAOA,EAAQ,KAAM,CAClE,EACAtB,GAA2CC,EAAM8B,GAAkB5B,EAAQ,CACzE,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAAC,EACD,OAAAe,EAAa,KAAKY,CAAY,EAEvB,UAA6B,CAClC,QAAWE,KAAOd,EAChBc,EAAI,CAER,CACF,CACF,ECtMA,SAASC,GAAoBC,EAAsC,CACjE,MAAO,CACL,mBAAoBA,EAAO,mBAC3B,+BAAgCA,EAAO,+BACvC,gBAAiBA,EAAO,eAC1B,CACF,CAKO,SAASC,IAAwC,CACtD,MAAO,CACL,gBAAiB,SAAqC,CACpD,IAAMD,EAAS,MAAME,GAAgB,EACrC,OAAOH,GAAoBC,CAAM,CACnC,CACF,CACF,CAKO,SAASG,GAA4BC,EAA8B,CACxE,IAAMC,EAAYD,EAClB,GAAI,OAAOC,EAAU,WAAc,WACjC,OAAOJ,GAAuB,EAGhC,IAAMK,EAAYD,EAAU,UAE5B,MAAO,CACL,gBAAiB,SAAqC,CACpD,IAAML,EAAS,MAAMM,EAAU,EAC/B,OAAOP,GAAoBC,CAAM,CACnC,CACF,CACF,CCfO,SAASO,GAAsBC,EAAyD,CAC7F,OAAO,IAAI,YAA8BC,GAAa,CACpD,OAAAD,EACA,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAEO,SAASE,GAAuBF,EAA2D,CAChG,OAAO,IAAI,YAA+BG,EAAc,CACtD,OAAAH,EACA,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAEO,SAASI,GACdJ,EACoC,CACpC,OAAO,IAAI,YAAmCK,GAAkB,CAC9D,OAAAL,EACA,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAEO,SAASM,GACdN,EACmC,CACnC,OAAO,IAAI,YAAkCO,GAAiB,CAC5D,OAAAP,EACA,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CAEO,SAASQ,GAA2BR,EAAuD,CAChG,OAAO,IAAI,YAA6BS,GAAmB,CACzD,OAAAT,EACA,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CC7DO,IAAMU,GAAN,KAAqB,CAClB,cAAyBC,EACzB,mBAAqC,KACrC,aAAe,GACf,kBAA0C,eAC1C,cAAoC,OACpC,kBAAoB,EAE5B,IAAI,cAAwB,CAC1B,OAAO,KAAK,aACd,CAEA,SAASC,EAAqB,CAC5B,KAAK,cAAgBA,EACrB,KAAK,aAAe,EACtB,CAEA,kBAAyB,CACvB,KAAK,aAAe,EACtB,CAMA,uBAAiC,CAC/B,MAAI,CAAC,KAAK,cAAgB,KAAK,gBAAkB,KAAK,mBAC7C,IAET,KAAK,mBAAqB,KAAK,cAC/B,KAAK,aAAe,GACb,GACT,CAEA,2BAA2BC,EAAoB,CAC7C,KAAK,kBAAoBA,IAAQ,QAAU,eAAiB,UAC9D,CAEA,IAAI,kBAAyC,CAC3C,OAAO,KAAK,iBACd,CAEA,SAASC,EAAiC,CACxC,KAAK,cAAgBA,CACvB,CAEA,wCAAuE,CACrE,GAAI,KAAK,gBAAkB,iBAAkB,OAAO,KACpD,IAAMC,EAAgC,CACpC,UAAW,KAAK,oBAAsB,eAAiB,QAAU,KAAK,kBACtE,GAAI,KAAK,gBAAkB,QAAa,CAAE,MAAO,KAAK,aAAc,CACtE,EACA,YAAK,cAAgB,OACdA,CACT,CAEA,mBAA0B,CACxB,IAAMH,EAAOI,EAAyB,qBAAqB,KAAK,aAAa,EACzEJ,IAAS,MACb,KAAK,SAASA,CAAI,CACpB,CAEA,iBAAwB,CACtB,IAAMA,EAAOI,EAAyB,mBAAmB,KAAK,aAAa,EACvEJ,IAAS,MACb,KAAK,SAASA,CAAI,CACpB,CAEA,aAAaG,EAAiD,CACxDA,GAAQ,QAAU,SACpB,KAAK,cAAgBA,EAAO,MAEhC,CAEA,mBAAmBE,EAA2BJ,EAAcK,EAAiC,CAE3F,GADI,CAACD,GACD,CAACE,GAAa,KAAK,aAAa,EAAG,OACvC,KAAK,2BAA2BN,CAAG,EACnC,IAAMD,EAAOI,EAAyB,UACpC,KAAK,cACOH,EACZI,EACAC,CACF,EACA,KAAK,SAASN,CAAI,CACpB,CAEA,MAAM,WAAWQ,EAAyE,CACxF,IAAMC,EAAY,EAAE,KAAK,kBACzB,KAAK,SAASL,EAAyB,aAAa,KAAK,aAAa,CAAC,EACvE,IAAMM,EAAY,MAAMN,EAAyB,YAAY,CAC3D,GAAGI,EACH,aAAc,KAAK,aACrB,CAAC,EACD,OAAIC,IAAc,KAAK,kBACd,KAEFC,CACT,CAEA,OAAc,CACZ,KAAK,cAAgBN,EAAyB,MAAM,KAAK,aAAa,EACtE,KAAK,mBAAqB,KAC1B,KAAK,aAAe,GACpB,KAAK,cAAgB,MACvB,CAEA,kBAAkBO,EAAsB,CACtC,KAAK,cAAgBA,EACrB,KAAK,aAAe,EACtB,CACF,ECpGO,IAAeC,GAAf,cAAuC,WAAY,CAC9C,YAAc,IAAIC,GAClB,mBAA0C,KAC1C,MAA6B,KAC7B,gBAAqC,KAGrC,SAASC,EAAqB,CACtC,KAAK,YAAY,SAASA,CAAI,EAC9B,KAAK,uBAAuB,CAC9B,CAGU,kBAAyB,CACjC,KAAK,YAAY,iBAAiB,EAClC,KAAK,uBAAuB,CAC9B,CAGU,wBAA+B,CAClC,KAAK,YACL,KAAK,YAAY,sBAAsB,GAC5C,KAAK,QAAQ,CACf,CAGU,gCAA0C,CAClD,IAAMC,EAAS,KAAK,YAAY,uCAAuC,EACvE,OAAKA,GACL,KAAK,cAAcC,GAA2BD,CAAM,CAAC,EAC9C,IAFa,EAGtB,CAOA,WAAWE,EAAqB,CAI9B,GAHI,KAAK,QAAU,MACjB,KAAK,cAAc,EAEjBA,GAAQ,KAAM,CAChB,KAAK,MAAQ,KACb,KAAK,YAAY,MAAM,EACvB,KAAK,uBAAuB,EAC5B,MACF,CACA,GAAI,CAACC,GAAeD,CAAI,EACtB,MAAM,IAAI,MAAM,0EAA0E,EAE5F,KAAK,MAAQA,EACb,KAAK,mBAAqBE,GAAmB,UAAU,KAAK,MAAO,IAAI,EACvE,KAAK,qBAAqB,EAC1B,KAAK,YAAY,CACnB,CAEU,eAAsB,CAC9B,KAAK,qBAAqB,EAC1B,KAAK,mBAAqB,KAC1B,KAAK,oBAAoB,eAAgB,KAAK,cAAc,EAC5D,KAAK,oBAAoB,iBAAkB,KAAK,gBAAgB,EAChE,KAAK,oBAAoB,eAAgB,KAAK,cAAc,EAC5D,KAAK,MAAQ,IACf,CAEU,sBAA6B,CACrC,KAAK,oBAAoB,eAAgB,KAAK,cAAc,EAC5D,KAAK,oBAAoB,iBAAkB,KAAK,gBAAgB,EAChE,KAAK,oBAAoB,eAAgB,KAAK,cAAc,EAC5D,KAAK,iBAAiB,eAAgB,KAAK,cAAc,EACzD,KAAK,iBAAiB,iBAAkB,KAAK,gBAAgB,EAC7D,KAAK,iBAAiB,eAAgB,KAAK,cAAc,CAC3D,CAEU,iBAAmB,IAAY,CACvC,KAAK,YAAY,kBAAkB,EACnC,KAAK,uBAAuB,CAC9B,EAEU,eAAiB,IAAY,CACrC,KAAK,YAAY,gBAAgB,EACjC,KAAK,uBAAuB,CAC9B,EAEU,eAAkBC,GAAmB,CAC7C,IAAML,EAAUK,EAAyC,OACzD,KAAK,YAAY,aAAaL,CAAM,CACtC,EAMU,oBAA2B,CAC9B,KAAK,OACL,KAAK,aAAa,IACvB,KAAK,YAAY,mBAAmB,KAAK,MAAO,KAAK,WAAW,EAAG,KAAK,mBAAmB,CAAC,EAC5F,KAAK,uBAAuB,EAC9B,CAKU,iBAAiBM,EAA6B,CACtD,IAAMN,EACJM,IAAS,OACL,CAAE,GAAG,KAAK,kBAAkB,EAAG,aAAcA,CAAK,EAClD,KAAK,kBAAkB,EAC7B,KAAK,cAAcC,GAA0BP,CAAM,CAAC,CACtD,CAEA,MAAgB,aAA6B,CAC3C,GAAI,CAAC,KAAK,MAAO,OACjB,IAAMQ,EAA2B,CAC/B,GAAG,KAAK,iBAAiB,EACzB,cAAeC,GAA4B,KAAK,KAAK,CAEvD,EACMC,EAAY,MAAM,KAAK,YAAY,WAAWF,CAAM,EACtDE,IAAc,OACd,CAAC,KAAK,OAAS,CAAC,KAAK,aACzB,KAAK,SAASA,CAAS,EACzB,CAEU,mCAA0C,CAClD,GAAI,KAAK,QAAU,KAAM,OACzB,IAAMC,EAAS,KAAK,cAAc,EAClC,GAAI,CAACA,EAAQ,OACb,IAAMT,EAAOU,GAAgBD,CAAM,EACnC,GAAI,CAACT,EAAM,CACT,KAAK,WAAW,IAAI,EACpB,MACF,CACA,KAAK,WAAWA,CAAI,CACtB,CAGU,0BAAiC,CACzC,IAAMW,EAAa,KAAK,cAAc,EAQtC,GANG,KAAK,kBAAoB,MAAQA,IAAe,MAChD,KAAK,kBAAoB,MACxBA,IAAe,MACf,KAAK,gBAAgB,QAAUA,EAAW,OAC1C,KAAK,gBAAgB,iBAAmBA,EAAW,eAEvC,OAIhB,GAFA,KAAK,gBAAkBA,EAEnBA,IAAe,KAAM,CACvB,KAAK,WAAW,IAAI,EACpB,MACF,CAEA,IAAMX,EAAOU,GAAgBC,CAAU,EACvC,KAAK,WAAWX,GAAQ,IAAI,CAC9B,CAEA,sBAA6B,CAC3B,KAAK,cAAc,CACrB,CAGA,IAAI,cAAwB,CAC1B,OAAO,KAAK,YAAY,YAC1B,CAMA,OAAc,CACZ,KAAK,+BAA+B,EACpC,KAAK,YAAY,MAAM,EACvB,KAAK,uBAAuB,CAC9B,CAGA,kBAAkBY,EAAsB,CACtC,KAAK,YAAY,kBAAkBA,CAAK,EACxC,KAAK,uBAAuB,CAC9B,CASF,EC/KA,SAASC,GAAeC,EAAiC,CACvD,GAAIA,GAAS,MAAQA,EAAM,KAAK,IAAM,GAAI,OAAOC,EACjD,IAAMC,EAAQF,EAAM,MAAM,GAAG,EAAE,IAAKG,GAAMA,EAAE,KAAK,CAAC,EAC5CC,EAAWF,EAAM,CAAC,GAAKD,EAAmB,SAC1CI,EAAQH,EAAM,CAAC,GAAKD,EAAmB,MAC7C,MAAO,CAAE,SAAAG,EAAU,MAAAC,CAAM,CAC3B,CAKO,SAASC,GAAgCC,EAA6C,CAC3F,IAAMC,EAAM,CACV,KAAMC,GAAaF,EAAQ,aAAa,MAAM,CAAC,EAC/C,KAAMG,EAAUH,EAAQ,aAAa,MAAM,EAAGI,GAAqBC,EAA0B,EAC7F,IAAKF,EAAUH,EAAQ,aAAa,KAAK,EAAGM,GAAWC,EAAW,EAClE,UAAWf,GAAeQ,EAAQ,aAAa,YAAY,CAAC,EAC5D,MAAOG,EAAUH,EAAQ,aAAa,OAAO,EAAGQ,EAAaC,CAAa,EAC1E,UAAWC,EAAoBV,EAAQ,aAAa,YAAY,CAAC,EACjE,cAAeU,EAAoBV,EAAQ,aAAa,gBAAgB,CAAC,EACzE,iBAAkBW,GAAqBX,EAAQ,aAAa,oBAAoB,CAAC,EACjF,aAAcY,GAAkBZ,EAAQ,aAAa,eAAe,EAAGa,EAAc,EACrF,MAAOC,EAAYd,EAAQ,aAAa,QAAQ,CAAC,EACjD,eAAgBc,EAAYd,EAAQ,aAAa,iBAAiB,CAAC,EACnE,QAASU,EAAoBV,EAAQ,aAAa,UAAU,CAAC,EAC7D,YAAaU,EAAoBV,EAAQ,aAAa,cAAc,CAAC,EACrE,kBAAmBU,EAAoBV,EAAQ,aAAa,oBAAoB,CAAC,EACjF,eAAgBU,EAAoBV,EAAQ,aAAa,kBAAkB,CAAC,EAC5E,aAAcG,EACZH,EAAQ,aAAa,eAAe,EACpCe,GACAC,EACF,CACF,EACA,OAAOC,GAA4BhB,CAAG,CACxC,CCpCA,SAASiB,GAAcC,EAAqC,CAC1D,IAAIC,EAAUD,EAAW,cAA2B,IAAIE,EAAa,EAAE,EACvE,OAAKD,IACHA,EAAU,SAAS,cAAc,KAAK,EACtCA,EAAQ,UAAYC,GACpBF,EAAW,YAAYC,CAAO,GAEzBA,CACT,CAEA,SAASE,GAAcF,EAAmC,CACxD,IAAIG,EAAUH,EAAQ,cAA2B,IAAII,EAAa,EAAE,EACpE,OAAKD,IACHA,EAAU,SAAS,cAAc,KAAK,EACtCA,EAAQ,UAAYC,GACpBD,EAAQ,aAAa,cAAe,MAAM,EAC1CH,EAAQ,YAAYG,CAAO,GAEtBA,CACT,CAEA,SAASE,GAAYL,EAAmC,CACtD,IAAIM,EAAQN,EAAQ,cAA2B,IAAIO,EAAW,EAAE,EAChE,OAAKD,IACHA,EAAQ,SAAS,cAAc,KAAK,EACpCA,EAAM,UAAYC,GAClBP,EAAQ,YAAYM,CAAK,GAEpBA,CACT,CAGA,SAASE,GAAmBF,EAAoBG,EAAgC,CAC9EH,EAAM,aAAa,OAAQ,QAAQ,EACnCA,EAAM,aAAa,aAAcG,IAAS,QAAU,OAAS,OAAO,EACpEH,EAAM,aAAa,kBAAmBI,EAAsB,EAC5DJ,EAAM,aAAa,mBAAoBK,EAAqB,CAC9D,CAGA,SAASC,GAAgCN,EAAoBO,EAAqC,CAChG,IAAIC,EAAUR,EAAM,cAA2B,IAAII,EAAsB,EAAE,EACtEI,IACHA,EAAU,SAAS,cAAc,IAAI,EACrCA,EAAQ,GAAKJ,GACbI,EAAQ,UAAY,sBACpBR,EAAM,aAAaQ,EAASR,EAAM,UAAU,GAE9C,IAAMS,EACJF,EAAO,aAAa,KAAK,IACxBA,EAAO,SAAS,KAAK,EAAIG,GAAsBH,EAAO,QAAQ,KAAK,CAAC,EAAII,IAC3EH,EAAQ,YAAcC,EAEtB,IAAIG,EAASZ,EAAM,cAA2B,IAAIK,EAAqB,EAAE,EACpEO,IACHA,EAAS,SAAS,cAAc,GAAG,EACnCA,EAAO,GAAKP,GACZO,EAAO,UAAY,qBACnBZ,EAAM,aAAaY,EAAQJ,EAAQ,WAAW,GAEhDI,EAAO,YAAcL,EAAO,mBAAmB,KAAK,GAAKM,EAC3D,CAGA,SAASC,GAAkBd,EAA0B,CACnD,IAAIe,EAAMf,EAAM,cAAiC,IAAIgB,EAAwB,EAAE,EAC3ED,IACJA,EAAM,SAAS,cAAc,QAAQ,EACrCA,EAAI,KAAO,SACXA,EAAI,UAAYC,GAChBD,EAAI,aAAa,aAAcE,EAA6B,EAC5DF,EAAI,aAAa,0BAA2B,MAAM,EAClDA,EAAI,YAAc,OAClBf,EAAM,YAAYe,CAAG,EACvB,CAEA,SAASG,GACPlB,EACAmB,EACa,CACb,IAAIC,EAAOpB,EAAM,cAA2B,IAAIqB,EAAU,EAAE,EAC5D,GAAI,CAACD,EAAM,CACTA,EAAO,SAAS,cAAc,KAAK,EACnCA,EAAK,UAAYC,GACjBD,EAAK,aAAa,OAAQ,SAAS,EACnC,IAAME,EAAc,SAAS,cAAc,QAAQ,EACnDA,EAAY,KAAO,SACnBA,EAAY,aAAa,WAAY,UAAU,EAC/CA,EAAY,aAAa,OAAQ,KAAK,EACtC,IAAMC,EAAW,SAAS,cAAc,QAAQ,EAChDA,EAAS,KAAO,SAChBA,EAAS,aAAa,WAAY,OAAO,EACzCA,EAAS,aAAa,OAAQ,KAAK,EACnCH,EAAK,YAAYE,CAAW,EAC5BF,EAAK,YAAYG,CAAQ,EACzB,IAAMC,EAAYxB,EAAM,cAA2B,IAAIK,EAAqB,EAAE,EAC9EL,EAAM,aAAaoB,EAAMI,EAAYA,EAAU,YAAcxB,EAAM,UAAU,CAC/E,CACA,GAAM,CAACsB,EAAaC,CAAQ,EAAIH,EAAK,iBAAiB,QAAQ,EAC9D,OAAIE,IAAaA,EAAY,YAAcH,EAAU,UACjDI,IAAUA,EAAS,YAAcJ,EAAU,OACxCC,CACT,CAGA,SAASK,GAA0BzB,EAAiC,CAClE,IAAIN,EAAUM,EAAM,cAA2B,IAAI0B,EAAqB,EAAE,EAC1E,GAAI,CAAChC,EAAS,CACZA,EAAU,SAAS,cAAc,KAAK,EACtCA,EAAQ,UAAYgC,GACpB,IAAMC,EAAY3B,EAAM,cAAc,IAAIqB,EAAU,EAAE,EACtDrB,EAAM,aAAaN,EAASiC,EAAYA,EAAU,YAAc3B,EAAM,UAAU,CAClF,CACA,OAAON,CACT,CAGA,SAASkC,IAA8B,CACrC,IAAMC,EAAM,SAAS,gBAAgBC,EAAQ,KAAK,EAClDD,EAAI,aAAa,UAAW,WAAW,EACvCA,EAAI,aAAa,cAAe,MAAM,EACtCA,EAAI,aAAa,QAAS,gBAAgB,EAC1CA,EAAI,aAAa,OAAQ,cAAc,EACvC,IAAME,EAAO,SAAS,gBAAgBD,EAAQ,MAAM,EACpD,OAAAC,EAAK,aACH,IACA,8LACF,EACAF,EAAI,YAAYE,CAAI,EACbF,CACT,CAGA,SAASG,IAAoD,CAC3D,IAAMC,EAAO,SAAS,uBAAuB,EACvCC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAYC,GACjB,IAAMC,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,UAAY,+BACdA,EAAE,YAAcC,GAChBH,EAAK,YAAYE,CAAC,EAClB,IAAMrB,EAAM,SAAS,cAAc,QAAQ,EAC3C,OAAAA,EAAI,KAAO,SACXA,EAAI,UAAY,gCAChBA,EAAI,aAAa,qBAAsBuB,CAAyB,EAChEvB,EAAI,aAAa,aAAcwB,EAAiC,EAChExB,EAAI,YAAYa,GAAgB,CAAC,EACjCM,EAAK,YAAYnB,CAAG,EACpBkB,EAAK,YAAYC,CAAI,EACdD,CACT,CAGA,SAASO,IAAoC,CAC3C,IAAMC,EAAK,SAAS,cAAc,KAAK,EACvCA,EAAG,UAAYC,GACfD,EAAG,aAAa,YAAa,QAAQ,EACrC,IAAME,EAAQ,SAAS,cAAc,MAAM,EAC3CA,EAAM,YAAcC,GACpB,IAAMC,EAAO,SAAS,cAAc,MAAM,EAC1C,OAAAA,EAAK,UAAY,iBACjBA,EAAK,aAAa,cAAe,MAAM,EACvCJ,EAAG,YAAYE,CAAK,EACpBF,EAAG,YAAYI,CAAI,EACZJ,CACT,CAGA,SAASK,IAAiC,CACxC,IAAML,EAAK,SAAS,cAAc,KAAK,EACvC,OAAAA,EAAG,UAAYM,GACfN,EAAG,aAAa,YAAa,QAAQ,EACrCA,EAAG,YAAcO,GACVP,CACT,CAGA,SAASQ,GAAsBjD,EAAqC,CAClE,IAAMN,EAAU+B,GAA0BzB,CAAK,EAC3CkC,EAAOxC,EAAQ,cAA2B,IAAIwD,CAAuB,EAAE,EAC3E,GAAI,CAAChB,EAAM,CACTA,EAAO,SAAS,cAAc,KAAK,EACnCA,EAAK,UAAYgB,EACjBhB,EAAK,aAAa,qBAAsB,SAAS,EAEjDA,EAAK,YAAYM,GAAqB,CAAC,EACvCN,EAAK,YAAYY,GAAkB,CAAC,EAEpC,IAAMK,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,UAAYC,GACrB,IAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,KAAOC,EACZD,EAAK,YAAYrB,GAAgC,CAAC,EAClDmB,EAAS,YAAYE,CAAI,EACzBnB,EAAK,YAAYiB,CAAQ,EAEzBzD,EAAQ,YAAYwC,CAAI,CAC1B,CACA,IAAMmB,EAAOnB,EAAK,cAA+B,cAAcoB,CAAiB,IAAI,EACpF,GAAI,CAACD,EAAM,CACT,IAAME,EAAU,SAAS,cAAc,MAAM,EAC7C,OAAAA,EAAQ,KAAOD,EACfC,EAAQ,YAAYvB,GAAgC,CAAC,EACrDE,EAAK,YAAYqB,CAAO,EACjBA,CACT,CACA,OAAOF,CACT,CAGA,SAASG,GAAgBxD,EAA0B,CACjD,IAAMN,EAAU+B,GAA0BzB,CAAK,EAC/C,GAAIN,EAAQ,cAAc,IAAI+D,EAAqB,EAAE,EAAG,OACxD,IAAMC,EAAM,SAAS,cAAc,KAAK,EACxCA,EAAI,UAAYD,GAChBC,EAAI,aAAa,cAAe,MAAM,EACtC,IAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,UAAY,wBACjBA,EAAK,YAAcC,GACnBF,EAAI,YAAYC,CAAI,EACpB,IAAMzB,EAAOxC,EAAQ,cAAc,IAAIwD,CAAuB,EAAE,EAChExD,EAAQ,aAAagE,EAAKxB,EAAOA,EAAK,YAAcxC,EAAQ,UAAU,CACxE,CAGA,SAASmE,GAA0B7D,EAAiC,CAClE,IAAMN,EAAU+B,GAA0BzB,CAAK,EAC3CqD,EAAO3D,EAAQ,cAA+B,kBAAkB,EACpE,GAAI,CAAC2D,EAAM,CACTA,EAAO,SAAS,cAAc,MAAM,EACpC,IAAMS,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,GAAKC,EACVD,EAAK,UAAY,cACjBT,EAAK,YAAYS,CAAI,EACrBpE,EAAQ,YAAY2D,CAAI,CAC1B,CACA,IAAIS,EAAO9D,EAAM,cAA2B,IAAI+D,CAAc,EAAE,EAChE,OAAKD,IACHA,EAAO,SAAS,cAAc,KAAK,EACnCA,EAAK,GAAKC,EACVD,EAAK,UAAY,cACjBT,EAAK,YAAYS,CAAI,GAEhBA,CACT,CAEA,SAASE,GAAmBhE,EAAqC,CAC/D,IAAIqD,EAAOrD,EAAM,cAA+B,cAAciE,EAAiB,IAAI,EACnF,OAAKZ,IACHA,EAAO,SAAS,cAAc,MAAM,EACpCA,EAAK,KAAOY,GACZjE,EAAM,YAAYqD,CAAI,GAEjBA,CACT,CAGA,SAASa,GAAoBlE,EAAoBmE,EAAuC,CACtF,IAAM/C,EAAOpB,EAAM,cAA2B,IAAIqB,EAAU,EAAE,EAC9D,GAAI,CAACD,EAAM,OACX,IAAMgD,EAAMhD,EAAK,cAAiC,uBAAuB,EACnEiD,EAAMjD,EAAK,cAAiC,oBAAoB,EAClEgD,GAAKA,EAAI,aAAa,gBAAiB,OAAOD,IAAc,UAAU,CAAC,EACvEE,GAAKA,EAAI,aAAa,gBAAiB,OAAOF,IAAc,OAAO,CAAC,CAC1E,CAGA,SAASG,GAAqB7E,EAAwBc,EAAqC,CACzF,GAAId,GAAc,MAAQc,GAAU,KAAM,OAC1C,IAAMb,EAAUF,GAAcC,CAAU,EACxCC,EAAQ,aAAa,4BAA6Ba,EAAO,YAAY,EACjEA,EAAO,OAAS,SAClBX,GAAcF,CAAO,EAEvB,IAAMM,EAAQD,GAAYL,CAAO,EACjCQ,GAAmBF,EAAOO,EAAO,IAAI,EACrCD,GAAgCN,EAAOO,CAAM,EAC7CO,GAAkBd,CAAK,EACvBkB,GAAWlB,EAAOO,EAAO,SAAS,EAClC0C,GAAsBjD,CAAK,EAC3BwD,GAAgBxD,CAAK,EACrB6D,GAA0B7D,CAAK,EAC/BgE,GAAmBhE,CAAK,EACxBkE,GAAoBlE,EAAOO,EAAO,GAAG,CACvC,CC3TA,SAASgE,GAAqBC,EAA0B,CAEtD,MADK,EAAAA,EAAuC,SAAW,IACnDA,EAAG,aAAa,aAAa,IAAM,OAEzC,CAGO,SAASC,GAAcC,EAAuC,CAEnE,OADmB,MAAM,KAAKA,EAAU,iBAA8BC,EAAkB,CAAC,EACvE,OAAQH,GAAOD,GAAqBC,CAAE,CAAC,CAC3D,CAWO,SAASI,GAAgBF,EAAyC,CACvE,IAAIG,EAAwC,KACxCC,EAAoD,KACpDC,EAAW,GAEf,SAASC,EAAcC,EAAwB,CAC7C,GAAIA,EAAE,MAAQ,MAAO,OACrB,IAAMC,EAAaT,GAAcC,CAAS,EAC1C,GAAIQ,EAAW,SAAW,EAAG,OAC7B,IAAMC,EAAUF,EAAE,kBAAkB,KAAQA,EAAE,OAAyB,KACjEG,EAAeD,EAAUD,EAAW,QAAQC,CAAO,EAAI,GACvDE,EAAYH,EAAW,OAAS,EAClCI,EACAL,EAAE,SACJK,EAAYF,GAAgB,EAAIC,EAAYD,EAAe,EAE3DE,EAAYF,GAAgBC,EAAY,EAAID,EAAe,EAE7D,IAAMG,EAAOL,EAAWI,CAAS,EAC7BC,IACFN,EAAE,eAAe,EACjBM,EAAK,MAAM,EAEf,CAEA,SAASC,GAAiB,CACxB,GAAIT,EAAU,OACdF,EAAwB,SAAS,cAEjC,IAAMY,EADahB,GAAcC,CAAS,EACjB,CAAC,EACtBe,GACFA,EAAM,MAAM,EAEdX,EAAeE,EACfN,EAAU,iBAAiB,UAAWI,EAAc,EAAI,EACxDC,EAAW,EACb,CAEA,SAASW,GAAmB,CAC1B,GAAI,CAACX,EAAU,OACXD,IACFJ,EAAU,oBAAoB,UAAWI,EAAc,EAAI,EAC3DA,EAAe,MAEjBC,EAAW,GACX,IAAMY,EAAOjB,EAAU,YAAY,GAA6B,eAAiB,SAC3EkB,EACJf,aAAiC,aAAec,EAAI,KAAK,SAASd,CAAqB,EACnFA,EACA,KACN,GAAIe,EACFA,EAAU,MAAM,MACX,CACL,IAAMC,EAAOF,EAAI,KACXG,EAAeD,EAAK,aAAa,UAAU,EACjDA,EAAK,aAAa,WAAY,IAAI,EAClCA,EAAK,MAAM,EACPC,IAAiB,KAAMD,EAAK,gBAAgB,UAAU,EACrDA,EAAK,aAAa,WAAYC,CAAY,CACjD,CACAjB,EAAwB,IAC1B,CAEA,MAAO,CAAE,SAAAW,EAAU,WAAAE,CAAW,CAChC,CCtFA,IAAMK,GAAsB,uBACtBC,GAAsB,uBACtBC,GAAoB,qBAIbC,GAA2B,CACtC,SACA,kBACA,OACA,mBACA,QACA,SACA,eACA,iBACA,eACA,mBACF,EAEaC,GAA4B,CACvC,OACA,OACA,MACA,aACA,QACA,aACA,iBACA,qBACA,gBACA,SACA,kBACA,WACA,eACA,qBACA,mBACA,gBACA,oBACF,EAIaC,GAAkB,CAC7B,QAAS,IAAIL,EAAmB,GAChC,QAAS,IAAIC,EAAmB,GAChC,MAAO,IAAIC,EAAiB,EAC9B,EAIaI,GAA8B,OChB3C,IAAMC,GAAqE,CACzE,QAAS,CAAE,OAAQ,SAAU,EAC7B,eAAgB,CAAE,OAAQ,QAAS,EACnC,MAAO,CAAE,OAAQ,OAAQ,CAC3B,EAEA,SAASC,GAAqBC,EAAmC,CAE/D,OADeF,GAAsBE,CAAK,GACzB,CAAE,OAAQC,EAA4B,CACzD,CAEO,IAAMC,GAAN,cAAwCC,EAAgB,CAC7D,WAAW,oBAA+B,CACxC,MAAO,CAAC,GAAGC,EAAyB,CACtC,CAEU,QAAiCC,GAAgC,IAAmB,EACtF,WAAqC,KACrC,wBAA+C,KAE/C,yBAA0C,KAC1C,iBAAkC,KAClC,mBAA0C,KAG1C,oBAAuBC,GAA2B,CACpDA,EAAE,MAAQ,UACT,KAAK,QAAQ,OAClBA,EAAE,eAAe,EACjB,KAAK,KAAO,GACd,EAEA,mBAA0B,CAExB,GADA,KAAK,iBAAiB,UAAW,KAAK,oBAAqB,EAAI,EAC3D,KAAK,WAAY,CACnB,KAAK,sBAAsB,EACvB,KAAK,QAAU,MAAQ,KAAK,qBAAuB,MACrD,KAAK,WAAW,KAAK,KAAK,EAE5B,MACF,CAEA,IAAMC,EAAS,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EAE3CC,EAAQC,GAAmC,EACjD,GAAID,EACFD,EAAO,mBAAqB,CAACC,CAAK,MAC7B,CACL,IAAME,EAAU,SAAS,cAAc,OAAO,EAC9CA,EAAQ,YAAcC,GAAuB,EAC7CJ,EAAO,YAAYG,CAAO,CAC5B,CAEA,KAAK,QAAUL,GAAgC,IAAI,EACnDO,GAAqBL,EAAQ,KAAK,OAAO,EACzC,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC3B,KAAK,kCAAkC,CACzC,CAEQ,uBAA8B,CAC/B,KAAK,aACV,KAAK,0BAA0B,EAC/B,KAAK,wBAA0BM,GAA8B,KAAK,WAAY,CAC5E,YAAcC,GAAQ,CACpB,KAAK,cAAcC,GAA2B,CAAE,IAAAD,CAAI,CAAC,CAAC,EACtD,KAAK,aAAa,MAAOA,CAAG,CAC9B,EACA,eAAgB,IAAM,KAAK,mBAAmB,EAC9C,gBAAkBE,GAAS,KAAK,iBAAiBA,CAAI,EACrD,eAAgB,IAAM,CACpB,KAAK,KAAO,EACd,EACA,aAAc,IAAM,CAClB,KAAK,KAAO,EACd,CACF,CAAC,EACH,CAEA,yBAAyBC,EAAcC,EAAyBC,EAAgC,CAC9F,GAAK,KAAK,WAEV,IADA,KAAK,QAAUd,GAAgC,IAAI,EAC/CY,IAAS,OAAQ,CACnB,GAAI,KAAK,QAAQ,MAAQC,IAAa,OAAQ,CAC5C,IAAME,EAA2B,CAAE,UAAW,KAAK,IAAI,CAAE,EACzD,KAAK,cAAcC,GAAsBD,CAAM,CAAC,EAChD,KAAK,iBAAiB,CACxB,CACA,GAAI,CAAC,KAAK,QAAQ,KAAM,CACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,MACF,CACF,CACIH,IAAS,QACX,KAAK,+BAA+B,EACpC,KAAK,SAASK,EAAyB,UAAU,KAAK,aAAc,KAAK,QAAQ,GAAG,CAAC,IAEnFL,IAAS,UAAYA,IAAS,oBAChC,KAAK,yBAAyB,EAEhCL,GAAqB,KAAK,WAAY,KAAK,OAAO,EAClD,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC7B,CAEQ,kBAAyB,CAC/B,IAAMW,EAAO,KAAK,WAClB,GAAI,CAACA,EAAM,OACX,IAAMC,EAAOD,EAAK,cAA2B,IAAIE,CAAuB,EAAE,EACpEC,EAAOH,EAAK,cAA+B,cAAcI,CAAiB,IAAI,EACpF,GAAI,CAACH,GAAQ,CAACE,EAAM,OACpBF,EAAK,aAAa,qBAAsB,SAAS,EACjD,IAAMI,EAAK,KAAK,IACd,IACA,SAAS,KAAK,aAAa,oBAAoB,GAAK,OAAO,IAA0B,EAAG,EAAE,GACxF,IACJ,EACA,KAAK,iBAAmB,OAAO,WAAW,IAAM,CAE9C,GADA,KAAK,iBAAmB,KACpB,CAAC,KAAK,WAAY,OACtB,IAAMC,EAAc,KAAK,WAAW,cAA2B,IAAIJ,CAAuB,EAAE,EACxFI,GAAa,aAAa,oBAAoB,IAAM,WACtDA,EAAY,aAAa,qBAAsB,SAAS,CAE5D,EAAGD,CAAE,EACL,IAAME,EAAe,IAAY,CAC/B,GAAIJ,EAAK,cAAc,EAAE,OAAS,EAAG,CACnC,KAAK,iBAAiB,EACtB,IAAMK,EAAI,KAAK,YAAY,cAA2B,IAAIN,CAAuB,EAAE,EAC/EM,GAAGA,EAAE,aAAa,qBAAsB,QAAQ,CACtD,CACF,EACA,KAAK,mBAAqBD,EAC1BJ,EAAK,iBAAiB,aAAcI,CAAY,EAC5CJ,EAAK,cAAc,EAAE,OAAS,GAAGI,EAAa,CACpD,CAEQ,kBAAyB,CAC3B,KAAK,kBAAoB,OAC3B,aAAa,KAAK,gBAAgB,EAClC,KAAK,iBAAmB,MAE1B,IAAMP,EAAO,KAAK,WAClB,GAAI,CAACA,EAAM,OACX,IAAMG,EAAOH,EAAK,cAA+B,cAAcI,CAAiB,IAAI,EAChFD,GAAQ,KAAK,qBACfA,EAAK,oBAAoB,aAAc,KAAK,kBAAkB,EAC9D,KAAK,mBAAqB,MAE5B,IAAMF,EAAOD,EAAK,cAA2B,IAAIE,CAAuB,EAAE,EACtED,GAAMA,EAAK,aAAa,qBAAsB,SAAS,CAC7D,CAGQ,mBAA0B,CAChC,KAAK,yBAA2B,KAEhC,IAAMJ,EAA4B,CAAE,OADhBrB,GAAqB,KAAK,YAAY,EACF,OAAQ,UAAW,KAAK,IAAI,CAAE,EACtF,KAAK,cAAciC,GAAuBZ,CAAM,CAAC,EACjD,KAAK,+BAA+B,EACpC,KAAK,SAASE,EAAyB,MAAM,KAAK,YAAY,CAAC,EAC1D,KAAK,aACVV,GAAqB,KAAK,WAAY,KAAK,OAAO,EAClD,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC7B,CAEA,IAAI,MAAgB,CAClB,OAAO,KAAK,QAAQ,IACtB,CACA,IAAI,KAAKqB,EAAgB,CACvB,KAAK,aAAa,OAAQA,EAAQ,OAAS,OAAO,CACpD,CAEA,IAAI,MAA2B,CAC7B,OAAO,KAAK,QAAQ,IACtB,CACA,IAAI,KAAKA,EAA2B,CAClC,KAAK,aAAa,OAAQA,CAAK,CACjC,CAEA,IAAI,KAA4B,CAC9B,OAAO,KAAK,QAAQ,GACtB,CACA,IAAI,IAAIA,EAA6B,CACnC,KAAK,aAAa,MAAOA,CAAK,CAChC,CAEA,IAAI,WAAoB,CACtB,MAAO,GAAG,KAAK,QAAQ,UAAU,QAAQ,IAAI,KAAK,QAAQ,UAAU,KAAK,EAC3E,CACA,IAAI,UAAUA,EAA2B,CACnCA,GAAS,MAAQA,IAAU,GAAI,KAAK,gBAAgB,YAAY,EAC/D,KAAK,aAAa,aAAcA,CAAK,CAC5C,CAEA,IAAI,OAA0B,CAC5B,OAAO,KAAK,QAAQ,KACtB,CACA,IAAI,MAAMA,EAAyB,CACjC,KAAK,aAAa,QAASA,CAAK,CAClC,CAEA,IAAI,WAA2B,CAC7B,OAAO,KAAK,QAAQ,SACtB,CACA,IAAI,UAAUA,EAAsB,CAC9BA,GAAS,KAAM,KAAK,gBAAgB,YAAY,EAC/C,KAAK,aAAa,aAAcA,CAAK,CAC5C,CAEA,IAAI,eAA+B,CACjC,OAAO,KAAK,QAAQ,aACtB,CACA,IAAI,cAAcA,EAAsB,CAClCA,GAAS,KAAM,KAAK,gBAAgB,gBAAgB,EACnD,KAAK,aAAa,iBAAkBA,CAAK,CAChD,CAEA,IAAI,kBAAmC,CACrC,OAAO,KAAK,QAAQ,gBACtB,CACA,IAAI,iBAAiBA,EAAuB,CACtCA,GAAS,KAAM,KAAK,gBAAgB,oBAAoB,EACvD,KAAK,aAAa,qBAAsBA,EAAQ,OAAS,OAAO,CACvE,CAEA,IAAI,cAA2C,CAC7C,OAAO,KAAK,QAAQ,YACtB,CACA,IAAI,aAAaA,EAAmC,CAC9CA,GAAS,KAAM,KAAK,gBAAgB,eAAe,EAClD,KAAK,aAAa,gBAAiBA,CAAK,CAC/C,CAEA,IAAI,OAAgB,CAClB,OAAO,KAAK,QAAQ,KACtB,CACA,IAAI,MAAMA,EAAe,CACvB,KAAK,aAAa,SAAUA,GAAS,EAAE,CACzC,CAEA,IAAI,gBAAyB,CAC3B,OAAO,KAAK,QAAQ,cACtB,CACA,IAAI,eAAeA,EAAe,CAChC,KAAK,aAAa,kBAAmBA,GAAS,EAAE,CAClD,CAEA,IAAI,SAAyB,CAC3B,OAAO,KAAK,QAAQ,OACtB,CACA,IAAI,QAAQA,EAAsB,CAC5BA,GAAS,KAAM,KAAK,gBAAgB,UAAU,EAC7C,KAAK,aAAa,WAAYA,CAAK,CAC1C,CAEA,IAAI,aAA6B,CAC/B,OAAO,KAAK,QAAQ,WACtB,CACA,IAAI,YAAYA,EAAsB,CAChCA,GAAS,KAAM,KAAK,gBAAgB,cAAc,EACjD,KAAK,aAAa,eAAgBA,CAAK,CAC9C,CAEA,IAAI,mBAAmC,CACrC,OAAO,KAAK,QAAQ,iBACtB,CACA,IAAI,kBAAkBA,EAAsB,CACtCA,GAAS,KAAM,KAAK,gBAAgB,oBAAoB,EACvD,KAAK,aAAa,qBAAsBA,CAAK,CACpD,CAEA,IAAI,gBAAgC,CAClC,OAAO,KAAK,QAAQ,cACtB,CACA,IAAI,eAAeA,EAAsB,CACnCA,GAAS,KAAM,KAAK,gBAAgB,kBAAkB,EACrD,KAAK,aAAa,mBAAoBA,CAAK,CAClD,CAOS,sBAA6B,CACpC,KAAK,0BAA0B,EAC/B,KAAK,wBAA0B,KAC/B,KAAK,oBAAoB,UAAW,KAAK,oBAAqB,EAAI,EAClE,MAAM,qBAAqB,CAC7B,CAES,OAAc,CACrB,KAAK,kBAAkB,CACzB,CAEU,YAAsB,CAC9B,OAAO,KAAK,QAAQ,GACtB,CAEU,oBAAyD,CACjE,IAAMC,EAAiB,KAAK,uBAAuB,EACnD,OAAOA,EAAiB,CAAE,eAAAA,CAAe,EAAI,CAAC,CAChD,CAGQ,wBAAwC,CAC9C,IAAMC,EAAW,KAAK,QAAQ,gBAAgB,KAAK,EACnD,OAAIA,IACA,KAAK,WAAW,IAAM,WAAmB,MAC7C,KAAK,2BACH,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,WAC1D,OAAO,WAAW,EAClB,KACC,KAAK,0BACd,CAGU,cAAwB,CAChC,MAAO,EACT,CAEU,kBAA6E,CACrF,MAAO,CACL,KAAkB,KAAK,QAAQ,IAC/B,iBAAkB,KAAK,QAAQ,kBAAoB,OACnD,aAAc,KAAK,QAAQ,YAC7B,CACF,CAEU,eAAkE,CAC1E,MAAI,CAAC,KAAK,QAAQ,OAAS,CAAC,KAAK,QAAQ,eAAuB,KACzD,CAAE,MAAO,KAAK,QAAQ,MAAO,eAAgB,KAAK,QAAQ,cAAe,CAClF,CAEU,mBAA0C,CAClD,MAAO,CAAE,UAAW,KAAK,QAAQ,GAAI,CACvC,CAGQ,uBAA8B,CACpC,GAAI,CAAC,KAAK,WAAY,OACtB,IAAMC,EAAU,KAAK,WAAW,cAA2BC,GAAgB,OAAO,EAC9ED,IAASA,EAAQ,OAAS,CAAC,KAAK,QAAQ,MAC5C,IAAME,EAAU,KAAK,WAAW,cAA2BD,GAAgB,OAAO,EAC9EC,IAASA,EAAQ,OAAS,KAAK,QAAQ,OAAS,SACpD,IAAMC,EAAQ,KAAK,WAAW,cAA2BF,GAAgB,KAAK,EAC1EE,GAAOA,EAAM,aAAa,cAAe,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,EAEnE,KAAK,QAAQ,MAAQH,GAClB,KAAK,aAAY,KAAK,WAAaI,GAAgBJ,CAAO,GAC/D,KAAK,WAAW,SAAS,GAEzB,KAAK,YAAY,WAAW,CAEhC,CAEU,SAAgB,CACxB,GAAI,CAAC,KAAK,WAAY,OACtBxB,GAAqB,KAAK,WAAY,KAAK,OAAO,EAClD,KAAK,sBAAsB,EAC3B,IAAM6B,EAAKC,GAAwB,KAAK,aAAc,KAAK,QAAS,CAClE,qBAAsB,KAAK,QAAQ,MAAQ,WAAa,KAAK,aAAa,EAAI,OAC9E,mBAAoBC,GACpB,uBAAwBC,EAC1B,CAAC,EACKC,EAA0B,CAAE,WAAY,KAAK,UAAW,EAC9DC,GAAgBD,EAASJ,CAAE,CAC7B,CACF,ECjYO,IAAMM,GAAN,cAAmCC,EAAgB,CACxD,WAAW,oBAA+B,CACxC,MAAO,CAAC,GAAGC,EAAwB,CACrC,CAEU,QAA4B,CAAE,GAAGC,EAA0B,EAC7D,eAAmD,KAEnD,oBAAsC,KACtC,wBAA+C,KAE/C,sBAAwB,IAAY,CACtC,KAAK,iBAAgB,KAAK,eAAe,KAAO,IACpD,KAAK,uBAAuB,CAC9B,EAGQ,wBAA2BC,GAAmB,CACpD,IAAMC,EAAKD,EACX,KAAK,cACH,IAAI,YAAYE,EAAgB,CAC9B,OAAQD,EAAG,OACX,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CACF,EAEQ,wBAA+B,CACrC,IAAME,EAAK,KAAK,oBAChB,KAAK,oBAAsB,KACvB,GAACA,GAAI,aAAe,OAAQA,EAAmB,OAAU,aAC5DA,EAAmB,MAAM,CAC5B,CAEA,mBAA0B,CACxB,GAAI,KAAK,WAAY,CACnB,KAAK,sBAAsB,EACvB,KAAK,QAAU,MAAQ,KAAK,qBAAuB,MACrD,KAAK,WAAW,KAAK,KAAK,EAE5B,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,EAC1B,MACF,CACA,IAAMC,EAAS,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EAE3CC,EAAQC,GAA8B,EAC5C,GAAID,EACFD,EAAO,mBAAqB,CAACC,CAAK,MAC7B,CACL,IAAME,EAAU,SAAS,cAAc,OAAO,EAC9CA,EAAQ,YAAcC,GAAkB,EACxCJ,EAAO,YAAYG,CAAO,CAC5B,CAEA,KAAK,QAAUE,GAA2B,IAAI,EAC9C,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,CAC5B,CAEQ,uBAA8B,CAC/B,KAAK,aACV,KAAK,0BAA0B,EAC/B,KAAK,wBAA0BC,GAA+B,KAAK,WAAY,CAC7E,eAAgB,IAAM,KAAK,gBAAgB,EAC3C,gBAAkBC,GAA0B,KAAK,iBAAiBA,CAAI,CACxE,CAAC,EACH,CAEA,yBAAyBC,EAAcC,EAA0BC,EAAgC,CAC/F,GAAI,CAAC,KAAK,WAAY,OACtB,IAAMC,EAAW,KAAK,QAAQ,KAQ9B,GAPA,KAAK,QAAUN,GAA2B,IAAI,GAC1CG,IAAS,kBAAoBA,IAAS,UACxC,KAAK,iBAAiB,GAEpBA,IAAS,UAAYA,IAAS,oBAChC,KAAK,yBAAyB,EAE5BA,IAAS,SAAW,KAAK,QAAQ,OAAS,YAAc,KAAK,QAAQ,OAAS,SAAU,CAC1F,IAAMI,EAAM,KAAK,QAAQ,KACrBD,IAAaC,IACf,KAAK,+BAA+B,EACpC,KAAK,SAASC,EAAyB,UAAU,KAAK,aAAcD,CAAG,CAAC,EAE5E,CACA,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,CAC5B,CAEQ,iBAAwB,CAC9B,GAAI,KAAK,QAAQ,SAAW,aAAc,CACxC,KAAK,oBACH,SAAS,yBAAyB,QAAU,SAAS,cAAgB,KACvE,KAAK,cACH,IAAI,YAAYE,GAAqB,CAAE,OAAQ,CAAC,EAAG,QAAS,GAAM,SAAU,EAAK,CAAC,CACpF,EACI,CAAC,KAAK,QAAQ,aAAe,KAAK,iBAAgB,KAAK,eAAe,KAAO,IACjF,MACF,CACA,KAAK,mBAAmB,CAC1B,CAEU,YAAsB,CAC9B,OAAO,KAAK,QAAQ,OAAS,OAAS,QAAU,KAAK,QAAQ,IAC/D,CAEU,oBAAyD,CACjE,OAAOC,GAAkB,KAAK,QAAQ,cAAc,CACtD,CAEU,cAAwB,CAChC,MAAO,EACT,CAEU,kBAA6E,CACrF,MAAO,CAAE,KAAM,KAAK,QAAQ,IAAK,CACnC,CAEU,eAAkE,CAC1E,MAAI,CAAC,KAAK,QAAQ,OAAS,CAAC,KAAK,QAAQ,eAAuB,KACzD,CAAE,MAAO,KAAK,QAAQ,MAAO,eAAgB,KAAK,QAAQ,cAAe,CAClF,CAEU,mBAA0C,CAClD,IAAMC,EACJ,KAAK,QAAQ,OAAS,SAAW,KAAK,QAAQ,OAAS,WACnD,KAAK,QAAQ,KACb,OACN,OAAOA,IAAc,OAAY,CAAE,UAAAA,CAAU,EAAI,CAAC,CACpD,CAEU,SAAgB,CACxB,GAAI,CAAC,KAAK,WAAY,OACtB,IAAMC,EAAKC,GAAyB,KAAK,aAAc,KAAK,QAAS,CACnE,qBAAsB,KAAK,QAAQ,OAAS,WAAa,KAAK,aAAa,EAAI,OAC/E,mBAAoB,KAAK,QAAQ,aAAe,OAChD,uBAAwB,KAAK,QAAQ,iBAAmB,MAC1D,CAAC,EACKC,EAA0B,CAAE,WAAY,KAAK,UAAW,EAC9DC,GAAiBD,EAASF,CAAE,CAC9B,CAEQ,qBAA4B,CAC9B,KAAK,aAAa,OAAO,IAAM,KAAK,QAAQ,OAC9C,KAAK,aAAa,QAAS,KAAK,QAAQ,KAAK,CAEjD,CAEQ,8BAAqC,CAC3C,GAAI,CAAC,KAAK,eAAgB,OAC1B,KAAK,eAAe,aAAa,SAAU,KAAK,QAAQ,OAAS,EAAE,EACnE,KAAK,eAAe,aAAa,kBAAmB,KAAK,QAAQ,gBAAkB,EAAE,EACrF,KAAK,eAAe,aAAa,QAAS,KAAK,QAAQ,KAAK,EAC5D,IAAML,EAAM,KAAK,QAAQ,OAAS,OAAS,QAAU,KAAK,QAAQ,KAClE,KAAK,eAAe,aAAa,MAAOA,CAAG,EAE3C,KAAK,eAAe,aAAa,gBAAiB,SAAS,CAC7D,CAEQ,sBAA6B,CACnC,GAAI,KAAK,QAAQ,SAAW,cAAgB,CAAC,KAAK,WAAY,OAC9D,GAAI,KAAK,QAAQ,YAAa,CACxB,KAAK,gBAAgB,cACvB,KAAK,eAAe,oBAAoBS,EAAc,KAAK,qBAAqB,EAChF,KAAK,eAAe,OAAO,EAC3B,KAAK,eAAiB,MAExB,MACF,CACA,GAAI,KAAK,gBAAgB,YAAa,CACpC,KAAK,6BAA6B,EAClC,MACF,CACA,IAAMC,EAAQ,SAAS,cAAc,sBAAsB,EAC3D,KAAK,eAAiBA,EACtB,KAAK,6BAA6B,EAClCA,EAAM,iBAAiBD,EAAc,KAAK,qBAAqB,EAC/DC,EAAM,iBAAiBxB,EAAgB,KAAK,uBAAuB,EAG/D,OAAO,SAAa,KAAe,SAAS,KAC9C,SAAS,KAAK,YAAYwB,CAAK,EAE/B,KAAK,WAAW,YAAYA,CAAK,CAErC,CAES,sBAA6B,CACpC,KAAK,0BAA0B,EAC/B,KAAK,wBAA0B,KAC3B,KAAK,gBAAgB,cACvB,KAAK,eAAe,oBAAoBD,EAAc,KAAK,qBAAqB,EAChF,KAAK,eAAe,oBAAoBvB,EAAgB,KAAK,uBAAuB,EACpF,KAAK,eAAe,OAAO,EAC3B,KAAK,eAAiB,MAExB,MAAM,qBAAqB,CAC7B,CACF,ECpOO,IAAMyB,GAAa,QAEbC,GAAqB,iBAErBC,GAA2B,uBAEpC,OAAO,eAAmB,KAAe,CAAC,eAAe,IAAID,EAAkB,GACjF,eAAe,OAAOA,GAAoBE,EAAoB,EAE5D,OAAO,eAAmB,KAAe,CAAC,eAAe,IAAID,EAAwB,GACvF,eAAe,OAAOA,GAA0BE,EAAyB","names":["resolveEnvState","payload","tabToReadyState","tab","getNextState","currentState","event","nextReady","INITIAL_UI_STATE","UI_STATES","UI_MODES","THEME_KINDS","TAB_KINDS","MODAL_DISPLAY_MODES","FALLBACK_TYPES","BUTTON_ACTIONS","BUTTON_VARIANTS","MODAL_VARIANTS","RECOMMENDED_FLOWS","isClientStatus","value","v","isOneOf","allowed","isUIState","UI_STATES","ensureUIState","INITIAL_UI_STATE","isUIMode","UI_MODES","isThemeKind","THEME_KINDS","isTabKind","TAB_KINDS","isModalDisplayMode","MODAL_DISPLAY_MODES","isButtonAction","BUTTON_ACTIONS","isButtonVariant","BUTTON_VARIANTS","isModalVariant","MODAL_VARIANTS","isEnvResolvedPayload","o","RECOMMENDED_FLOWS","FALLBACK_TYPES","isFSMEvent","t","DEFAULT_UI_MODE","DEFAULT_THEME","DEFAULT_MODAL_DISPLAY_MODE","DEFAULT_TAB","DEFAULT_TAB_LABELS","DEFAULT_BUTTON_ACTION","DEFAULT_BUTTON_VARIANT","DEFAULT_MODAL_VARIANT","DEFAULT_PARSED_ATTRIBUTES","DEFAULT_PARSED_MODAL_ATTRIBUTES","isParsedAttributes","value","o","isUIMode","isThemeKind","isButtonAction","isButtonVariant","isTabLabels","isParsedModalAttributes","isModalDisplayMode","isTabKind","isModalVariant","defaultParsedAttributes","DEFAULT_PARSED_ATTRIBUTES","defaultParsedModalAttributes","DEFAULT_PARSED_MODAL_ATTRIBUTES","ensureParsedAttributes","ensureParsedModalAttributes","applyTransition","currentState","event","state","ensureUIState","isFSMEvent","getNextState","buildAuthButtonViewModel","state","parsed","options","buildAuthModalViewModel","hasGetClientStatus","x","runEnvEval","params","INITIAL_UI_STATE","envStatusPort","currentState","ensureUIState","mode","isUIMode","isMobileOverride","fallbackType","stateEvaluating","applyTransition","status","rawStatus","isClientStatus","effectiveRecommendedFlow","payload","canStartAuth","currentState","applyTransition","applyStartAuthAndInvokeCore","mode","coreAuthPort","options","nextState","FALLBACK_EVENT","applyFallbackTransition","fallbackKind","authUiApplicationService","params","runEnvEval","tab","parseString","value","parseOptionalString","s","parseBoolean","v","parseOptionalBoolean","parseEnum","allowed","fallback","normalized","parseOptionalEnum","parseAttributesFromElement","element","raw","parseString","parseEnum","UI_MODES","DEFAULT_UI_MODE","parseOptionalString","THEME_KINDS","DEFAULT_THEME","BUTTON_ACTIONS","DEFAULT_BUTTON_ACTION","parseBoolean","BUTTON_VARIANTS","DEFAULT_BUTTON_VARIANT","ensureParsedAttributes","MELLON_ROOT_ID","MELLON_BTN_SELECTOR","MELLON_FALLBACK_BTN_SELECTOR","MELLON_ACTION_FALLBACK_EMAIL","MELLON_ACTION_FALLBACK_QR","PRIMARY_BUTTON_LABEL","MODAL_PASSKEY_BUTTON_LABEL","TRIGGER_ARIA_LABEL","MODAL_PASSKEY_ARIA_LABEL","SVG_NS","WRAPPER_CLASS","OVERLAY_CLASS","PANEL_CLASS","TABS_CLASS","CONTENT_WRAPPER_CLASS","SLOT_CROSS_DEVICE","SLOT_FALLBACK_CTA","MELLON_DIALOG_TITLE_ID","MELLON_DIALOG_DESC_ID","DIALOG_TITLE_TEXT","DIALOG_TITLE_WITH_APP","appName","DIALOG_DESC_TEXT","MODAL_SEPARATOR_TEXT","CROSS_DEVICE_WRAP_CLASS","MODAL_SEPARATOR_CLASS","MODAL_CLOSE_BUTTON_CLASS","MODAL_CLOSE_BUTTON_ARIA_LABEL","CROSS_DEVICE_CTA_TEXT","CROSS_DEVICE_CTA_CLASS","CROSS_DEVICE_QR_BUTTON_ARIA_LABEL","MELLON_QR_SKELETON_CLASS","MELLON_QR_ERROR_CLASS","MELLON_QR_SLOT_WRAP_CLASS","QR_SKELETON_TEXT","QR_TIMEOUT_ERROR_TEXT","createFingerprintIconSVG","svg","SVG_NS","path1","path2","path3","createPrimaryButtonDefault","disabled","label","PRIMARY_BUTTON_LABEL","ariaLabel","TRIGGER_ARIA_LABEL","btn","createPrimaryButtonPill","iconCircle","getPrimaryButtonBuilder","variant","getPrimaryButtonOptions","options","buildPrimaryButtonForReadyState","ensureRoot","surface","shadowRoot","root","MELLON_ROOT_ID","createParagraph","className","text","p","createFallbackButton","action","FALLBACK_BUTTON_CONFIG","MELLON_ACTION_FALLBACK_EMAIL","MELLON_ACTION_FALLBACK_QR","buildFallbackUI","state","wrap","msg","buildContentForState","fragment","render","safeState","ensureUIState","content","viewModelToRenderOptions","vm","modalViewModelToRenderOptions","renderAuthButton","surface","render","renderAuthModal","MELLON_MODAL_TABS_SELECTOR","TAB_ATTR","FOCUSABLE_SELECTOR","MELLON_MODAL_CLOSE_SELECTOR","fallbackActionToType","action","MELLON_ACTION_FALLBACK_EMAIL","MELLON_ACTION_FALLBACK_QR","registerAuthButtonInteractions","root","config","handler","e","target","fallbackBtn","MELLON_FALLBACK_BTN_SELECTOR","MELLON_BTN_SELECTOR","registerAuthModalInteractions","MELLON_MODAL_CLOSE_SELECTOR","MELLON_MODAL_TABS_SELECTOR","tab","TAB_ATTR","overlay","OVERLAY_CLASS","BASE_STYLES","SUPPORTS_ADOPTED_STYLESHEETS","createConstructableStylesheet","sheet","getStylesFallback","MODAL_EXTRA_STYLES","getModalStylesFallback","createModalConstructableStylesheet","ok","value","err","error","TryMellonError","_TryMellonError","code","message","details","DEFAULT_MESSAGES","createError","isTryMellonError","error","createNotSupportedError","createInvalidArgumentError","field","reason","createError","createCredentialError","operation","createEncodingError","type","validateUrl","url","fieldName","urlObj","createInvalidArgumentError","error","isTryMellonError","validateRange","value","min","max","validateBase64Url","s","DOM_EXCEPTION_ERROR_MAP","mapBackendErrorCodeToTryMellon","backendCode","normalized","mapWebAuthnError","name","message","errorCode","createError","isObject","value","isString","isNumber","isBoolean","isArray","validationError","message","details","err","createError","required","obj","key","validateChallengeRP","rp","data","isObject","isString","validationError","ok","validateChallengeUser","user","validatePubKeyCredParams","params","isArray","item","isNumber","validateUserEntity","userId","required","externalUserId","email","metadata","validateRegisterStartResponse","data","isObject","validationError","session_id","required","isString","challenge","rpResult","validateChallengeRP","userResult","validateChallengeUser","challengeStr","pubKeyCredParamsResult","validatePubKeyCredParams","timeout","isNumber","excludeCredentials","isArray","c","authenticatorSelection","ok","validateAuthStartResponse","ch","rpId","allowCredentials","userVerification","validateRegisterFinishResponse","credential_id","status","session_token","user","validateUserEntity","redirect_url","validateAuthFinishResponse","authenticated","signals","isBoolean","validateSessionValidateResponse","data","isObject","validationError","valid","required","user_id","external_user_id","tenant_id","app_id","isBoolean","isString","ok","validateEmailVerifyResponse","data","isObject","validationError","raw","isString","redirect_url","ok","ONBOARDING_STATUSES","REGISTER_PASSKEY_STATUSES","validateOnboardingStartResponse","data","isObject","validationError","session_id","required","onboarding_url","expires_in","isString","isNumber","ok","validateOnboardingStatusResponse","status","validateOnboardingRegisterResponse","challenge","parsedChallenge","chResult","validateOnboardingChallenge","rp","user","challengeStr","pubKeyCredParams","isArray","item","validateOnboardingRegisterPasskeyResponse","user_id","tenant_id","validateOnboardingCompleteResponse","session_token","validateCrossDeviceVerifyResponse","data","ok","isObject","validationError","isCreationOptionsShape","opts","o","isRequestOptionsShape","validateCrossDeviceInitResponse","payload","session_id","qr_url","expires_at","polling_token","isString","result","validateCrossDeviceStatusResponse","status","user_id","session_token","redirect_url","validateCrossDeviceContextResponse","rawType","type","options","MAX_CONTEXT_LENGTH","approval_context","optionalContextString","application_name","extra","value","maxLength","validateRecoveryVerifyResponse","data","isObject","validationError","challenge","required","recovery_session_id","isString","ok","validateRecoveryCompleteResponse","status","session_token","user","credential_id","user_id","redirect_url","userObj","ApiClient","httpClient","baseUrl","defaultHeaders","extra","path","body","validate","url","result","err","headers","request","validateRegisterStartResponse","validateAuthStartResponse","validateRegisterFinishResponse","validateAuthFinishResponse","sessionToken","validateSessionValidateResponse","options","ok","validateEmailVerifyResponse","validateOnboardingStartResponse","sessionId","validateOnboardingStatusResponse","validateOnboardingRegisterResponse","validateOnboardingRegisterPasskeyResponse","validateOnboardingCompleteResponse","validateCrossDeviceInitResponse","trimmed","pollingToken","validateCrossDeviceStatusResponse","validateCrossDeviceContextResponse","validateCrossDeviceVerifyResponse","externalUserId","otp","validateRecoveryVerifyResponse","recoverySessionId","credential","validateRecoveryCompleteResponse","isEnvelopeSuccess","data","isEnvelopeError","o","err","parseHttpErrorBody","errorData","statusText","mapBackendErrorCodeToTryMellon","body","errObj","message","rawCode","code","RETRY_DELAY_CAP_MS","generateRequestId","getRetryDelayMs","attempt","baseMs","delay","shouldRetryOnStatus","method","status","FetchHttpClient","timeoutMs","maxRetries","retryDelayMs","logger","url","headers","config","requestId","lastError","controller","timeoutId","response","errResult","createError","resolve","ok","raw","error","base64UrlEncode","buf","bytes","binary","b","createEncodingError","base64UrlDecode","s","base64","padding","padded","c","base64UrlDecodeToArrayBuffer","buffer","isValidCredentialResponse","response","serializeCredentialForRegister","credential","createError","clientDataJSON","attestationObject","base64UrlEncode","serializeCredentialForAuth","authenticatorData","signature","userHandle","isWebAuthnSupported","isPlatformAuthenticatorAvailable","getClientStatus","isPasskeySupported","platformAuthenticatorAvailable","validateCredentialStructure","credential","operation","createCredentialError","invokeCeremony","context","operation","eventEmitter","start","createOptions","invoke","finish","isWebAuthnSupported","error","createNotSupportedError","err","startResult","optionsResult","credential","createInvalidArgumentError","validateCredentialStructure","e","mapWebAuthnError","finishResult","ok","tryMellonError","createRegistrationOptions","serverChallengePayload","authenticatorType","validateBase64Url","challengeBuffer","base64UrlDecodeToArrayBuffer","userIdBuffer","authenticatorSelection","publicKey","cred","ok","e","err","mapWebAuthnError","createAuthenticationOptions","challenge","mediation","registerPasskey","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","result","invokeCeremony","startResult","ceremonyOptions","opts","credential","finishResult","serializeCredentialForRegister","authenticatePasskey","hasUserId","serializeCredentialForAuth","waitWithAbort","intervalMs","signal","resolve","onAbort","cleanup","timeout","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","OnboardingManager","apiClient","options","signal","startResult","err","session_id","attempt","createError","waitWithAbort","statusResult","status","onboarding_url","registerInfoResult","registerInfo","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","registerPasskeyResult","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","CrossDeviceManager","apiClient","options","sessionId","signal","pollingToken","err","createError","attempt","statusResult","redirectUrl","ok","waitWithAbort","contextResult","context","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","requestOptionsResult","createAuthenticationOptions","serializeCredentialForAuth","EventEmitter","event","handler","handlersSet","payload","DEFAULT_API_BASE_URL","DEFAULT_TELEMETRY_ENDPOINT","SANDBOX_SESSION_TOKEN","createDefaultTelemetrySender","endpoint","payload","body","buildTelemetryPayload","event","latencyMs","AuthService","apiClient","eventEmitter","sandbox","sandboxToken","telemetrySender","operation","options","externalUserId","externalId","ok","result","start","registerPasskey","buildTelemetryPayload","authenticatePasskey","recoverAccount","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","err","result","invokeCeremony","startResult","createRegistrationOptions","ceremonyOptions","credential","finishResult","serializeCredentialForRegister","credential_id","status","session_token","userPayload","redirect_url","ok","RecoveryService","apiClient","eventEmitter","options","recoverAccount","TryMellon","_TryMellon","config","appId","publishableKey","err","createInvalidArgumentError","apiBaseUrl","DEFAULT_API_BASE_URL","validateUrl","timeoutMs","validateRange","ok","e","isTryMellonError","SANDBOX_SESSION_TOKEN","maxRetries","retryDelayMs","httpClient","FetchHttpClient","originHeader","defaultHeaders","ApiClient","EventEmitter","createDefaultTelemetrySender","DEFAULT_TELEMETRY_ENDPOINT","AuthService","RecoveryService","OnboardingManager","CrossDeviceManager","isWebAuthnSupported","options","sessionToken","getClientStatus","event","handler","result","sessionId","signal","pollingToken","createCoreForUI","config","result","TryMellon","isCoreAuthPort","candidate","maybe","hasAuthenticate","hasRegister","hasOn","toCoreAuthOptions","externalUserId","MELLON_OPEN","MELLON_OPEN_REQUEST","MELLON_CLOSE","MELLON_SUCCESS","MELLON_ERROR","MELLON_START","MELLON_CANCELLED","MELLON_FALLBACK","MELLON_TAB_CHANGE","dispatchCustomEvent","host","name","detail","options","toPublicOperation","op","mapSuccessUser","raw","o","userId","result","isCoreStartPayload","isCoreSuccessPayload","isCoreErrorPayload","isCoreCancelledPayload","eventBridgeAdapter","core","unsubscribes","lastOperation","successEmittedThisCeremony","offStart","payload","MELLON_START","offSuccess","mappedUser","MELLON_SUCCESS","offError","code","MELLON_ERROR","offCancelled","MELLON_CANCELLED","off","mapClientStatusToUI","status","createEnvStatusAdapter","getClientStatus","createEnvStatusPortFromCore","core","candidate","getStatus","createMellonOpenEvent","detail","MELLON_OPEN","createMellonCloseEvent","MELLON_CLOSE","createMellonCancelledEvent","MELLON_CANCELLED","createMellonFallbackEvent","MELLON_FALLBACK","createMellonTabChangeEvent","MELLON_TAB_CHANGE","AuthController","INITIAL_UI_STATE","next","tab","nonce","detail","authUiApplicationService","core","options","canStartAuth","params","requestId","nextState","state","AuthElementBase","AuthController","next","detail","createMellonCancelledEvent","core","isCoreAuthPort","eventBridgeAdapter","e","type","createMellonFallbackEvent","params","createEnvStatusPortFromCore","nextState","config","createCoreForUI","nextConfig","state","parseTabLabels","value","DEFAULT_TAB_LABELS","parts","p","register","login","parseModalAttributesFromElement","element","raw","parseBoolean","parseEnum","MODAL_DISPLAY_MODES","DEFAULT_MODAL_DISPLAY_MODE","TAB_KINDS","DEFAULT_TAB","THEME_KINDS","DEFAULT_THEME","parseOptionalString","parseOptionalBoolean","parseOptionalEnum","FALLBACK_TYPES","parseString","MODAL_VARIANTS","DEFAULT_MODAL_VARIANT","ensureParsedModalAttributes","ensureWrapper","shadowRoot","wrapper","WRAPPER_CLASS","ensureOverlay","overlay","OVERLAY_CLASS","ensurePanel","panel","PANEL_CLASS","setPanelDialogAria","mode","MELLON_DIALOG_TITLE_ID","MELLON_DIALOG_DESC_ID","ensureDialogTitleAndDescription","parsed","titleEl","titleText","DIALOG_TITLE_WITH_APP","DIALOG_TITLE_TEXT","descEl","DIALOG_DESC_TEXT","ensureCloseButton","btn","MODAL_CLOSE_BUTTON_CLASS","MODAL_CLOSE_BUTTON_ARIA_LABEL","ensureTabs","tabLabels","tabs","TABS_CLASS","btnRegister","btnLogin","afterDesc","ensureModalContentWrapper","CONTENT_WRAPPER_CLASS","afterTabs","createQrIconSVG","svg","SVG_NS","path","createCrossDeviceDefaultContent","frag","wrap","CROSS_DEVICE_CTA_CLASS","p","CROSS_DEVICE_CTA_TEXT","MELLON_ACTION_FALLBACK_QR","CROSS_DEVICE_QR_BUTTON_ARIA_LABEL","createQrSkeletonNode","el","MELLON_QR_SKELETON_CLASS","label","QR_SKELETON_TEXT","dots","createQrErrorNode","MELLON_QR_ERROR_CLASS","QR_TIMEOUT_ERROR_TEXT","ensureCrossDeviceSlot","CROSS_DEVICE_WRAP_CLASS","slotWrap","MELLON_QR_SLOT_WRAP_CLASS","slot","SLOT_CROSS_DEVICE","created","ensureSeparator","MODAL_SEPARATOR_CLASS","sep","span","MODAL_SEPARATOR_TEXT","ensureDefaultSlotWithRoot","root","MELLON_ROOT_ID","ensureFallbackSlot","SLOT_FALLBACK_CTA","syncTabAriaSelected","activeTab","reg","log","ensureModalStructure","isFocusableCandidate","el","getFocusables","container","FOCUSABLE_SELECTOR","createFocusTrap","previousActiveElement","keydownBound","isActive","handleKeydown","e","focusables","current","currentIndex","lastIndex","nextIndex","next","activate","first","deactivate","doc","toRestore","body","prevTabindex","MODAL_WRAPPER_CLASS","MODAL_OVERLAY_CLASS","MODAL_PANEL_CLASS","OBSERVED_ATTRIBUTES_AUTH","OBSERVED_ATTRIBUTES_MODAL","MODAL_SELECTORS","MELLON_CLOSE_REASON_DEFAULT","CLOSE_REASON_BY_STATE","closeDetailFromState","state","MELLON_CLOSE_REASON_DEFAULT","TryMellonAuthModalElement","AuthElementBase","OBSERVED_ATTRIBUTES_MODAL","parseModalAttributesFromElement","e","shadow","sheet","createModalConstructableStylesheet","styleEl","getModalStylesFallback","ensureModalStructure","registerAuthModalInteractions","tab","createMellonTabChangeEvent","type","name","oldValue","_newValue","detail","createMellonOpenEvent","authUiApplicationService","root","wrap","CROSS_DEVICE_WRAP_CLASS","slot","SLOT_CROSS_DEVICE","ms","wrapElement","onSlotChange","w","createMellonCloseEvent","value","externalUserId","explicit","wrapper","MODAL_SELECTORS","overlay","panel","createFocusTrap","vm","buildAuthModalViewModel","MODAL_PASSKEY_BUTTON_LABEL","MODAL_PASSKEY_ARIA_LABEL","surface","renderAuthModal","TryMellonAuthElement","AuthElementBase","OBSERVED_ATTRIBUTES_AUTH","DEFAULT_PARSED_ATTRIBUTES","e","ev","MELLON_SUCCESS","el","shadow","sheet","createConstructableStylesheet","styleEl","getStylesFallback","parseAttributesFromElement","registerAuthButtonInteractions","type","name","_oldValue","_newValue","prevMode","tab","authUiApplicationService","MELLON_OPEN_REQUEST","toCoreAuthOptions","operation","vm","buildAuthButtonViewModel","surface","renderAuthButton","MELLON_CLOSE","modal","UI_VERSION","TRYMELLON_AUTH_TAG","TRYMELLON_AUTH_MODAL_TAG","TryMellonAuthElement","TryMellonAuthModalElement"]}
|